CAD.js 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008
  1. // 发布订阅,事件模型
  2. var Event = (function () {
  3. var _default = 'default';
  4. var _shift = Array.prototype.shift;
  5. var _unshift = Array.prototype.unshift;
  6. function createEvent() {
  7. var namespaceCache = {}
  8. function _listen(cache, key, fn) {
  9. if (cache[key]) {
  10. cache[key].push(fn)
  11. } else {
  12. cache[key] = [fn]
  13. }
  14. }
  15. function _trigger() {
  16. var args = arguments
  17. return new Promise(function (resolve) {
  18. setTimeout(function () {
  19. var cache = _shift.call(args);
  20. var key = _shift.call(args);
  21. var stack = cache[key]
  22. if (!stack || stack.length === 0) return;
  23. stack.forEach(function (fn) {
  24. fn.apply(this, args)
  25. })
  26. resolve(stack);
  27. }, 100)
  28. })
  29. }
  30. function _remove(cache, key, fn) {
  31. var stack = cache[key]
  32. if (!stack || stack.length === 0) return
  33. if (fn) {
  34. for (var i = stack.length; i >= 0; i--) {
  35. if (stack[i] === fn) {
  36. stack.splice(i, 1)
  37. }
  38. }
  39. } else {
  40. stack.length = 0
  41. }
  42. }
  43. function _create(namespace) {
  44. namespace = namespace || _default
  45. if (namespaceCache[namespace]) {
  46. return namespaceCache[namespace]
  47. }
  48. var cache = {}
  49. var ret = {
  50. listen: function (key, fn) {
  51. _listen(cache, key, fn)
  52. },
  53. once: function (key, fn) {
  54. fn.__once = true
  55. _listen(cache, key, fn)
  56. },
  57. remove: function (key, fn) {
  58. _remove(cache, key, fn)
  59. },
  60. trigger: function () {
  61. _unshift.call(arguments, cache)
  62. _trigger.apply(this, arguments).then(function (stack) {
  63. if (stack) {
  64. for (var i = stack.length; i >= 0; i--) {
  65. if (stack[i] && stack[i].__once) {
  66. stack.splice(i, 1)
  67. }
  68. }
  69. }
  70. })
  71. }
  72. }
  73. namespaceCache[namespace] = ret;
  74. return ret
  75. }
  76. return {
  77. create: _create,
  78. once: function () {
  79. this.create().once.apply(this, arguments)
  80. },
  81. listen: function () {
  82. this.create().listen.apply(this, arguments)
  83. },
  84. remove: function () {
  85. this.create().remove.apply(this, arguments)
  86. },
  87. trigger: function () {
  88. this.create().trigger.apply(this, arguments)
  89. }
  90. }
  91. }
  92. return createEvent()
  93. })();
  94. var grendCAD = (function grentWall() {
  95. var util = {
  96. /**
  97. * 计算直线向量
  98. * @param {*} line
  99. */
  100. lineVector(line) {
  101. var cpoint = {
  102. x: line.points[1].x - line.points[0].x,
  103. y: line.points[1].y - line.points[0].y
  104. }
  105. var xd = Math.abs(cpoint.x / 1)
  106. var yd = Math.abs(cpoint.y / 1)
  107. var js = xd > yd ? xd : yd
  108. var verctor = {
  109. x: cpoint.x / js,
  110. y: cpoint.y / js,
  111. }
  112. return verctor
  113. },
  114. /**
  115. * 获取向量获取固定长度时倍数
  116. * @param {*} v 向量
  117. * @param {*} width 长度
  118. */
  119. vectorWidth (v, w) {
  120. return Math.sqrt(Math.pow(w, 2) / (Math.pow(v.x, 2) + Math.pow(v.y, 2)))
  121. },
  122. /**
  123. * 计算直线与X轴夹角
  124. * @param {*} line1
  125. */
  126. lineAngle(line1) {
  127. var height = line1[0].y - line1[1].y,
  128. width = line1[0].x - line1[1].x;
  129. if (width == 0) {
  130. // 如果和y轴平行,角度为90或270
  131. return line1[0].y >= line1[1].y ? 90 : 270;
  132. } else {
  133. var tan = Math.atan(height / width),
  134. angle = tan * 180 / Math.PI;
  135. return tan > 0 ? (line1[0].x > line1[1].x ? angle : angle + 180) : (line1[0].x > line1[1].x ? angle + 360 : angle + 180);
  136. }
  137. },
  138. /**
  139. * 计算直线的长度
  140. * @param {*} line
  141. */
  142. lineDistance(line) {
  143. return Math.sqrt(Math.pow(line[0].x - line[1].x, 2) + Math.pow(line[0].y - line[1].y, 2))
  144. },
  145. isInfinity(num) {
  146. return num === Infinity || num === -Infinity
  147. },
  148. /**
  149. * 获取一组坐标的XY坐标区间
  150. * @param {*} points
  151. */
  152. getSection(points) {
  153. var ret = {
  154. minx: points[0].x,
  155. maxx: points[0].x,
  156. miny: points[0].y,
  157. maxy: points[0].y
  158. }
  159. points.forEach(function (point) {
  160. if (ret.minx > point.x) {
  161. ret.minx = point.x
  162. }
  163. if (ret.maxx < point.x) {
  164. ret.maxx = point.x
  165. }
  166. if (ret.miny > point.y) {
  167. ret.miny = point.y
  168. }
  169. if (ret.maxy < point.y) {
  170. ret.maxy = point.y
  171. }
  172. })
  173. return ret
  174. },
  175. /**
  176. * 计算垂直向量
  177. * @param {向量} arr
  178. */
  179. verticalLine(line) {
  180. var arr = [
  181. line.points[1].x - line.points[0].x,
  182. line.points[1].y - line.points[0].y
  183. ]
  184. if (arr.length !== 0) {
  185. var x, y;
  186. y = Math.sqrt(1 / ((arr[1] * arr[1]) / (arr[0] * arr[0]) + 1));
  187. x = Math.sqrt(1 - y * y);
  188. return [x, y];
  189. }
  190. return [];
  191. },
  192. /**
  193. * 将所有坐标转化为指定范围之间的值,但是保持比例不变
  194. * @param {*} points 要转化的坐标
  195. * @param {*} section 指定范围
  196. * @returns Array 转化后的值
  197. */
  198. tranProp(points, section) {
  199. var args = util.getSection(points)
  200. var xlen = args.maxx - args.minx
  201. var ylen = args.maxy - args.miny
  202. var prop = xlen > ylen ? xlen : ylen
  203. var offsetX = -(args.minx + xlen / 2)
  204. var offsetY = -(args.miny + ylen / 2)
  205. var range = section[1] - section[0]
  206. return {
  207. offset: {
  208. x: offsetX,
  209. y: offsetY
  210. },
  211. prop,
  212. range: range
  213. }
  214. },
  215. /**
  216. * 将屏幕转化为真实坐标
  217. * @param {*} point
  218. * @param {*} section
  219. */
  220. tranPoint(point, section) {
  221. return {
  222. x: point.x + section.minx,
  223. y: point.y + section.miny
  224. }
  225. },
  226. /**
  227. * 点到直线的距离
  228. */
  229. pointLineDis(line, point) {
  230. var dis = 0
  231. var s1 = line[1].x - line[0].x
  232. var s2 = point.x - line[0].x
  233. var s3 = point.x - line[1].x
  234. var k1 = line[1].y - line[0].y
  235. var k2 = point.y - line[0].y
  236. var k3 = point.y - line[1].y
  237. var cross = s1 * s2 + k1 * k2;
  238. var d2 = s1 * s1 + k1 * k1;
  239. if (cross <= 0) {
  240. dis = Math.sqrt(s2 * s2 + k2 * k2);
  241. } else if (cross >= d2) {
  242. dis = Math.sqrt(s3 * s3 + k3 * k3);
  243. } else {
  244. var r = cross / d2;
  245. var px = line[0].x + s1 * r;
  246. var py = line[0].y + k1 * r;
  247. dis = Math.sqrt((point.x - px) * (point.x - px) + (py - point.y) * (py - point.y));
  248. }
  249. return dis
  250. },
  251. /**
  252. * 判断点是否在线上
  253. * @param {*} point 要判断的点
  254. * @param {*} line 线段
  255. * @param {*} width 线宽
  256. */
  257. isContainPoint(point, line, width) {
  258. var dis = util.pointLineDis(line, point)
  259. var max = width / 2
  260. var min = 0 - max
  261. return dis >= min && dis <= max
  262. },
  263. /**
  264. * 判断两条线段是否相交
  265. * @param {*} line1
  266. * @param {*} line2
  267. */
  268. isLineIntersect(line1, line2) {
  269. var a1 = line1[1].y - line1[0].y;
  270. var b1 = line1[0].x - line1[1].x;
  271. var c1 = a1 * line1[0].x + b1 * line1[0].y;
  272. //转换成一般式: Ax+By = C
  273. var a2 = line2[1].y - line2[0].y;
  274. var b2 = line2[0].x - line2[1].x;
  275. var c2 = a2 * line2[0].x + b2 * line2[0].y;
  276. // 计算交点
  277. var d = a1 * b2 - a2 * b1;
  278. // 当d==0时,两线平行
  279. if (d == 0) {
  280. return false;
  281. } else {
  282. var x = (b2 * c1 - b1 * c2) / d;
  283. var y = (a1 * c2 - a2 * c1) / d;
  284. // 检测交点是否在两条线段上
  285. if ((isInBetween(line1[0].x, x, line1[1].x) || isInBetween(line1[0].y, y, line1[1].y)) &&
  286. (isInBetween(line2[0].x, x, line2[1].x) || isInBetween(line2[0].y, y, line2[1].y))) {
  287. return true;
  288. }
  289. }
  290. function isInBetween(a, b, c) {
  291. // 如果b几乎等于a或c,返回false.为了避免浮点运行时两值几乎相等,但存在相差0.00000...0001的这种情况出现使用下面方式进行避免
  292. if (Math.abs(a - b) < 0.000001 || Math.abs(b - c) < 0.000001) {
  293. return false;
  294. }
  295. return (a <= b && b <= c) || (c <= b && b <= a);
  296. }
  297. return false;
  298. },
  299. /**
  300. * 判断两个点是否相同
  301. * @param {*} point1
  302. * @param {*} poin2
  303. */
  304. equalPoint(point1, poin2) {
  305. return point1.x === poin2.x && point1.y === poin2.y
  306. },
  307. /**
  308. * 判断两个面是否相交,
  309. * @param {*} face1
  310. * @param {*} face2
  311. */
  312. isFaceIntersect(face1, face2) {
  313. for (var i = 0; i < face1.length; i++) {
  314. var next = i + 1 === face1.length ? 0 : i + 1
  315. var line1 = [face1[i], face1[next]]
  316. for (var j = 0; j < face2.length; j++) {
  317. var next = j + 1 === face2.length ? 0 : j + 1
  318. var line2 = [face2[j], face2[next]]
  319. var isIntersect1 = util.isLineIntersect(line2, line1)
  320. var isIntersect2 = util.isLineIntersect(line1, line2)
  321. if (isIntersect1 && isIntersect2) {
  322. return true
  323. }
  324. }
  325. }
  326. },
  327. /**
  328. * 判断一个点是否在面上
  329. * @param {*} face1
  330. * @param {*} face2
  331. */
  332. pointInside(point, face) {
  333. var inside = false;
  334. var x = point.x,
  335. y = point.y;
  336. for (var i = 0, j = face.length - 1; i < face.length; j = i++) {
  337. var xi = face[i].x,
  338. yi = face[i].y;
  339. var xj = face[j].x,
  340. yj = face[j].y;
  341. if (((yi > y) != (yj > y)) &&
  342. (x < (xj - xi) * (y - yi) / (yj - yi) + xi)) {
  343. inside = !inside;
  344. }
  345. }
  346. return inside;
  347. }
  348. }
  349. /**
  350. * 获取一个元素在指定父元素或文档中的位置
  351. */
  352. function getPosition(dom, parent) {
  353. var ret = {
  354. x: 0,
  355. y: 0
  356. }
  357. while (dom && dom !== parent && dom !== document.documentElement) {
  358. ret.x += dom.offsetLeft
  359. ret.y += dom.offsetTop
  360. dom = dom.offsetParent
  361. }
  362. return ret
  363. }
  364. /**
  365. * 添加拖拽事件
  366. */
  367. function addMouseEvent(dom, event) {
  368. dom.addEventListener('mousemove', function(ev) {
  369. event.move({x: ev.pageX, y: ev.pageY})
  370. }, {
  371. passive: false
  372. })
  373. dom.addEventListener('mousedown', function downHandle(ev) {
  374. var prevPoint = {
  375. x: ev.pageX,
  376. y: ev.pageY
  377. }
  378. var con = event.down(prevPoint)
  379. if (!con) return;
  380. document.documentElement.addEventListener('mousemove', moveHandle, {
  381. passive: false
  382. })
  383. document.documentElement.addEventListener('mouseup', endHandle, {
  384. passive: false
  385. })
  386. function moveHandle(ev) {
  387. event.move({
  388. x: ev.pageX,
  389. y: ev.pageY
  390. }, prevPoint)
  391. prevPoint = {
  392. x: ev.pageX,
  393. y: ev.pageY
  394. }
  395. }
  396. function endHandle(ev) {
  397. document.documentElement.removeEventListener('mousemove', moveHandle, {
  398. passive: false
  399. })
  400. document.documentElement.removeEventListener('mouseup', endHandle, {
  401. passive: false
  402. })
  403. event.up()
  404. }
  405. }, false)
  406. }
  407. /**
  408. * 包含对象
  409. */
  410. function inherit(origin, target) {
  411. for (var key in target) {
  412. origin.prototype[key] = target[key]
  413. }
  414. }
  415. /**
  416. * 墙面跟相机
  417. */
  418. var Wall = (function Wall() {
  419. /**
  420. * 获取面的所有点
  421. * @param {*} face
  422. */
  423. function getFacePoints(face) {
  424. var start = face[0]
  425. var ret = []
  426. var iteration = start
  427. do {
  428. ret.push(iteration.points[0])
  429. iteration = face.find(function (item) {
  430. return item.id === iteration.linkedLineID[1]
  431. })
  432. } while (start !== iteration)
  433. return ret
  434. }
  435. function Wall(data, cameras) {
  436. this.lineWidth = 4
  437. this.cameras = cameras
  438. this.stateStack = []
  439. var faces = {}
  440. data.forEach(function (line) {
  441. if (faces[line.roomIndex]) {
  442. faces[line.roomIndex].push(line)
  443. } else {
  444. faces[line.roomIndex] = [line]
  445. }
  446. })
  447. this.faces = faces
  448. // this.regEvent()
  449. // this.init()
  450. // this.draw()
  451. }
  452. Wall.prototype._down = function (point, renderer) {
  453. this.preservationState()
  454. var rets = []
  455. for (var key in this.faces) {
  456. var face = this.faces[key]
  457. for (var i = 0, line; line = face[i]; i++) {
  458. var p1d = util.lineDistance([point, line.points[0]]) < 0.2
  459. var p2d = util.lineDistance([point, line.points[1]]) < 0.2
  460. if (p1d || p2d) {
  461. var cpoint = p1d ? line.points[0] : line.points[1]
  462. var lline = face.find(function(fline) {
  463. return fline !== line && (util.equalPoint(fline.points[0], cpoint) || util.equalPoint(fline.points[1], cpoint))
  464. })
  465. rets.push({
  466. face: face,
  467. line: line,
  468. dire: util.verticalLine(line)
  469. }, {
  470. face: face,
  471. line: lline,
  472. dire: util.verticalLine(lline)
  473. })
  474. rets.horn = true
  475. break
  476. } else if (util.isContainPoint(point, line.points, (this.lineWidth + 4) / renderer.status.prop)) {
  477. rets.push({
  478. face: face,
  479. line: line,
  480. dire: util.verticalLine(line)
  481. })
  482. }
  483. }
  484. if (i !== face.length) break;
  485. }
  486. return rets.length > 0 ? rets : null
  487. }
  488. Wall.prototype.updateLine = function (line, x, y) {
  489. if (!x && !y) return;
  490. var face
  491. for (var key in this.faces) {
  492. var index = this.faces[key].findIndex(function (item) {
  493. return item === line
  494. })
  495. if (~index) {
  496. face = this.faces[key]
  497. break
  498. }
  499. }
  500. if (!face) return
  501. var prevLine = face.find(function (cLine) {
  502. return line.linkedLineID[0] === cLine.id
  503. })
  504. var lastLine = face.find(function (cLine) {
  505. return line.linkedLineID[1] === cLine.id
  506. })
  507. var prevK = (prevLine.points[1].y - prevLine.points[0].y) / (prevLine.points[1].x - prevLine.points[0].x)
  508. var lastK = (lastLine.points[1].y - lastLine.points[0].y) / (lastLine.points[1].x - lastLine.points[0].x)
  509. var prevX, prevY, lastX, lastY
  510. if (x) {
  511. prevX = prevLine.points[1].x + x
  512. prevY = (prevX - prevLine.points[0].x) * prevK + prevLine.points[0].y
  513. lastX = lastLine.points[0].x + x
  514. lastY = (lastX - lastLine.points[0].x) * lastK + lastLine.points[0].y
  515. } else {
  516. prevY = prevLine.points[1].y + y
  517. prevX = (prevY - prevLine.points[0].y) / prevK + prevLine.points[0].x
  518. lastY = lastLine.points[0].y + y
  519. lastX = (lastY - lastLine.points[0].y) / lastK + lastLine.points[0].x
  520. }
  521. if (util.isInfinity(prevX) ||
  522. util.isInfinity(prevY) ||
  523. util.isInfinity(lastX) ||
  524. util.isInfinity(lastY)) {
  525. prevX = prevLine.points[1].x + x
  526. prevY = prevLine.points[1].y + y
  527. lastX = lastLine.points[0].x + x
  528. lastY = lastLine.points[0].y + y
  529. }
  530. prevLine.points[1].x = prevX
  531. prevLine.points[1].y = prevY
  532. lastLine.points[0].x = lastX
  533. lastLine.points[0].y = lastY
  534. line.points[0].x = prevLine.points[1].x
  535. line.points[0].y = prevLine.points[1].y
  536. line.points[1].x = lastLine.points[0].x
  537. line.points[1].y = lastLine.points[0].y
  538. }
  539. Wall.prototype.detection = function (movePosition) {
  540. var revoke = false
  541. var activeFacePoint = getFacePoints(movePosition.face)
  542. for (let key in this.faces) {
  543. if (this.faces[key] !== movePosition.face &&
  544. util.isFaceIntersect(activeFacePoint, getFacePoints(this.faces[key]))) {
  545. revoke = true;
  546. break;
  547. }
  548. }
  549. var cameras;
  550. if (this.cameras && (cameras = this.cameras[movePosition.face[0].roomIndex])) {
  551. for (var i = 0, camera; camera = cameras[i]; i++) {
  552. if (!util.pointInside(camera, activeFacePoint)) {
  553. revoke = true
  554. break;
  555. }
  556. }
  557. }
  558. return revoke
  559. }
  560. Wall.prototype._move = function (point, prevPoint, movePositions, renderer) {
  561. for (var i = 0; i < movePositions.length; i++) {
  562. var movePosition = movePositions[i]
  563. if (!movePositions.horn && this.movePositioning && this.movePositioning != movePosition) {
  564. movePosition.line.selected = false
  565. continue;
  566. };
  567. var xdis = point.x - prevPoint.x
  568. var ydis = point.y - prevPoint.y
  569. var dire = movePosition.dire[0] - movePosition.dire[1] > 0 ? 'X' : 'Y'
  570. if (dire === 'X') {
  571. this.updateLine(movePosition.line, xdis, 0)
  572. } else {
  573. this.updateLine(movePosition.line, 0, ydis)
  574. }
  575. var revoke = this.detection(movePosition)
  576. if (revoke) {
  577. if (dire === 'X') {
  578. this.updateLine(movePosition.line, -xdis, 0)
  579. } else {
  580. this.updateLine(movePosition.line, 0, -ydis)
  581. }
  582. } else {
  583. this.trigger('changePosition', movePosition.line)
  584. renderer.render()
  585. if (!movePositions.horn && !this.movePositioning && (xdis || ydis)) {
  586. this.movePositioning = movePosition
  587. }
  588. }
  589. }
  590. }
  591. Wall.prototype._up = function () {
  592. this.movePositioning = null
  593. }
  594. Wall.prototype._hover = function (point, prevPoint, renderer) {
  595. var rets = []
  596. for (var key in this.faces) {
  597. for (var i = 0, line; line = this.faces[key][i]; i++) {
  598. delete line.selected
  599. delete line.horn
  600. }
  601. }
  602. for (var key in this.faces) {
  603. var face = this.faces[key]
  604. for (var i = 0, line; line = face[i]; i++) {
  605. var p1d = util.lineDistance([point, line.points[0]]) < 0.2
  606. var p2d = util.lineDistance([point, line.points[1]]) < 0.2
  607. if (p1d || p2d) {
  608. var cpoint = p1d ? line.points[0] : line.points[1]
  609. var lline = face.find(function (fline) {
  610. return fline !== line && (util.equalPoint(fline.points[0], cpoint) || util.equalPoint(fline.points[1], cpoint))
  611. })
  612. rets.push(line, lline)
  613. line.selected = true
  614. lline.selected = true
  615. line.horn = cpoint
  616. rets.horn = true
  617. break
  618. } else if (util.isContainPoint(point, line.points, (this.lineWidth + 4) / renderer.status.prop)) {
  619. rets.push(line)
  620. line.selected = true
  621. }
  622. }
  623. if (i !== face.length) {
  624. break;
  625. }
  626. }
  627. renderer.render()
  628. return rets.length > 0
  629. }
  630. Wall.prototype.drawSelectedPoint = function (context, point) {
  631. context.beginPath()
  632. context.fillStyle = 'rgba(245, 255, 255, 0.3)'
  633. context.arc(point.x, point.y, 12, 0, 2 * Math.PI)
  634. context.fill()
  635. context.closePath()
  636. context.beginPath()
  637. context.fillStyle = 'rgba(245, 255, 0, 0.7)'
  638. context.arc(point.x, point.y, 6, 0, 2 * Math.PI)
  639. context.fill()
  640. context.closePath()
  641. var pointsArr = [
  642. [
  643. {
  644. x: point.x + 20,
  645. y: point.y
  646. }, {
  647. x: point.x + 36,
  648. y: point.y
  649. }, {
  650. x: point.x + 28,
  651. y: point.y - 8
  652. }, {
  653. x: point.x + 28,
  654. y: point.y + 8
  655. }
  656. ],
  657. [
  658. {
  659. x: point.x - 20,
  660. y: point.y
  661. }, {
  662. x: point.x - 36,
  663. y: point.y
  664. }, {
  665. x: point.x - 28,
  666. y: point.y - 8
  667. }, {
  668. x: point.x - 28,
  669. y: point.y + 8
  670. }
  671. ],
  672. [
  673. {
  674. x: point.x,
  675. y: point.y + 20
  676. }, {
  677. x: point.x,
  678. y: point.y + 36
  679. }, {
  680. x: point.x - 8,
  681. y: point.y + 28
  682. }, {
  683. x: point.x + 8,
  684. y: point.y + 28
  685. }
  686. ],
  687. [
  688. {
  689. x: point.x,
  690. y: point.y - 20
  691. }, {
  692. x: point.x,
  693. y: point.y - 36
  694. }, {
  695. x: point.x - 8,
  696. y: point.y - 28
  697. }, {
  698. x: point.x + 8,
  699. y: point.y - 28
  700. }
  701. ]
  702. ]
  703. var lines = [[0, 1], [1, 2], [1, 3]]
  704. pointsArr.forEach(function (points) {
  705. context.strokeStyle = '#fff';
  706. context.lineWidth = 8;
  707. context.lineCap = 'round'
  708. lines.forEach(function (line) {
  709. context.beginPath()
  710. context.moveTo(points[line[0]].x, points[line[0]].y)
  711. context.lineTo(points[line[1]].x, points[line[1]].y)
  712. context.stroke()
  713. context.closePath()
  714. })
  715. context.strokeStyle = '#01c7ae';
  716. context.lineWidth = 3;
  717. lines.forEach(function (line) {
  718. context.beginPath()
  719. context.moveTo(points[line[0]].x, points[line[0]].y)
  720. context.lineTo(points[line[1]].x, points[line[1]].y)
  721. context.stroke()
  722. context.closePath()
  723. })
  724. })
  725. }
  726. Wall.prototype.drawSelectedLine = function (context, _line) {
  727. var width = 8
  728. var lV = util.lineVector({points: _line})
  729. var vV = util.verticalLine({points: _line})
  730. vV = {x: vV[0], y: vV[1]}
  731. var center = {
  732. x: (_line[0].x + _line[1].x) / 2 + vV.x * 4,
  733. y: (_line[0].y + _line[1].y) / 2 + vV.y * 4
  734. }
  735. w = util.vectorWidth(lV, width)
  736. h = util.vectorWidth(vV, width)
  737. var shape = [
  738. {x: center.x + lV.x * w, y: center.y + lV.y * w},
  739. {x: center.x - lV.x * w, y: center.y - lV.y * w},
  740. {x: center.x + vV.x * h, y: center.y + vV.y * h}
  741. ]
  742. context.beginPath();
  743. context.lineWidth = 3
  744. context.strokeStyle = '#fff';
  745. context.fillStyle = '#00c7b0'
  746. context.moveTo(shape[0].x, shape[0].y);
  747. context.lineTo(shape[1].x, shape[1].y);
  748. context.lineTo(shape[2].x, shape[2].y);
  749. context.closePath();
  750. context.stroke();
  751. context.fill();
  752. center = {
  753. x: (_line[0].x + _line[1].x) / 2 - vV.x * 4,
  754. y: (_line[0].y + _line[1].y) / 2 - vV.y * 4
  755. }
  756. shape = [
  757. {x: center.x + lV.x * w, y: center.y + lV.y * w},
  758. {x: center.x - lV.x * w, y: center.y - lV.y * w},
  759. {x: center.x - vV.x * h, y: center.y - vV.y * h}
  760. ]
  761. context.beginPath();
  762. context.moveTo(shape[0].x, shape[0].y);
  763. context.lineTo(shape[1].x, shape[1].y);
  764. context.lineTo(shape[2].x, shape[2].y);
  765. context.closePath();
  766. context.stroke();
  767. context.fill();
  768. }
  769. Wall.prototype.drawLine = function (context, _line) {
  770. context.beginPath();
  771. context.strokeStyle = '#fff';
  772. context.lineWidth = this.lineWidth;
  773. context.lineCap = 'round'
  774. context.moveTo(_line[0].x, _line[0].y);
  775. context.lineTo(_line[1].x, _line[1].y);
  776. context.closePath();
  777. context.stroke();
  778. }
  779. Wall.prototype.draw = function (renderer, context) {
  780. var selected = false
  781. for (var key in this.faces) {
  782. var face = this.faces[key]
  783. for (var i = 0, line; line = face[i]; i++) {
  784. var _line = [
  785. renderer.transScreenPoint(line.points[0]),
  786. renderer.transScreenPoint(line.points[1])
  787. ]
  788. this.drawLine(context, _line)
  789. }
  790. }
  791. for (var key in this.faces) {
  792. var face = this.faces[key]
  793. for (var i = 0, line; line = face[i]; i++) {
  794. var _line = [
  795. renderer.transScreenPoint(line.points[0]),
  796. renderer.transScreenPoint(line.points[1])
  797. ]
  798. if (line.selected) {
  799. context.beginPath();
  800. context.strokeStyle = '#f3ff33';
  801. context.lineWidth = this.lineWidth;
  802. context.lineCap = 'round'
  803. context.moveTo(_line[0].x, _line[0].y);
  804. context.lineTo(_line[1].x, _line[1].y);
  805. context.closePath();
  806. context.stroke();
  807. }
  808. }
  809. }
  810. for (var key in this.faces) {
  811. var face = this.faces[key]
  812. for (var i = 0, line; line = face[i]; i++) {
  813. var _line = [
  814. renderer.transScreenPoint(line.points[0]),
  815. renderer.transScreenPoint(line.points[1])
  816. ]
  817. if (line.selected) {
  818. if (!selected) {
  819. selected = true
  820. if (line.horn) {
  821. this.drawSelectedPoint(context, renderer.transScreenPoint(line.horn))
  822. } else {
  823. this.drawSelectedLine(context, _line)
  824. }
  825. }
  826. }
  827. }
  828. }
  829. if (this.cameras) {
  830. for (var key in this.cameras) {
  831. for (var i = 0; i < this.cameras[key].length; i++) {
  832. var point = renderer.transScreenPoint(this.cameras[key][i])
  833. context.fillStyle = "#00cc00";
  834. context.fillRect(point.x - this.lineWidth / 2, point.y - this.lineWidth / 2, this.lineWidth, this.lineWidth);
  835. }
  836. }
  837. }
  838. }
  839. Wall.prototype.preservationState = function (renderer) {
  840. var state = {}
  841. for (var key in this.faces) {
  842. state[key] = {}
  843. for (var i = 0; i < this.faces[key].length; i++) {
  844. var line = this.faces[key][i]
  845. state[key][line.id] = [{
  846. x: line.points[0].x,
  847. y: line.points[0].y
  848. },
  849. {
  850. x: line.points[1].x,
  851. y: line.points[1].y
  852. }
  853. ]
  854. }
  855. }
  856. this.stateStack.push(state)
  857. }
  858. Wall.prototype.revokeState = function (renderer) {
  859. var state = this.stateStack.pop()
  860. for (var key in state) {
  861. for (var id in state[key]) {
  862. var cline = state[key][id]
  863. var line = this.faces[key].find(function (line) {
  864. return line.id === id
  865. })
  866. line.points[0].x = cline[0].x
  867. line.points[0].y = cline[0].y
  868. line.points[1].x = cline[1].x
  869. line.points[1].y = cline[1].y
  870. }
  871. }
  872. renderer.render();
  873. }
  874. Wall.prototype.getIndex = function() {
  875. return -1
  876. }
  877. inherit(Wall, Event.create('__wall__'))
  878. return Wall
  879. })();
  880. /**
  881. * 当前所在位置
  882. */
  883. var Position = (function Position() {
  884. function Position(point, angle) {
  885. this.point = point
  886. this.angle = angle
  887. this.withinW = 6
  888. this.abroadW = 2
  889. this.lightW = 12
  890. this.lightrRdian = 1 / 2.5 * Math.PI
  891. }
  892. Position.prototype.draw = function (renderer, context) {
  893. var point = renderer.transScreenPoint(this.point)
  894. var startRdian = this.angle - this.lightrRdian / 2
  895. var endRdian = this.angle + this.lightrRdian / 2
  896. var ligWidth = this.withinW + this.abroadW + this.lightW
  897. var abroadWidth = this.withinW + this.abroadW
  898. var grd = context.createRadialGradient(point.x, point.y, abroadWidth, point.x, point.y, ligWidth);
  899. grd.addColorStop(0, "rgba(0,200,175,0.9)");
  900. grd.addColorStop(1, "rgba(0,200,175,0.3)");
  901. context.beginPath();
  902. context.fillStyle = grd;
  903. context.moveTo(point.x, point.y);
  904. context.arc(point.x, point.y, ligWidth, startRdian, endRdian, false);
  905. context.fill()
  906. context.closePath();
  907. context.beginPath();
  908. context.fillStyle = "#ffffff";
  909. context.arc(point.x, point.y, abroadWidth, 0, 2 * Math.PI, false);
  910. context.fill()
  911. context.closePath();
  912. context.beginPath();
  913. context.fillStyle = "rgba(0,200,175,1)";
  914. context.arc(point.x, point.y, this.withinW, 0, 2 * Math.PI, false);
  915. context.fill()
  916. context.closePath();
  917. }
  918. inherit(Position, Event.create('__position__'))
  919. return Position
  920. })();
  921. /**
  922. * 门,正式版本
  923. */
  924. var Door = (function Door() {
  925. var count = 0
  926. function Door(line, points, link) {
  927. count++
  928. this.line = line
  929. this.linkedLines = link
  930. this.points = points
  931. this.color = 'rgba(0,200,175,1)'
  932. }
  933. Door.prototype.getIndex = function() {
  934. return 1;
  935. }
  936. Door.prototype.detection = function (origin) {
  937. if (origin) {
  938. var oV = util.lineVector({points: origin})
  939. var pV = util.lineVector({points: this.points})
  940. if (oV.x * pV.x < 0 || oV.y * pV.y < 0) {
  941. return false
  942. }
  943. }
  944. var collision = true
  945. var detection = []
  946. this.line.__doors && detection.push.apply(detection, this.line.__doors)
  947. this.line.__casements && detection.push.apply(detection, this.line.__casements)
  948. this.line.__columns && detection.push.apply(detection, this.line.__columns)
  949. for (var i = 0; i < detection.length; i++) {
  950. if (detection[i].points !== this.points && (
  951. util.isContainPoint(this.points[0], detection[i].points, 0.3) ||
  952. util.isContainPoint(this.points[1], detection[i].points, 0.3)
  953. )) {
  954. collision = false
  955. }
  956. }
  957. return collision && util.isContainPoint(this.points[0], this.line.points, 0.1) &&
  958. util.isContainPoint(this.points[1], this.line.points, 0.1) &&
  959. util.pointLineDis(this.linkedLines[0].points, this.points[0]) > 0.2 &&
  960. util.pointLineDis(this.linkedLines[0].points, this.points[1]) > 0.2 &&
  961. util.pointLineDis(this.linkedLines[1].points, this.points[0]) > 0.2 &&
  962. util.pointLineDis(this.linkedLines[1].points, this.points[1]) > 0.2
  963. }
  964. Door.prototype._down = function (point) {
  965. var info = {
  966. vector: util.lineVector(this.line)
  967. };
  968. if (util.lineDistance([point, this.points[0]]) < 0.3) {
  969. info.scalePoint = 0
  970. } else if (util.lineDistance([point, this.points[1]]) < 0.3) {
  971. info.scalePoint = 1
  972. } else if (!util.isContainPoint(point, this.points, 0.5)) {
  973. info = null
  974. }
  975. return info
  976. }
  977. Door.prototype.getMoveChange = function (vector, curr, prev) {
  978. var move = {
  979. x: vector.x < 0 ? (prev.x - curr.x) : (curr.x - prev.x),
  980. y: vector.y < 0 ? (prev.y - curr.y) : (curr.y - prev.y)
  981. }
  982. if (Math.abs(vector.x) > Math.abs(vector.y)) {
  983. move = {
  984. x: move.x * vector.x,
  985. y: move.x * vector.y
  986. }
  987. } else {
  988. move = {
  989. x: move.y * vector.x,
  990. y: move.y * vector.y
  991. }
  992. }
  993. return move
  994. }
  995. Door.prototype._move = function (point, prevPoint, info, renderer) {
  996. if (info.scalePoint !== undefined) {
  997. this.scale(point, prevPoint, info, renderer)
  998. } else {
  999. this.move(point, prevPoint, info.vector, renderer)
  1000. }
  1001. }
  1002. Door.prototype.move = function (point, prevPoint, vector, renderer) {
  1003. var move = this.getMoveChange(vector, point, prevPoint)
  1004. this.points.forEach(function (point) {
  1005. point.x += move.x
  1006. point.y += move.y
  1007. })
  1008. if (this.detection()) {
  1009. renderer.render()
  1010. this.trigger('changePoints')
  1011. } else {
  1012. this.points.forEach(function (point) {
  1013. point.x -= move.x
  1014. point.y -= move.y
  1015. })
  1016. }
  1017. }
  1018. Door.prototype._hover = function (point, prevPoint, renderer) {
  1019. this.selected = util.isContainPoint(point, this.points, 0.5)
  1020. renderer.render()
  1021. return this.selected
  1022. }
  1023. Door.prototype.scale = function (point, prevPoint, info, renderer) {
  1024. var move = this.getMoveChange(info.vector, point, prevPoint)
  1025. var origin = this.points.map(function(point) {
  1026. return {
  1027. x: point.x,
  1028. y: point.y
  1029. }
  1030. })
  1031. this.points[info.scalePoint].x += move.x
  1032. this.points[info.scalePoint].y += move.y
  1033. if (this.detection(origin)) {
  1034. renderer.render()
  1035. this.trigger('changePoints')
  1036. } else {
  1037. this.points[info.scalePoint].x -= move.x
  1038. this.points[info.scalePoint].y -= move.y
  1039. }
  1040. }
  1041. Door.prototype.draw = function (renderer, context) {
  1042. var vpoint = util.verticalLine({points: this.points})
  1043. var width = util.lineDistance(this.points)
  1044. var points = this.points.concat([{
  1045. x: this.points[0].x + vpoint[0] * width,
  1046. y: this.points[0].y + vpoint[1] * width
  1047. }])
  1048. points = points.map(function (point) {
  1049. return renderer.transScreenPoint(point)
  1050. })
  1051. var startDeg = util.lineAngle([points[1], points[0]]) * Math.PI / 180
  1052. var endDeg = util.lineAngle([points[2], points[0]]) * Math.PI / 180
  1053. var deg = endDeg - startDeg
  1054. var router = ((deg > Math.PI || (deg < 0 && deg > -Math.PI)) ? true : false)
  1055. var r = util.lineDistance([points[1], points[0]])
  1056. context.strokeStyle = this.color;
  1057. context.lineWidth = 4;
  1058. // context.lineCap = 'round'
  1059. context.strokeStyle = '#181c1d';
  1060. context.beginPath();
  1061. context.moveTo(points[0].x, points[0].y);
  1062. context.lineTo(points[1].x, points[1].y);
  1063. context.stroke()
  1064. context.closePath();
  1065. context.lineWidth = 1;
  1066. context.strokeStyle = '#fff';
  1067. context.beginPath();
  1068. context.moveTo(points[0].x, points[0].y);
  1069. context.arc(points[0].x, points[0].y, r, startDeg, endDeg, router);
  1070. context.lineTo(points[0].x, points[0].y);
  1071. context.stroke()
  1072. if (this.selected) {
  1073. context.fillStyle = 'rgba(243, 255, 0, 0.6)'
  1074. context.fill()
  1075. }
  1076. context.closePath();
  1077. }
  1078. inherit(Door, Event.create('__door' + count + '__'))
  1079. return Door
  1080. })();
  1081. /**
  1082. * 窗
  1083. */
  1084. var Casement = (function Casement() {
  1085. var count = 0
  1086. function Casement(line, points, links) {
  1087. count++
  1088. this.line = line
  1089. this.linkedLines = links
  1090. this.points = points
  1091. this.lineWidth = 4
  1092. this.color = '#202123'
  1093. }
  1094. Casement.prototype.getIndex = function () {
  1095. return 1;
  1096. }
  1097. Casement.prototype.detection = function (origin) {
  1098. if (origin) {
  1099. var oV = util.lineVector({
  1100. points: origin
  1101. })
  1102. var pV = util.lineVector({
  1103. points: this.points
  1104. })
  1105. if (oV.x * pV.x < 0 || oV.y * pV.y < 0) {
  1106. return false
  1107. }
  1108. }
  1109. var collision = true
  1110. var detection = []
  1111. this.line.__doors && detection.push.apply(detection, this.line.__doors)
  1112. this.line.__casements && detection.push.apply(detection, this.line.__casements)
  1113. this.line.__columns && detection.push.apply(detection, this.line.__columns)
  1114. for (var i = 0; i < detection.length; i++) {
  1115. if (detection[i].points !== this.points &&(
  1116. util.isContainPoint(this.points[0], detection[i].points, 0.3) ||
  1117. util.isContainPoint(this.points[1], detection[i].points, 0.3)
  1118. )
  1119. ) {
  1120. collision = false
  1121. }
  1122. }
  1123. return collision && util.isContainPoint(this.points[0], this.line.points, 0.1) &&
  1124. util.isContainPoint(this.points[1], this.line.points, 0.1) &&
  1125. util.pointLineDis(this.linkedLines[0].points, this.points[0]) > 0.2 &&
  1126. util.pointLineDis(this.linkedLines[0].points, this.points[1]) > 0.2 &&
  1127. util.pointLineDis(this.linkedLines[1].points, this.points[0]) > 0.2 &&
  1128. util.pointLineDis(this.linkedLines[1].points, this.points[1]) > 0.2
  1129. }
  1130. Casement.prototype._down = function (point) {
  1131. var info = {
  1132. vector: util.lineVector(this.line)
  1133. };
  1134. if (util.lineDistance([point, this.points[0]]) < 0.3) {
  1135. info.scalePoint = 0
  1136. } else if (util.lineDistance([point, this.points[1]]) < 0.3) {
  1137. info.scalePoint = 1
  1138. } else if (!util.isContainPoint(point, this.points, 0.5)) {
  1139. info = null
  1140. }
  1141. return info
  1142. }
  1143. Casement.prototype.getMoveChange = function (vector, curr, prev) {
  1144. var move = {
  1145. x: vector.x < 0 ? (prev.x - curr.x) : (curr.x - prev.x),
  1146. y: vector.y < 0 ? (prev.y - curr.y) : (curr.y - prev.y)
  1147. }
  1148. if (Math.abs(vector.x) > Math.abs(vector.y)) {
  1149. move = {
  1150. x: move.x * vector.x,
  1151. y: move.x * vector.y
  1152. }
  1153. } else {
  1154. move = {
  1155. x: move.y * vector.x,
  1156. y: move.y * vector.y
  1157. }
  1158. }
  1159. return move
  1160. }
  1161. Casement.prototype._hover = function (point, prevPoint, renderer) {
  1162. this.selected = util.isContainPoint(point, this.points, 0.5)
  1163. renderer.render()
  1164. return this.selected
  1165. }
  1166. Casement.prototype._move = function (point, prevPoint, info, renderer) {
  1167. if (info.scalePoint !== undefined) {
  1168. this.scale(point, prevPoint, info, renderer)
  1169. } else {
  1170. this.move(point, prevPoint, info.vector, renderer)
  1171. }
  1172. }
  1173. Casement.prototype.move = function (point, prevPoint, vector, renderer) {
  1174. var move = this.getMoveChange(vector, point, prevPoint)
  1175. this.points.forEach(function (point) {
  1176. point.x += move.x
  1177. point.y += move.y
  1178. })
  1179. if (this.detection()) {
  1180. renderer.render()
  1181. this.trigger('changePoints')
  1182. } else {
  1183. this.points.forEach(function (point) {
  1184. point.x -= move.x
  1185. point.y -= move.y
  1186. })
  1187. }
  1188. }
  1189. Casement.prototype.scale = function (point, prevPoint, info, renderer) {
  1190. var move = this.getMoveChange(info.vector, point, prevPoint)
  1191. var origin = this.points.map(function (point) {
  1192. return {
  1193. x: point.x,
  1194. y: point.y
  1195. }
  1196. })
  1197. this.points[info.scalePoint].x += move.x
  1198. this.points[info.scalePoint].y += move.y
  1199. if (this.detection(origin)) {
  1200. renderer.render()
  1201. this.trigger('changePoints')
  1202. } else {
  1203. this.points[info.scalePoint].x -= move.x
  1204. this.points[info.scalePoint].y -= move.y
  1205. }
  1206. }
  1207. Casement.prototype.draw = function (renderer, context) {
  1208. var points = this.points.map(function (point) {
  1209. return renderer.transScreenPoint(point)
  1210. })
  1211. context.strokeStyle = this.color;
  1212. context.lineWidth = this.lineWidth;
  1213. context.beginPath();
  1214. context.moveTo(points[0].x, points[0].y);
  1215. context.lineTo(points[1].x, points[1].y);
  1216. context.stroke()
  1217. context.closePath();
  1218. context.strokeStyle = '#fff';
  1219. context.lineWidth = 1;
  1220. context.beginPath();
  1221. context.moveTo(points[0].x, points[0].y);
  1222. context.lineTo(points[1].x, points[1].y);
  1223. context.stroke()
  1224. context.closePath();
  1225. // if (this.selected) {
  1226. // context.strokeStyle = 'rgba(243, 255, 0, 0.9)'
  1227. // context.lineWidth = this.lineWidth;
  1228. // context.beginPath();
  1229. // context.moveTo(points[0].x, points[0].y);
  1230. // context.lineTo(points[1].x, points[1].y);
  1231. // context.closePath();
  1232. // context.stroke()
  1233. // }
  1234. }
  1235. inherit(Casement, Event.create('__casement' + count + '__'))
  1236. return Casement
  1237. })();
  1238. /**
  1239. * 柱子
  1240. */
  1241. var Column = (function Column() {
  1242. var count = 0
  1243. function Column(line, points, links) {
  1244. count++
  1245. this.line = line
  1246. this.linkedLines = links
  1247. this.points = points
  1248. this.color = '#ffffff'
  1249. }
  1250. Column.prototype.getIndex = function () {
  1251. return 1;
  1252. }
  1253. Column.prototype.detection = function (origin) {
  1254. if (origin) {
  1255. var oV = util.lineVector({
  1256. points: origin
  1257. })
  1258. var pV = util.lineVector({
  1259. points: this.points
  1260. })
  1261. if (oV.x * pV.x < 0 || oV.y * pV.y < 0) {
  1262. return false
  1263. }
  1264. }
  1265. var collision = true
  1266. var detection = []
  1267. this.line.__doors && detection.push.apply(detection, this.line.__doors)
  1268. this.line.__casements && detection.push.apply(detection, this.line.__casements)
  1269. this.line.__columns && detection.push.apply(detection, this.line.__columns)
  1270. for (var i = 0; i < detection.length; i++) {
  1271. if (detection[i].points !== this.points && (
  1272. util.isContainPoint(this.points[0], detection[i].points, 0.3) ||
  1273. util.isContainPoint(this.points[1], detection[i].points, 0.3)
  1274. )) {
  1275. collision = false
  1276. }
  1277. }
  1278. return collision && util.isContainPoint(this.points[0], this.line.points, 0.1) &&
  1279. util.isContainPoint(this.points[1], this.line.points, 0.1) &&
  1280. util.pointLineDis(this.linkedLines[0].points, this.points[0]) > 0.2 &&
  1281. util.pointLineDis(this.linkedLines[0].points, this.points[1]) > 0.2 &&
  1282. util.pointLineDis(this.linkedLines[1].points, this.points[0]) > 0.2 &&
  1283. util.pointLineDis(this.linkedLines[1].points, this.points[1]) > 0.2
  1284. }
  1285. Column.prototype._down = function (point) {
  1286. var info = {
  1287. vector: util.lineVector(this.line)
  1288. };
  1289. if (util.isContainPoint(point, [this.points[1], this.points[2]], 0.3)) {
  1290. info.scalePoint = 0
  1291. } else if (util.isContainPoint(point, [this.points[2], this.points[3]], 0.3)) {
  1292. info.scalePoint = 1
  1293. } else if (util.isContainPoint(point, [this.points[3], this.points[0]], 0.3)) {
  1294. info.scalePoint = 2
  1295. } else if (!util.pointInside(point, this.points)) {
  1296. info = null
  1297. }
  1298. return info
  1299. }
  1300. Column.prototype.getMoveChange = function (vector, curr, prev) {
  1301. var move = {
  1302. x: vector.x < 0 ? (prev.x - curr.x) : (curr.x - prev.x),
  1303. y: vector.y < 0 ? (prev.y - curr.y) : (curr.y - prev.y)
  1304. }
  1305. if (Math.abs(vector.x) > Math.abs(vector.y)) {
  1306. move = {
  1307. x: move.x * vector.x,
  1308. y: move.x * vector.y
  1309. }
  1310. } else {
  1311. move = {
  1312. x: move.y * vector.x,
  1313. y: move.y * vector.y
  1314. }
  1315. }
  1316. return move
  1317. }
  1318. Column.prototype._hover = function (point, prevPoint, renderer) {
  1319. this.selected = util.isContainPoint(point, [this.points[1], this.points[2]], 0.3) ||
  1320. util.isContainPoint(point, [this.points[2], this.points[3]], 0.3) ||
  1321. util.isContainPoint(point, [this.points[3], this.points[0]], 0.3) ||
  1322. util.pointInside(point, this.points)
  1323. renderer.render()
  1324. return this.selected
  1325. }
  1326. Column.prototype._move = function (point, prevPoint, info, renderer) {
  1327. if (info.scalePoint !== undefined) {
  1328. this.scale(point, prevPoint, info, renderer)
  1329. } else {
  1330. this.move(point, prevPoint, info.vector, renderer)
  1331. }
  1332. }
  1333. Column.prototype.move = function (point, prevPoint, vector, renderer) {
  1334. var move = this.getMoveChange(vector, point, prevPoint)
  1335. this.points.forEach(function (point) {
  1336. point.x += move.x
  1337. point.y += move.y
  1338. })
  1339. if (this.detection()) {
  1340. renderer.render()
  1341. this.trigger('changePoints')
  1342. } else {
  1343. this.points.forEach(function (point) {
  1344. point.x -= move.x
  1345. point.y -= move.y
  1346. })
  1347. }
  1348. }
  1349. Column.prototype.scale = function (point, prevPoint, info, renderer) {
  1350. var origin = this.points.map(function (point) {
  1351. return {
  1352. x: point.x,
  1353. y: point.y
  1354. }
  1355. })
  1356. var prev = (info.scalePoint + 1) % this.points.length
  1357. var next = (info.scalePoint + 2) % this.points.length
  1358. var vV = util.verticalLine({points: [this.points[prev], this.points[next]]})
  1359. vV = {x: vV[0], y: vV[1]}
  1360. var move = this.getMoveChange(vV,point, prevPoint)
  1361. this.points[prev].x += move.x
  1362. this.points[prev].y += move.y
  1363. this.points[next].x += move.x
  1364. this.points[next].y += move.y
  1365. if (this.detection(origin)) {
  1366. renderer.render()
  1367. this.trigger('changePoints')
  1368. } else {
  1369. this.points[prev].x -= move.x
  1370. this.points[prev].y -= move.y
  1371. this.points[next].x -= move.x
  1372. this.points[next].y -= move.y
  1373. }
  1374. }
  1375. Column.prototype.draw = function (renderer, context) {
  1376. var points = this.points.map(function (point) {
  1377. return renderer.transScreenPoint(point)
  1378. })
  1379. context.strokeStyle = this.color;
  1380. context.lineWidth = 1;
  1381. context.beginPath();
  1382. context.moveTo(points[0].x, points[0].y);
  1383. for (var i = 0; i < points.length; i++) {
  1384. context.lineTo(points[i].x, points[i].y);
  1385. }
  1386. context.lineTo(points[0].x, points[0].y);
  1387. context.stroke();
  1388. if (this.selected) {
  1389. context.fillStyle = 'rgba(243, 255, 0, 0.6)'
  1390. context.fill()
  1391. }
  1392. context.closePath();
  1393. context.beginPath();
  1394. context.moveTo(points[0].x, points[0].y);
  1395. context.lineTo(points[2].x, points[2].y);
  1396. context.stroke();
  1397. context.closePath();
  1398. context.beginPath();
  1399. context.moveTo(points[1].x, points[1].y);
  1400. context.lineTo(points[3].x, points[3].y);
  1401. context.closePath();
  1402. context.stroke();
  1403. }
  1404. inherit(Column, Event.create('__column' + count + '__'))
  1405. return Column
  1406. })();
  1407. /**
  1408. * 总控制
  1409. */
  1410. var Renderer = (function Renderer() {
  1411. var execFilter = 'FUNCTION_EXEC'
  1412. /**
  1413. * 渲染器
  1414. * @param {*} canvas 画布
  1415. * @param {*} wallData 墙面数据
  1416. */
  1417. function Renderer(canvas, wallData) {
  1418. this.canvas = canvas
  1419. this.context = canvas.getContext('2d')
  1420. this.origin = wallData
  1421. this.models = []
  1422. this.init()
  1423. this.regEvent()
  1424. }
  1425. /**
  1426. * 计算所有需要的信息,渲染器需要的宽高,真实比例等
  1427. */
  1428. Renderer.prototype.init = function () {
  1429. this.width = this.canvas.width
  1430. this.height = this.canvas.height
  1431. this.wMultiple = this.canvas.width / this.canvas.offsetWidth
  1432. this.hMultiple = this.canvas.height / this.canvas.offsetHeight
  1433. this.context.translate(this.width / 2, this.height / 2);
  1434. this.screenOffset = getPosition(this.canvas)
  1435. this.section = {
  1436. minx: -this.width / 2,
  1437. maxx: this.width / 2,
  1438. miny: -this.height / 2,
  1439. maxy: this.height / 2
  1440. }
  1441. var points = []
  1442. this.origin.forEach(function (line) {
  1443. points = points.concat(...line.points)
  1444. })
  1445. var result = util.tranProp(points, [-0.8, 0.8])
  1446. this.status = {
  1447. offset: result.offset,
  1448. prop: result.prop,
  1449. range: result.range
  1450. }
  1451. }
  1452. /**
  1453. * 真实点位转化为画布点位
  1454. */
  1455. Renderer.prototype.transScreenPoint = function (point) {
  1456. var spoint = {
  1457. x: point.x,
  1458. y: point.y
  1459. }
  1460. spoint.x += this.status.offset.x
  1461. spoint.y += this.status.offset.y
  1462. spoint.x = (spoint.x * this.status.range / this.status.prop) * (this.width / 2)
  1463. spoint.y = (spoint.y * this.status.range / this.status.prop) * (this.height / 2)
  1464. return spoint
  1465. }
  1466. /**
  1467. * 画布点位转化为真实点位
  1468. */
  1469. Renderer.prototype.transRealPoint = function (point) {
  1470. return {
  1471. x: (point.x * this.status.prop) / (this.status.range * this.width / 2) - this.status.offset.x,
  1472. y: (point.y * this.status.prop) / (this.status.range * this.height / 2) - this.status.offset.y
  1473. }
  1474. }
  1475. Renderer.prototype.regEvent = function () {
  1476. var sinfo, model;
  1477. var startPoint = null
  1478. var prevPoint = null
  1479. var models = null
  1480. var event = {
  1481. down(offset) {
  1482. offset.x = (offset.x - this.screenOffset.x) * this.wMultiple
  1483. offset.y = (offset.y - this.screenOffset.y) * this.hMultiple
  1484. startPoint = this.transRealPoint(util.tranPoint(offset, this.section))
  1485. prevPoint = startPoint
  1486. models = Object.assign([], this.models).sort(function(a, b) {
  1487. return ((b.getIndex && b.getIndex()) || 0) - ((a.getIndex && a.getIndex()) || 0)
  1488. })
  1489. for (var i = 0; i < models.length; i++) {
  1490. sinfo = models[i]._down && models[i]._down(startPoint, this)
  1491. if (sinfo) {
  1492. model = models[i]
  1493. break;
  1494. }
  1495. }
  1496. return true
  1497. },
  1498. move(move) {
  1499. if (!models) {
  1500. models = Object.assign([], this.models).sort(function (a, b) {
  1501. return ((b.getIndex && b.getIndex()) || 0) - ((a.getIndex && a.getIndex()) || 0)
  1502. })
  1503. }
  1504. move.x = (move.x - this.screenOffset.x) * this.wMultiple
  1505. move.y = (move.y - this.screenOffset.y) * this.hMultiple
  1506. var point = this.transRealPoint(util.tranPoint(move, this.section))
  1507. if (model) {
  1508. model._move(point, prevPoint, sinfo, this, this.context)
  1509. } else {
  1510. for (var i = 0; i < models.length; i++) {
  1511. if (models[i]._hover && models[i]._hover(point, prevPoint, this, this.context)) {
  1512. break;
  1513. }
  1514. }
  1515. if (i === models.length) {
  1516. this.canvas.style.cursor = 'inherit';
  1517. } else {
  1518. this.canvas.style.cursor = 'pointer';
  1519. }
  1520. }
  1521. prevPoint = point
  1522. },
  1523. up() {
  1524. model && model._up && model._up(startPoint, prevPoint, this, this.context)
  1525. startPoint = null
  1526. prevPoint = null
  1527. model = null
  1528. sinfo = null
  1529. models = null
  1530. }
  1531. }
  1532. event.down = event.down.bind(this)
  1533. event.move = event.move.bind(this)
  1534. event.up = event.up.bind(this)
  1535. addMouseEvent(this.canvas, event)
  1536. }
  1537. /**
  1538. * 统一执行命令
  1539. */
  1540. Renderer.prototype.unifiedExec = function () {
  1541. var args = Array.from(arguments)
  1542. var command = args.shift()
  1543. var ret = []
  1544. var filter = args[args.length - 1] === execFilter
  1545. this.models.map(function (model) {
  1546. if (model[command]) {
  1547. if (filter) {
  1548. ret.push(args[0].apply(model, [model, args.slice(1, args.length - 1)]))
  1549. } else {
  1550. ret.push(model[command].apply(model, args))
  1551. }
  1552. } else {
  1553. ret.push(null)
  1554. }
  1555. })
  1556. return ret
  1557. }
  1558. /**
  1559. * 保存状态
  1560. */
  1561. Renderer.prototype.preservationState = function () {
  1562. this.unifiedExec('preservationState', this)
  1563. }
  1564. Renderer.prototype.revokeState = function () {
  1565. this.unifiedExec('revokeState', this)
  1566. }
  1567. /**
  1568. * 渲染所有依赖了渲染器的模型
  1569. */
  1570. Renderer.prototype.render = function () {
  1571. var that = this
  1572. if (!that.rendering) {
  1573. that.rendering = true
  1574. requestAnimationFrame(render)
  1575. }
  1576. function render() {
  1577. that.context.clearRect(-that.width / 2, -that.height / 2, that.width, that.height)
  1578. that.unifiedExec('draw', function (model) {
  1579. that.context.save()
  1580. model.draw(that, that.context)
  1581. that.context.restore()
  1582. }, execFilter);
  1583. that.rendering = false
  1584. }
  1585. }
  1586. return Renderer
  1587. })();
  1588. function update3D(line) {
  1589. if (line.updateLine3D) {
  1590. line.updateLine3D()
  1591. } else {
  1592. // console.error('当前线条没有注册3D线条方法')
  1593. }
  1594. }
  1595. function update2d(wall, line) {
  1596. if (line.___loadUpdate) {
  1597. return;
  1598. }
  1599. var update = line.update
  1600. line.___loadUpdate = true
  1601. line.update = function (dirs, len, renderer) {
  1602. var args = [{
  1603. x: 0,
  1604. y: 0
  1605. },
  1606. {
  1607. x: 0,
  1608. y: 0
  1609. },
  1610. {
  1611. line: this,
  1612. face: wall.faces[this.roomIndex],
  1613. dire: dirs[1]
  1614. },
  1615. renderer
  1616. ]
  1617. args[0][dirs[0]] = len;
  1618. wall._move.apply(wall, args)
  1619. update && update.bind(this)()
  1620. }
  1621. }
  1622. /**
  1623. * 装载门窗,并拦截线段移动碰到门窗
  1624. * @param {*} line2Ds
  1625. * @param {*} wall
  1626. */
  1627. function loadComponents(line2Ds, wall, renderer) {
  1628. var doors = []
  1629. var casements = []
  1630. var columns = []
  1631. line2Ds.forEach(function (line) {
  1632. line.__doors = line.__doors || []
  1633. line.__casements = line.__casements || []
  1634. line.__columns = line.__columns || []
  1635. line.otherobjs && line.otherobjs.forEach(function (obj) {
  1636. function check(_obj) {
  1637. return _obj.origin === obj
  1638. }
  1639. if (~line.__doors.findIndex(check) || ~line.__casements.findIndex(check)) return;
  1640. var links = line.linkedLineID.map(function(id) {
  1641. return line2Ds.find(function(line) {
  1642. return line.id === id
  1643. })
  1644. })
  1645. var _obj
  1646. if (~obj.id.indexOf('door')) {
  1647. _obj = new Door(line, obj.points2d, links)
  1648. // 创建线段中的门
  1649. line.__doors.push(_obj)
  1650. doors.push(_obj)
  1651. } else if (~obj.id.indexOf('window')) {
  1652. _obj = new Casement(line, obj.points2d, links)
  1653. // 创建线段中的窗
  1654. line.__casements.push(_obj)
  1655. casements.push(_obj)
  1656. } else if (~obj.id.indexOf('column')) {
  1657. _obj = new Column(line, obj.points2d, links)
  1658. // 创建线段中的柱子
  1659. line.__columns.push(_obj)
  1660. columns.push(_obj)
  1661. }
  1662. _obj.origin = obj
  1663. var update = obj.update2d
  1664. /**
  1665. * x 偏移 y偏移
  1666. */
  1667. obj.update2d = function(x, y) {
  1668. update && update()
  1669. // var ret = renderer.transScreenPoint({x: x, y: y})
  1670. var args = [
  1671. {x: 0, y: 0},
  1672. {x: -x, y: -y},
  1673. {
  1674. vector: util.lineVector(obj),
  1675. scalePoint: 0 //0为移动 1为放大缩小
  1676. },
  1677. renderer
  1678. ]
  1679. _obj._move.apply(_obj, args)
  1680. }
  1681. })
  1682. // 3D改变同步状态改变2D方法注册
  1683. update2d(wall, line, renderer)
  1684. })
  1685. if (!wall.__additional__detection) {
  1686. // 创建拦截,拦截移动墙面碰到门窗
  1687. wall.__additional__detection = true
  1688. var detection = wall.detection.bind(wall)
  1689. wall.detection = function (movePos) {
  1690. if (detection(movePos)) {
  1691. return true
  1692. }
  1693. var line = movePos.line
  1694. // var objs = [(line.__doors || []).concat(line.__casements || [])]
  1695. var objs = []
  1696. var reject = false
  1697. for (var i = 0; i < line2Ds.length; i++) {
  1698. if (line2Ds[i].id === line.linkedLineID[0] || line2Ds[i].id === line.linkedLineID[1]) {
  1699. line2Ds[i].__doors && objs.push.apply(objs, line2Ds[i].__doors)
  1700. line2Ds[i].__casements && objs.push.apply(objs, line2Ds[i].__casements)
  1701. line2Ds[i].__columns && objs.push.apply(objs, line2Ds[i].__columns)
  1702. }
  1703. }
  1704. objs.forEach(function (obj) {
  1705. if (!obj.detection()) {
  1706. reject = true
  1707. }
  1708. })
  1709. return reject
  1710. }
  1711. }
  1712. return doors.concat(casements).concat(columns)
  1713. }
  1714. return function (dom, line2Ds, cameras) {
  1715. var renderer = new Renderer(dom, line2Ds)
  1716. var wall = new Wall(line2Ds, cameras)
  1717. // 当墙面位置发生改变时同步3D
  1718. wall.listen('changePosition', function(line2D) {
  1719. line2Ds.forEach(function (line) {
  1720. if (line.id === line2D.linkedLineID[0] ||
  1721. line.id === line2D.linkedLineID[1]) {
  1722. update3D(line)
  1723. }
  1724. })
  1725. update3D(line2D)
  1726. })
  1727. renderer.models.push(wall)
  1728. renderer.render()
  1729. function load () {
  1730. var objs = loadComponents(line2Ds, wall, renderer)
  1731. // 当门窗位置大小发生改变时同步3D
  1732. objs.forEach(function (obj) {
  1733. obj.listen('changePoints', function () {
  1734. if (obj.origin.update3D) {
  1735. obj.origin.update3D()
  1736. } else {
  1737. // console.log(obj.origin, '组件未绑定更新3D方法')
  1738. }
  1739. })
  1740. })
  1741. renderer.models.push.apply(renderer.models, objs)
  1742. renderer.render()
  1743. }
  1744. load();
  1745. var position;
  1746. return {
  1747. // 设置当前位置
  1748. position: function (posPoint, angle) {
  1749. if (!position) {
  1750. position = new Position(posPoint, angle)
  1751. renderer.models.push(position)
  1752. } else {
  1753. position.point = posPoint
  1754. position.angle = angle
  1755. }
  1756. renderer.render()
  1757. },
  1758. renderer: renderer,
  1759. updateComponents: load
  1760. }
  1761. }
  1762. })();