Browse Source

修改传入场景

bill 4 years ago
parent
commit
5e6468b69e
52 changed files with 3450 additions and 1015 deletions
  1. 127 46
      lang/_zh.ts
  2. 7 4
      package-lock.json
  3. 1 0
      package.json
  4. 420 0
      src/CAD/calcRoom.js
  5. 6 0
      src/CAD/core/additional/calcRoom.js
  6. 12 0
      src/CAD/core/additional/customized.ts
  7. 103 32
      src/CAD/core/additional/dataHandle.ts
  8. 0 1
      src/CAD/core/additional/eleAttr.ts
  9. 33 5
      src/CAD/core/additional/insert.ts
  10. 148 75
      src/CAD/core/additional/label.ts
  11. 19 14
      src/CAD/core/additional/rote.ts
  12. 10 11
      src/CAD/core/additional/screenshot.ts
  13. 22 17
      src/CAD/core/additional/sign.ts
  14. 13 3
      src/CAD/core/additional/styleSet.ts
  15. 9 6
      src/CAD/core/additional/transform.ts
  16. 8 1
      src/CAD/core/architecture/bayCase.ts
  17. 9 8
      src/CAD/core/architecture/casement.ts
  18. 27 7
      src/CAD/core/architecture/door/index.ts
  19. 100 0
      src/CAD/core/architecture/doubleDoor.ts
  20. 1 1
      src/CAD/core/architecture/groundCase.ts
  21. 3 2
      src/CAD/core/architecture/linearch.ts
  22. 21 14
      src/CAD/core/architecture/slideDoor.ts
  23. 38 17
      src/CAD/core/base/cad.ts
  24. 43 1
      src/CAD/core/base/processing/index.ts
  25. 0 1
      src/CAD/core/base/processing/pointOper.ts
  26. 14 3
      src/CAD/core/base/processing/toData.ts
  27. 33 6
      src/CAD/core/base/processing/toEle.ts
  28. 2 3
      src/CAD/core/base/renderer.ts
  29. 6 0
      src/CAD/core/constant/Element.ts
  30. 41 0
      src/CAD/core/constant/Label.ts
  31. 14 9
      src/CAD/core/core/element.ts
  32. 9 8
      src/CAD/core/core/fixedpoint.ts
  33. 1 0
      src/CAD/core/core/line.ts
  34. 1 16
      src/CAD/core/core/wallfixedline.ts
  35. 3 2
      src/CAD/core/core/wallline.ts
  36. 86 3
      src/CAD/core/geometry.ts
  37. 5 1
      src/CAD/core/index.ts
  38. 111 0
      src/CAD/core/label/SelectPoint.ts
  39. 11 8
      src/CAD/core/label/gauge.ts
  40. 66 0
      src/CAD/core/label/mapping.ts
  41. 3 3
      src/CAD/core/label/sign.ts
  42. 23 46
      src/CAD/core/label/tagging.ts
  43. 34 27
      src/CAD/eleAttr.ts
  44. 13 5
      src/CAD/index.ts
  45. 18 7
      src/CAD/other.ts
  46. 175 139
      src/CAD/screenAdapt.ts
  47. 22 14
      src/CAD/toCanvas.ts
  48. 1 1
      static/data.js
  49. 699 445
      static/data.json
  50. 768 0
      static/data1.json
  51. 3 3
      static/index.html
  52. 108 0
      static/t-knpQzAP.json

+ 127 - 46
lang/_zh.ts

@@ -9,7 +9,9 @@ export default {
         "guide": "自动导览",
         "sign": "地面Logo",
         "walk": "漫游可行",
-        "model": "修整模型",
+        "model": "3D模型",
+        "cad": "户型图",
+        "data": "数据对接",
         "custom": "上传下载",
         "videos": "添加视频",
         "vrhouse": "看房 4Dkankan",
@@ -59,7 +61,7 @@ export default {
             "vr_fail_safari_tips": "浏览器未能检测到转动。为完整体验VR效果,请打开 “设置” > “Safari” > “隐私和安全” 下的 “运动和方向访问” 开关,然后刷新此页面。",
             "loading_bottom_text": "四维时代提供技术支持",
             "vr_fail_reopen_tips": "运动和方向访问失败。您需要完全关闭此应用,然后再次打开,并允许访问运动与方向",
-            "add_music_title":"添加背景音乐",
+            "add_music_title": "添加背景音乐",
             "add_music_tips": "支持MP3、WAV等音频格式,不超过5MB",
             "re_add_music": "重新添加",
             "re_add_title": "重新添加背景音乐",
@@ -235,10 +237,10 @@ export default {
             "save": "保存当前设置",
             "hide": "隐藏该点位置",
             "show": "显示该点位置",
-            "pano_tips":"提示:您隐藏了初始画面点位,此操作将使进入场景后无法漫游。"
+            "pano_tips": "提示:您隐藏了初始画面点位,此操作将使进入场景后无法漫游。"
         },
         "model": {
-            "__name": "修整模型",
+            "__name": "3D模型",
             "cad": "CAD视角",
             "cad_download": "平面图下载",
             "view": "切换视角",
@@ -248,6 +250,7 @@ export default {
             "title_other": "其他",
             "attribute": "属性",
             "door": "门",
+            "double_door": "门",
             "slideDoor": "移门",
             "casement": "窗",
             "bayCase": "飘窗",
@@ -261,7 +264,7 @@ export default {
             "tagging_name_tips": "请输入名称",
             "tagging_area_tips": "输入面积,支持小数点后面两位",
             "direction": "指南针",
-            "wallLine": "墙关联房间",
+            "wallLine": "墙属性",
             "widget_delete": "{widget}将被删除",
             "panel_btn_default": "恢复默认",
             "panel_btn_delete": "删除部件",
@@ -274,6 +277,7 @@ export default {
             "attr_showContent": "标注面积",
             "attr_top": "顶部",
             "attr_bottom": "底部",
+            "attr_estart": "入户门",
             "success": "成功添加{widget}",
             "error_location": "当前位置无法添加{widget}",
             "error_outdoor": "户外无法添加{widget}",
@@ -281,7 +285,71 @@ export default {
             "error_widget": "当前位置不可添加{widget}",
             "enter_adjust_floor": "进入地面高度调节模式",
             "exit_adjust_floor": "退出地面高度调节模式",
-            "color_title":"量角器颜色:"
+            "color_title": "量角器颜色:"
+        },
+        "cad": {
+            "__name": "户型图",
+            "name": "户型图",
+            "no_tip": "不再提示",
+            "reset": "重置",
+            "cad_download": "户型图下载",
+            "cad_download_ing": "下载中…",
+            "label_tip": "点击右键或Esc键可以退出添加标注。",
+            "wall_tip": "点击右键或Esc键可以退出画墙。",
+            "save_undf_tip": "无法保存空户型图。",
+            "reload_tip": "即将导入由模型生成的户型图,此操作会清空现有户型,是否继续?",
+            "reset_tip": "此操作会清空现有户型,是否继续?",
+            "title_door": "门窗",
+            "title_component": "构建",
+            "title_wall": "画墙",
+            "title_other": "标注",
+            "border_wall": "外墙",
+            "wall": "内墙",
+            "attribute": "属性",
+            "door": "门",
+            "slideDoor": "移门",
+            "doubleDoor": "双开门",
+            "casement": "窗",
+            "bayCase": "飘窗",
+            "groundCase": "落地窗",
+            "column": "柱子",
+            "furnColumn": "框架柱",
+            "furnFlue": "烟道",
+            "point": "点",
+            "line": "墙",
+            "tagging": "单个",
+            "un_data_tip": "无法下载空户型图,请先绘制。",
+            "taggings": "多个",
+            "tagging_name_tips": "请输入名称",
+            "tagging_custom_name_tips": "自定义房间名称",
+            "tagging_area_tips": "输入面积,支持小数点后面两位",
+            "direction": "指南针",
+            "wallLine": "墙属性",
+            "widget_delete": "{widget}将被删除",
+            "panel_btn_default": "恢复默认",
+            "panel_btn_delete": "删除部件",
+            "attr_angle": "旋转角度",
+            "attr_within": "翻转方向",
+            "attr_ewidth": "宽度",
+            "attr_eheight": "高度",
+            "attr_tick": "厚度",
+            "attr_showTitle": "标注名称",
+            "attr_showContent": "标注面积",
+            "attr_top": "顶部",
+            "attr_bottom": "底部",
+            "attr_estart": "入户门",
+            "success": "成功添加{widget}",
+            "error_location": "当前位置无法添加{widget}",
+            "error_outdoor": "户外无法添加{widget}",
+            "error_something": "当前位置点有建筑,无法添加{widget}",
+            "error_widget": "当前位置不可添加{widget}",
+            "enter_adjust_floor": "进入地面高度调节模式",
+            "exit_adjust_floor": "退出地面高度调节模式",
+            "color_title": "量角器颜色:",
+            "hall_tests": '整套,客厅,走廊,餐厅,起居室,客餐厅,玄关,门厅',
+            "room_tests": '主卧,儿童房,次卧,客卧,老人房,卧室',
+            "other_tests": '书房,厨房,卫生间,多功能室,阳台,储物间,步入式衣柜,外景,露台(无顶),影视间,入房花园',
+            "rotate":"旋转",
         },
         "videos": {
             "__name": "添加视频",
@@ -297,8 +365,8 @@ export default {
             "recoverRatioTip": "恢复视频文件原始长宽比"
         },
         "custom": {
-            "model_title":"模型下载",
-            "uploading":"文件上传中...",
+            "model_title": "模型下载",
+            "uploading": "文件上传中...",
             "download": "原始模型下载",
             "download_panos": "下载点位图",
             "upload": "修改模型上传",
@@ -322,14 +390,14 @@ export default {
             "ball_video_upload_tips": "上传后点击“保存并发布”即生效",
             "ball_video_download_tips": "请勿修改视频名称和格式",
             "ball_video_upload_box_tips": "球幕视频支持MP4格式,不超过1024M",
-            "upload_title":"上传文件",
+            "upload_title": "上传文件",
             "upload_format_error": "文件格式错误,请重新上传",
             "upload_name_error": "文件名称错误,请重新上传",
             "upload_success": "上传成功,保存并发布后才能生效",
             "upload_code_5017": "上传模型失败,请参照右侧教程",
             "upload_code_5018": "zip文件只能有一层目录或无目录",
             "upload_code_5019": "必须有且仅有一个obj和mtl文件",
-            "upload_code_5020": "贴图需控制在1.5M以内,obj文件需要控制在3M以内。",
+            "upload_code_5020": "贴图需控制在1.5M以内,obj文件需要控制在20M以内。",
             "upload_code_5012": "数据不正常",
             "upload_code_5023": "上传文件格式不正确,只能是jpg或mp4格式",
             "download_tips": "下载后名称与格式请勿修改",
@@ -337,52 +405,64 @@ export default {
         },
         "vrhouse": {
             "__name": "VR看房",
-            "linkto_management": "前往看房管理后台",
+            "linkto_management": "前往看房管理后台",
             "refer": "刷新",
             "scene_link": "场景链接"
         },
         "business": {
             "__name": "商圈模块",
             "list_title": "场景热点列表",
+            "list_unf": "当前场景没有热点",
+            "add_tip_info": "请在场景中添加热点后,再绑定热点",
             "linkto_management": "前往看店管理后台",
             "refer": "刷新",
-            "scene_link": "场景链接"
+            "scene_link": "场景链接",
+            "explain": "说明",
+            "shopexplain": {
+                "1": "当前商品数据来源于场景绑定的4DKanKan店铺商品数据,如需增加请点击",
+                "2": "此处跳转"
+            },
+            "select_style": "选择热点样式",
+            "join_info": "关联商品信息",
+            "add_com": "添加商品",
+            "join_info_show": "关联商品会在热点中展示",
+            "select_com": "选择商品"
         },
-        "link":{
+        "link": {
             "__name": "跳转关联",
-            "title1":"锁定关联点",
-            "title2":"编辑关联点",
-            "title3":"全景图关联",
-            "list_text":" 已关联场景({l_count}), 全景图({p_count})",
-            "btn_new_text":"添加关联点",
-            "btn_add_title":"关联点定位",
-            "btn_add_text":"确定关联点位置",
-            "btn_add_desc":"将关联点标记并拖动到合适的位置。",
-            "btn_edit_text":"修改关联点位置",
+            "title1": "锁定关联点",
+            "title2": "编辑关联点",
+            "title3": "全景图关联",
+            "list_text": " 已关联场景({l_count}), 全景图({p_count})",
+            "btn_new_text": "添加关联点",
+            "btn_add_title": "关联点定位",
+            "btn_add_text": "确定关联点位置",
+            "btn_add_desc": "将关联点标记并拖动到合适的位置。",
+            "btn_edit_text": "修改关联点位置",
             "style": "关联点样式",
             "style_name": "样式",
             "style_desc": "支持自定义图标,建议尺寸为128x128 像素,格式为jpg/png。",
             "style_dele": "是否删除该样式?<br />如该样式在其它关联点使用,也将被删除",
-            "desc_title":"描述",
-            "desc_tips":"请输入描述内容",
-            "desc_require":"请输入描述内容",
-            "type":"选择关联类型",
+            "desc_title": "描述",
+            "desc_tips": "请输入描述内容",
+            "desc_require": "请输入描述内容",
+            "type": "选择关联类型",
             "type_photo": "支持上传宽高比为2:1的单张全景图片,建议像素不小于6000x3000像素,文件不超过120M。",
-            "type_photo_require":"请上传全景图",
+            "type_photo_require": "请上传全景图",
             "type_link": "请输入目标场景链接",
             "type_link_tips": "http(s)://",
-            "type_link_require": "请输入场景链接",
-            "enter_title":"进入画面",
-            "enter_require":"请设置进入画面",
-            "enter_btn_text":"设置进入画面",
-            "outer_title":"跳出点位置",
-            "outer_style":"跳出点样式",
-            "outer_desc":"支持自定义图标,建议尺寸为128x128像素,格式为jpg/png。",
-            "outer_require":"请设置跳出点位置",
-            "outer_btn_text":"设置跳出点位置",
-            "links_title":"选择全景图",
-            "links_tips":"选择全景图,拖动到左侧画面相应位置,进行跳转设置。",
-            "links_cancel_tips":"取消关联设置"
+            "type_link_require": "请输入需要跳转的场景链接",
+            "enter_title": "进入画面",
+            "enter_require": "请设置进入画面",
+            "enter_btn_text": "设置进入画面",
+            "outer_title": "跳出点位置",
+            "outer_style": "跳出点样式",
+            "outer_desc": "支持自定义图标,建议尺寸为128x128像素,格式为jpg/png。",
+            "outer_require": "请设置跳出点位置",
+            "outer_btn_text": "设置跳出点位置",
+            "links_title": "选择全景图",
+            "links_tips": "选择全景图,拖动到左侧画面相应位置,进行跳转设置。",
+            "links_cancel_tips": "取消关联设置"
         }
     },
     "login": {
@@ -438,8 +518,9 @@ export default {
         "custom": "自定义",
         "back": "返回",
         "will_delete": "将被删除",
-        "setup":"设置",
+        "setup": "设置",
         "exit": "退出",
+        "size": "大小",
         "music": {
             "__name": "背景音乐",
             "none": "无",
@@ -524,14 +605,14 @@ export default {
         "password_tips": "密码",
         "password_require": "请输入密码"
     },
-    components:{
-        user_guid:{
+    "components": {
+        "user_guid": {
             "__name": "用户引导",
-            "title":"操作提示",
-            "pano":"行走<br />点击任意方向移动",
-            "rotate":"旋转视角<br />左右滑动屏幕,旋转视觉",
+            "title": "操作提示",
+            "pano": "行走<br />点击任意方向移动",
+            "rotate": "旋转视角<br />左右滑动屏幕,旋转视觉",
             "zoom": "缩放<br />双指滑动放大或缩小视图",
-            "set":"我知道了"
+            "set": "我知道了"
         }
     }
 }

+ 7 - 4
package-lock.json

@@ -5342,8 +5342,7 @@
     },
     "performance-now": {
       "version": "2.1.0",
-      "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz",
-      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+      "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz"
     },
     "picomatch": {
       "version": "2.1.1",
@@ -7190,8 +7189,7 @@
     },
     "rgbcolor": {
       "version": "1.0.1",
-      "resolved": "https://registry.npm.taobao.org/rgbcolor/download/rgbcolor-1.0.1.tgz",
-      "integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0="
+      "resolved": "https://registry.npm.taobao.org/rgbcolor/download/rgbcolor-1.0.1.tgz"
     },
     "rimraf": {
       "version": "2.7.1",
@@ -7970,6 +7968,11 @@
         "has-flag": "^3.0.0"
       }
     },
+    "svg-innerhtml-polyfill": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/svg-innerhtml-polyfill/-/svg-innerhtml-polyfill-1.1.0.tgz",
+      "integrity": "sha512-JvaA4afptmGtbknc8brmBd4BzSdHHjFaqOTWGw3JQJ9Arhv4g0YAyMCb4R4TQWyJThhJolELWNg9c4q5aWR3Bg=="
+    },
     "tapable": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",

+ 1 - 0
package.json

@@ -41,6 +41,7 @@
     "mathjs": "^5.10.0",
     "ol": "^5.3.0",
     "proj4": "^2.5.0",
+    "svg-innerhtml-polyfill": "^1.1.0",
     "three": "^0.96.0",
     "three-obj-loader": "^1.1.3",
     "three-stats": "^1.0.1"

+ 420 - 0
src/CAD/calcRoom.js

@@ -0,0 +1,420 @@
+import Point from './core/core/fixedpoint'
+import { segmentsIntr, lineDis, lineCenter, lineVector } from './core/geometry'
+
+//颜色对象
+function Color(){
+  let r = Math.floor(Math.random()*255);
+  let g = Math.floor(Math.random()*255);
+  let b = Math.floor(Math.random()*255);
+  return 'rgba('+ r +','+ g +','+ b +',0.8)';
+}
+
+function handleData(data, cad) {
+  let lines = data.wall
+  let points = data["vertex"]
+
+  for (let i = 0; i < points.length; i++) {
+    let point = points[i]
+    let delPoints = points.filter(cpoint => 
+      cpoint !== point && (
+        cpoint.x === point.x && cpoint.y === point.y ||
+        lineDis({points: [cpoint, point]}) < 0.1
+      )
+    )
+
+    delPoints.forEach(delPoint => {
+      lines.forEach(line => {
+        if (line.p1 === delPoint.id) {
+          line.p1 = point.id
+        }
+        if (line.p2 === delPoint.id) {
+          line.p2 = point.id
+        }
+      })
+      ~points.indexOf(delPoint) && points.splice(points.indexOf(delPoint), 1)
+    })
+  }
+
+
+  for (let i = 0; i < lines.length; i++) {
+    let line = lines[i]
+    if (line.p1 === line.p2) {
+      [ 'case', 'door', 'slideDoor', 'column','groundCase', 'bayCase'].forEach(attr => {
+        for (let i = 0; i < data[attr] && data[attr].length; i++) {
+          let obj = data[attr][i]
+          if (obj.line === line.id) {
+            data[attr].splice(i--, 1)
+          }
+        }
+      })
+      lines.splice(i--, 1)
+    }
+  }
+
+  let split = 10
+
+  for (let i = 0; i < lines.length; i++) {
+    let oline = lines[i]
+    let p1 = points.find(({id}) => id === lines[i].p1);
+    let p2 = points.find(({id}) => id === lines[i].p2);
+    let line = {points: [p1, p2]}
+    let j = 0
+
+
+    for (j = i + 1; j < lines.length; j++) {
+      let ocline = lines[j]
+      if (ocline === oline) continue;
+      let cp1 = points.find(({id}) => id === lines[j].p1);
+      let cp2 = points.find(({id}) => id === lines[j].p2);
+      if (p1 === cp1 || p1 === cp2 || p2 === cp1 || p2 === cp2) continue;
+
+      let cline = {points: [cp1, cp2]}
+      let jpoint = segmentsIntr(line, cline)
+
+      if (
+        lineDis({points: [p1, jpoint]}) < 0.1 || 
+        lineDis({points: [p2, jpoint]}) < 0.1 || 
+        lineDis({points: [cp1, jpoint]}) < 0.1 || 
+        lineDis({points: [cp2, jpoint]}) < 0.1
+      ) continue
+
+      if (!jpoint) continue;
+
+      let pointId = Math.max(...points.map(({id}) => id)) + 1
+      let maxLine = Math.max(...lines.map(({id}) => id))
+
+
+      points.push(({...jpoint, id: pointId}))
+      lines.splice(
+        lines.indexOf(oline), 1,
+        { p1: p1.id, p2: pointId, id: ++maxLine },
+        { p1: p2.id, p2: pointId, id: ++maxLine },
+      )
+      lines.splice(
+        lines.indexOf(ocline), 1,
+        { p1: cp1.id, p2: pointId, id: ++maxLine },
+        { p1: cp2.id, p2: pointId, id: ++maxLine }
+      )
+      
+      break;
+    }
+
+    if (j !== lines.length) {
+      i --
+    }
+  }  
+  return data
+}
+
+export default function calcRoom(data, cad) {
+  data = handleData(data, cad)
+
+  let startTime = Date.now()
+
+  console.log('开始计算房间')
+  let _roomsEdges = [];
+  let _roomsEdgesPoints = [];
+  let _roomsWalls = [];
+  let _roomsPoints = [];
+  let _roomsCenter = [];
+  let _roomsBoundingBox = [];
+  let _roomStartEdge = [];
+  let _roomMappings = [];
+  let _originRooms = [];
+  //分房间
+  //wallIds里的元素有三个属性:id,p1,p2,p1和p2对应的是墙端点的id
+  function getAllRooms(wallIds) {
+    for (let i = 0; i < wallIds.length; ++i) {
+      let exceptWalls = [];
+      let exceptPoints = [];
+      let ringPoints = [];   //存放的是顶点
+      let ringWalls = [];   //存放的是墙面
+      for (let k = 0; k <= i; ++k) {
+        exceptWalls.push(k);
+      }
+      let wall1 = wallIds[i];
+      let startPointId = wall1.p1.id;
+      let endPointId = wall1.p2.id;
+      ringPoints.push(endPointId);
+      ringWalls.push(wall1.id);
+      let currentPointId = null;
+      for (let j = i + 1; j < wallIds.length; ++j) {
+        let wall2 = wallIds[j];
+        if (startPointId == wall2.p1.id || startPointId == wall2.p2.id) {
+          //相连
+          let _ringPoints = JSON.parse(JSON.stringify(ringPoints));
+          let _ringWalls = JSON.parse(JSON.stringify(ringWalls));
+          let _exceptWalls = JSON.parse(JSON.stringify(exceptWalls));
+          let _exceptPoints = JSON.parse(JSON.stringify(exceptPoints));
+          let _startPointId = startPointId;
+          _ringPoints.push(startPointId);
+          _ringWalls.push(wall2.id);
+          _exceptWalls.push(j);
+          if (_startPointId == wall2.p1.id) {
+            currentPointId = wall2.p2.id;
+          }
+          else {
+            currentPointId = wall2.p1.id;
+          }
+          _exceptPoints.push(_startPointId);
+          addLineToRoom(wallIds, endPointId, _ringPoints, _ringWalls, _exceptWalls, _exceptPoints, currentPointId);
+        }
+      }
+    }
+  }
+  //roomPoints房间的顶点
+  //roomWalls房间的墙
+  //exceptWalls不需要考虑的墙
+  //exceptPoints不需要考虑的端点
+  //currentPointId当前需要考虑的顶点,不在exceptPoints里
+  function addLineToRoom(wallIds, begin, roomPoints, roomWalls, exceptWalls, exceptPoints, currentPointId) {
+    for (let i = 0; i < wallIds.length; ++i) {
+      if (exceptWalls.indexOf(i) > -1 || exceptPoints.indexOf(currentPointId) > -1) {
+        continue;
+      }
+      let wall = wallIds[i];
+      let startPointId = wall.p1.id;
+      let endPointId = wall.p2.id;
+      if (currentPointId == startPointId || currentPointId == endPointId) {
+        let _roomPoints = JSON.parse(JSON.stringify(roomPoints));
+        let _roomWalls = JSON.parse(JSON.stringify(roomWalls));
+        let _exceptWalls = JSON.parse(JSON.stringify(exceptWalls));
+        let _exceptPoints = JSON.parse(JSON.stringify(exceptPoints));
+        let _currentPointId = currentPointId;
+        _roomWalls.push(wall.id);
+        _roomPoints.push(currentPointId);
+        _exceptWalls.push(i)
+        _exceptPoints.push(currentPointId);
+        if (_currentPointId == startPointId) {
+          _currentPointId = endPointId;
+        }
+        else if (_currentPointId == endPointId) {
+          _currentPointId = startPointId;
+        }
+        if (begin == _currentPointId) {
+          _roomsPoints.push(_roomPoints);
+          _roomsWalls.push(_roomWalls);
+        }
+        else {
+			//if(_roomWalls[2] == 45&&_roomWalls[26] == 13){
+				//console.log('test')
+			//}
+          addLineToRoom(wallIds, begin, _roomPoints, _roomWalls, _exceptWalls, _exceptPoints, _currentPointId)
+        }
+      }
+    }
+  }
+
+  //获取最小多边形
+  function removeBigPolygon() {
+    for (var i = 0; i < _roomsPoints.length; ++i) {
+      for (var j = i + 1; j < _roomsPoints.length; ++j) {
+        if (isInPolygonForPolygon(_roomsWalls[i], _roomsWalls[j], _roomsPoints[i], _roomsPoints[j])) {
+          _roomsPoints.splice(j, 1);
+          _roomsWalls.splice(j, 1);
+          --j;
+        }
+        else if (isInPolygonForPolygon(_roomsWalls[j], _roomsWalls[i], _roomsPoints[j], _roomsPoints[i])) {
+          _roomsPoints.splice(i, 1);
+          _roomsWalls.splice(i, 1);
+          --i;
+          --j;
+          break;
+        }
+      }
+    }
+  }
+  //arr1是否被arr2包围
+  function isInPolygonForPolygon(arrwalls1, arrwalls2, arrpoints1, arrpoints2) {
+    let arrpt2 = [];
+    for (let i = 0; i < arrpoints2.length; ++i) {
+      let point = arrpoints2[i];
+      arrpt2.push(point);
+    }
+    let flag = true;   //防止误杀回字形
+    for (var i = 0; i < arrpoints1.length; ++i) {
+      if (arrwalls2.indexOf(arrwalls1[i]) > -1) {
+        flag = false;   //存在重合的墙
+        continue;
+      }
+      let wall = arrwalls1[i];
+      var p1 = wall.p1;
+      var p2 = wall.p2;
+      var p3 = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };
+      if (isInPolygonForPoint(p1, arrpt2) && isInPolygonForPoint(p2, arrpt2) && isInPolygonForPoint(p3, arrpt2)) {
+        continue;
+      }
+      else {
+        return false;
+      }
+    }
+    if (flag) {
+      //可能是回字形了
+      //因为房间可能是多余的,要删除,所以只能先这么存储
+      let _roomMapping = [];
+      _roomMapping.push(arrwalls2[0]);
+      _roomMapping.push(arrwalls2[arrwalls2.length - 1]);
+      _roomMapping.push(arrwalls1[0]);
+      _roomMapping.push(arrwalls1[arrwalls1.length - 1]);
+      _roomMappings.push(_roomMapping);
+      return false;
+    }
+    else {
+      return true;
+    }
+  }
+  function isInPolygonForPoint(p, points) {
+    for (var i = 0; i < points.length; ++i) {
+      let point = points[i];
+      if (equalForPoint(p, point)) {
+        return true;
+      }
+    }
+    if (isPointInPoly(p, points)) {
+      return true;
+    }
+    else {
+      return false;
+    }
+  }
+  //找房间包含关系,因为接下来房间内,墙的顺序会改
+  function getIncludeFromRoom() {
+    let mappings = [];
+    for (let i = 0; i < _roomMappings.length; ++i) {
+      let _roomMapping = _roomMappings[i];
+      let mapping = [];
+      mapping[0] = null;
+      mapping[1] = null;
+      for (let j = 0; j < _roomsWalls.length; ++j) {
+        if (_roomMapping[0] == _roomsWalls[j][0] && _roomMapping[1] == _roomsWalls[j][_roomsWalls[j].length - 1]) {
+          mapping[0] = j;
+        }
+        else if (_roomMapping[2] == _roomsWalls[j][0] && _roomMapping[3] == _roomsWalls[j][_roomsWalls[j].length - 1]) {
+          mapping[1] = j;
+        }
+        if (mapping[0] != null && mapping[1] != null) {
+          break;
+        }
+      }
+      if (mapping[0] != null && mapping[1] != null) {
+        mappings.push(mapping);
+      }
+    }
+    _roomMappings = mappings;
+  }
+
+  function equalForPoint(p1, p2) {
+    if (p1.x == p2.x && p1.y == p2.y) {
+      return true;
+    }
+    else {
+      return false;
+    }
+  }
+
+
+  function isPointInPoly(point, points) {
+    var x = point.x, y = point.y;
+    var inside = false;
+    for (var i = 0, j = points.length - 1; i < points.length; j = i++) {
+      var pt1 = points[i];
+      var pt2 = points[j];
+      var xi = pt1.x, yi = pt1.y;
+      var xj = pt2.x, yj = pt2.y;
+      var intersect = ((yi > y) != (yj > y))
+        && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
+      if (intersect) inside = !inside;
+    }
+    return inside;
+  }
+
+  // 将wall p1 p2字段转化为真实点坐标
+  let wall = data.wall.map(line => {
+    return {
+      p1: data.vertex.find(({id}) => line.p1 === id),
+      p2: data.vertex.find(({id}) => line.p2 === id),
+      id: line.id
+    }
+  })
+
+
+  getAllRooms(wall)
+  
+
+  _roomsPoints = _roomsPoints.map(points => points.map(point => data.vertex.find(({id}) => point === id)))
+  // 将_roomsWalls所有的p1 p2转化为真实坐标
+  _roomsWalls = _roomsWalls.map(walls => {
+    return walls.map(cid => wall.find(({id}) => cid === id))
+  })
+
+
+  removeBigPolygon()
+  getIncludeFromRoom()
+
+  //计算多边形中心
+  //后续要修改,应该是重心才合理
+  function getPolygonAreaCenter(points){
+    var sum_x = 0;
+    var sum_y = 0;
+    var sum_area = 0;
+    var p1 = points[1];
+    for (var i = 2; i < points.length; i++) {
+        var p2 = points[i];
+        var area = Area(points[0], p1, p2);
+        sum_area += area;
+        sum_x += (points[0].x + p1.x + p2.x) * area;
+        sum_y += (points[0].y + p1.y + p2.y) * area;
+        p1 = p2;
+    }
+    var xx = sum_x / sum_area / 3;
+    var yy = sum_y / sum_area / 3;
+    return {x:xx, y:yy};
+  }
+
+  function Area(p0,p1,p2) {
+      var area = 0.0 ;
+      area = p0.x * p1.y + p1.x * p2.y + p2.x * p0.y - p1.x * p0.y - p2.x * p1.y - p0.x * p2.y;
+      return area / 2 ;
+  }
+
+  data.room = _roomsWalls.map((wall, i) => {
+    return {
+      wall: wall.map(({id}) => id),
+      ground: _roomsPoints[i]
+    }
+  })
+
+
+
+  let endTime = Date.now()
+  console.warn('计算完毕,耗时' + (endTime - startTime) )
+
+
+  
+  if (cad) {
+    window.testCenterPoints && cad.processing.render.remove(...window.testCenterPoints)
+    window.testCenterPoints = _roomsPoints.map(points => {
+      // points = points.map(pid => data.vertex.find(({id}) => pid === id))
+      let point = getPolygonAreaCenter(points.map(point => ({...point, y: -point.y})))
+      let color = Color();
+      let epoint = new Point({ fillColor: color, storkeColor: color, x: point.x, y: point.y, renderer: cad.processing.render })
+      cad.processing.render.push(epoint)
+      return epoint
+    })
+
+    window.testCenterPoints.forEach((point, i) => {
+      let ground = {
+        pointEles: data.room[i].ground.map(point => cad.processing.points.find(({id}) => id === point.id).ele.real),
+        lineEles: _roomsWalls[i].map(line => cad.processing.lines.find(({id}) => id === line.id).ele.real),
+        center: point.real,
+        pointData: _roomsWalls[i],
+        lineData: _roomsPoints[i]
+      }
+
+      console.log(ground)
+    })
+  }
+
+
+  return _roomsPoints
+}

+ 6 - 0
src/CAD/core/additional/calcRoom.js

@@ -1,4 +1,5 @@
 import Point from '../core/fixedpoint'
+import {isFaceContain} from '../geometry'
 
 //颜色对象
 function Color(){
@@ -280,6 +281,10 @@ export default function calcRoom(data, cad) {
       return area / 2 ;
   }
 
+  _roomsPoints = _roomsPoints.sort((room1, room2) => Number(!isFaceContain(room1, room2)))
+
+  
+
   data.room = _roomsWalls.map((wall, i) => {
     return {
       wall: wall.map(({id}) => id),
@@ -308,6 +313,7 @@ export default function calcRoom(data, cad) {
         pointData: _roomsWalls[i],
         lineData: _roomsPoints[i]
       }
+
       console.log(ground)
     })
   }

+ 12 - 0
src/CAD/core/additional/customized.ts

@@ -0,0 +1,12 @@
+import {AttachCAD as CAD} from '../index'
+
+
+
+export interface Custom{
+  edits: []
+}
+
+// 附加走过路径的label
+export const attchCustom = (cad: CAD) => {
+  cad.edits = []
+}

+ 103 - 32
src/CAD/core/additional/dataHandle.ts

@@ -1,5 +1,5 @@
 import { AttachCAD as CAD } from '../index'
-import { Data, _Point, _Line, _window, _door, _column } from '../base/processing/index'
+import { Data, _Point, _Line, _window, _door, _column, FloorData } from '../base/processing/index'
 import Stack from '../base/stack'
 import Point from '../core/point'
 import Case from '../architecture/casement'
@@ -13,13 +13,20 @@ import FurnFlue from '../furniture/flue'
 import { debounce } from '../util'
 import Line from '../core/line'
 import wallline from '../core/wallline'
+import DoubleDoor from '../architecture/doubleDoor'
+import Tagging from '../label/tagging'
+import linearch from '../architecture/linearch'
+import furn from '../furniture/furn'
+
 import calcRoom from './calcRoom'
 
 let notSave = false
 
 export interface transformRet {
-  getData: (isCalcRoom?: boolean) => Data
-  loadData: (data: Data) => void
+  getData: (isCalcRoom?: boolean) => FloorData
+  
+  loadData: (data: FloorData | Data) => void
+  getCurrentData: () => FloorData
 }
 
 type stackStatus = { previous: boolean, next: boolean }
@@ -27,6 +34,7 @@ export interface stackRet {
   getStackState: () => stackStatus
   preservation: () => void
   previous: () => stackStatus
+  stack: Stack
   next: () => stackStatus
   clearStack: () => void
 }
@@ -34,8 +42,10 @@ export interface stackRet {
 
 // 兼容V2
 const compatiblev2 = (data: any): Data => {
+
   data.column = data.column || []
   data.window = data.window || []
+  data.doubleDoor = data.doubleDoor || []
   data.door = data.door || []
   data.groundCase = data.groundCase || []
   data.bayCase = data.bayCase || []
@@ -47,7 +57,12 @@ const compatiblev2 = (data: any): Data => {
   let eles = ['column', 'window', 'door', 'groundCase', 'bayCase', 'slideDoor', 'tagging', 'furnColumn', 'furnFlue']
   if (data['vertex-xy']) {
     data.vertex = data['vertex-xy']
-    data.wall = data['segment'].map(item => ({ id: item.id, p1: item.a, p2: item.b, border: item.border }))
+    data.wall = data['segment'].map(item => ({ id: item.id, p1: item.a, p2: item.b, border: item.border, exterior: item.exterior }))
+  }
+  
+  if (data['outdoor-segment']) {
+    data.wall = data.wall.concat(data['outdoor-segment'].map(item => ({ id: item.id, p1: item.a, p2: item.b, border: item.border, exterior: true })))
+    data.vertex = data.vertex.concat(data['outdoor-vertex'])
   }
 
 
@@ -65,6 +80,7 @@ const compatiblev2 = (data: any): Data => {
         data[attr].forEach((item) => {
           if (item.line === data.wall[i].id) {
             item.line = so.id
+            console.log('update', item)
           }
         })
       })
@@ -73,6 +89,8 @@ const compatiblev2 = (data: any): Data => {
   }
 
   data.vertex = data.vertex.filter(p => data.wall.some(({ p1, p2 }) => p.id === p1 || p.id === p2))
+
+
   return data
 }
 
@@ -89,10 +107,11 @@ export const roateDataY = (data: Data): Data => {
     bayCase: [...data.bayCase],
     tagging: [...data.tagging],
     furnColumn: [...data.furnColumn],
-    furnFlue: [...data.furnFlue]
+    furnFlue: [...data.furnFlue],
+    doubleDoor: [...data.doubleDoor]
   };
 
-  [data.window, data.column, data.door, data.slideDoor, data.tagging, data.groundCase, data.bayCase, data.furnColumn, data.furnFlue].forEach((eles) => {
+  [data.window, data.column, data.door, data.slideDoor, data.tagging, data.groundCase, data.bayCase, data.furnColumn, data.furnFlue, data.doubleDoor].forEach((eles) => {
     eles.forEach((ele, i) => {
       eles[i] = {
         ...ele,
@@ -107,42 +126,91 @@ export const roateDataY = (data: Data): Data => {
 
 // 附加数据与svg转换功能
 export const attchTransform = (cad: CAD) => {
-  const processing = cad.processing
-
   // 获取数据
-  cad.getData = (isCalcRoom = false): Data => {
-    let data = roateDataY(processing.toData())
-    data.dire = cad.direction.angle
-
-    if (isCalcRoom) {
-      data = calcRoom(data, cad)
+  cad.getData = (isCalcRoom = false): FloorData => {
+    return {
+      floors: cad.processings.map(processing => {
+        let data = roateDataY(processing.toData())
+        data.dire = processing.direction.angle
+
+            
+        if (isCalcRoom) {
+          data = calcRoom(data, cad)
+        }
+        
+        return data
+      })
     }
-
-    return data
   }
   // 加载数据
-  cad.loadData = (data: Data) => {
+  cad.loadData = (ndata: FloorData | Data) => {
+    if (!(ndata as FloorData).floors) {
+      (ndata as Data).show = true
+      ndata = {floors: [(ndata as Data)]}
+    }
+    let data: FloorData = JSON.parse(JSON.stringify(ndata)) as FloorData
+
+    if (!data.floors.some(item => item.show)) {
+      data.floors[0].show = true
+    }
+    data.floors = data.floors.map(floor => roateDataY(compatiblev2(floor)))
+
+
     notSave = true
     // 卸载旧数据
-    processing.attrs.forEach(attr => {
-      while (processing[attr].length) {
-        // 同步删除
-        try {
-          processing[attr][0].ele.destroy(true, true, false)
-        } catch {
+    cad.processings.forEach(processing => {
+      // 卸载旧数据
+      processing.attrs.forEach(attr => {
+        while (processing[attr].length) {
+          // 同步删除
+          processing[attr][0].ele.destroy(true, true)
         }
+      })
+    })
+
+    data.floors.forEach(item => {
+      let processing = cad.processings.find(({id}) => id === item.id)
+      if (!processing) {
+        processing = cad.addProcessing()
+        processing.id = item.id
       }
     })
 
+    for (let i = 0; i < cad.processings.length; i++) {
+      if (!data.floors.some(({id}) => cad.processings[i].id === id)) {
+        cad.delProcessing(cad.processings[i--])
+      }
+    }
 
-    data = roateDataY(compatiblev2(data))
+    cad.processings.forEach(processing => {
+      for (let i = 0; i < processing.render.elements.length; i++) {
+        let ele = processing.render.elements[i]
+        let delAttrs = [Case, Door, SlideDoor, DoubleDoor, Column, wallline, Point, GroundCase, Tagging, BayCase, FurnColumn, FurnFlue]
+  
+        if (delAttrs.some(cls => ele instanceof cls)) {
+          processing.render.remove(ele)
+          i--
+        }
+      }
+    })
 
-    // 多余的剔除
-    data.surplus = []
 
-    processing.toEles(data)
-    cad.direction.angle = data.dire || 0
-    cad.adapt(data)
+    data.floors.forEach(item => {
+      let processing = cad.processings.find(({id}) => {
+        return id === item.id
+      })
+      item.surplus = []
+      processing.toEles(item)
+
+
+      processing.direction.__state.direct = true
+      processing.direction.angle = item.dire || 0
+      processing.direction.__state.direct = false
+      processing.direction.update()
+
+      cad.adapt(item, void 0, void 0, data.floors[0])
+    })
+
     setTimeout(() => notSave = false, 5000)
   }
 }
@@ -154,6 +222,7 @@ export const attchStack = (cad: CAD) => {
   let current = 0
   let stack = new Stack('cad_' + Date.now())
 
+  cad.stack = stack
   const getRet = (c = current): stackStatus => {
     let slen = stack.getLength()
     let previous = slen === 1 && current === 1 ? false : c > 0
@@ -165,7 +234,8 @@ export const attchStack = (cad: CAD) => {
     stack.setLength(current = 0)
   }
 
-
+  
+  cad.getCurrentData = () => stack.get(current - 1)
   // 保存
   cad.preservation = debounce(() => {
     if ((cad as any).stoppreservation) return;
@@ -176,7 +246,7 @@ export const attchStack = (cad: CAD) => {
 
     // 旧版数据,先注释
     // newData["vertex-xy"] = newData["vertex-xy"].concat(newData.surplus)
-    delete newData.surplus
+    // delete newData.surplus
 
     if (prevIndex === 0 ||
       JSON.stringify(newData) !== JSON.stringify(stack.get(prevIndex))
@@ -224,6 +294,7 @@ export const attchStack = (cad: CAD) => {
     return getRet()
   }
 
+
   cad.getStackState = getRet
 
   let destroy = cad.destroy
@@ -236,7 +307,7 @@ export const attchStack = (cad: CAD) => {
 // 附加自动保存功能
 export const autoPreservation = (cad: CAD) => {
 
-  [Point, Case, Door, Column, GroundCase, SlideDoor, BayCase, FurnColumn, Line, FurnFlue, wallline].forEach(cls => {
+  [Point, Case, Door, Column, GroundCase, SlideDoor, BayCase, FurnColumn, Line, FurnFlue, wallline, DoubleDoor].forEach(cls => {
 
     let dragend = cls.prototype.dragEnd
     cls.prototype.dragEnd = async function (...args) {

+ 0 - 1
src/CAD/core/additional/eleAttr.ts

@@ -233,7 +233,6 @@ export default (cad: AttachCAD) => {
           }
         },
         set: (val) => {
-          console.error('-------------')
           if (val !== ele.bottom) {
             let lines = cad.processing.lines.filter(({ele: cele}) => ~cele.points.indexOf(ele.points[0]) && ~cele.points.indexOf(ele.points[1]))
             // let rooms = lines.map(({room}) => room)

+ 33 - 5
src/CAD/core/additional/insert.ts

@@ -22,12 +22,12 @@ import {
 import {
   TAGGING,
   POINT, DOOR, COLUMN, CASEMENT, ARCH, SLIDEDOOR,  GROUNDCASE, BAYCASE,
-  FURNCOLUMN, FURNFLUE, DEFAULT, LINE, SEFTLINE
+  FURNCOLUMN, FURNFLUE, DEFAULT, LINE, SEFTLINE, DOUBLEDOOR
 } from '../constant/Element'
 import { i18n } from '../../../../lang/index'
 
 const ONE = [TAGGING, LINE, SEFTLINE]
-const ATTACHCOM = [POINT, DOOR, COLUMN, CASEMENT, ARCH, SLIDEDOOR, GROUNDCASE, BAYCASE]
+const ATTACHCOM = [POINT, DOOR, COLUMN, CASEMENT, ARCH, SLIDEDOOR, GROUNDCASE, BAYCASE, DOUBLEDOOR]
 const STANDCOM = [FURNCOLUMN, FURNFLUE]
 
 export interface insertRet {error: boolean, msg: string, obj?: any}
@@ -36,8 +36,6 @@ export interface insert{
 }
 
 export const attachInsert = (cad: CAD) => {
-  let processing = cad.processing
-  let renderer = processing.render
 
   // 从一条线段指定位置中获取建筑两端端点
   const getArchLinePoints = (line: WallLine, point: Point, width: number) : string | [Point, Point] => {
@@ -47,6 +45,7 @@ export const attachInsert = (cad: CAD) => {
 
   // 计算添加所需要的参数
   const calcAttachComArgs = (rpoint: Point, type) => {
+    let processing = cad.processing
     let lines = processing.lines.map(({ele}) => ele)
         .filter(line => !line.exterior)
         .map(line => ({ dis: pointLineDis(line, rpoint), line }))
@@ -96,6 +95,7 @@ export const attachInsert = (cad: CAD) => {
   }
 
   const calcStandComArgs = (rpoint: Point, type) => {
+    let processing = cad.processing
     const width = DEFAULT[type].width
     const tick = DEFAULT[type].tick
     const splitWidth = width / 2
@@ -122,6 +122,8 @@ export const attachInsert = (cad: CAD) => {
 
   // 指定屏幕添加指定类型建筑或点
   const increase = (type: string, pos: Screen, top = null, bottom = null, isDOM = false) : insertRet => {
+    let processing = cad.processing
+    let renderer = processing.render
     if (!addEle[type]) return;
 
     // 转化为真实点位
@@ -153,7 +155,7 @@ export const attachInsert = (cad: CAD) => {
       }
     }
 
-    cad.preservation()
+    cad.preservation && cad.preservation()
 
     return {error: false, msg:  i18n.t('modules.model.success', { widget: ARCH[type]}), obj}
   }
@@ -161,6 +163,7 @@ export const attachInsert = (cad: CAD) => {
   const addEle = {
     // 添加点
     [POINT]: (aline: WallLine, pos: Point) => {
+      let processing = cad.processing
       processing.insertModel = true
 
       let newPoint = processing.addPoint({
@@ -184,6 +187,7 @@ export const attachInsert = (cad: CAD) => {
 
 
     [DOOR](line: WallLine, points: [Point, Point], l, top, bottom) {
+      let processing = cad.processing
       // 添加默认的top bottom
       return processing.addDoor({
         pos: [
@@ -195,8 +199,22 @@ export const attachInsert = (cad: CAD) => {
         within: 0
       }).ele
     },
+    [DOUBLEDOOR](line: WallLine, points: [Point, Point], l, top, bottom) {
+      let processing = cad.processing
+      // 添加默认的top bottom
+      return processing.adddDoubleDoor({
+        pos: [
+          points[0].x, points[0].y, 
+          points[1].x, points[1].y
+        ],
+        line: processing.getLineId(line),
+        start: false,
+        within: 0
+      }).ele
+    },
 
     [SLIDEDOOR](line: WallLine, points: [Point, Point], l, top, bottom) {
+      let processing = cad.processing
       // 添加默认的top bottom
       return processing.addSlideDoor({
         within: 0,
@@ -209,6 +227,7 @@ export const attachInsert = (cad: CAD) => {
     },
 
     [GROUNDCASE](line: WallLine, points: [Point, Point], l, top, bottom) {
+      let processing = cad.processing
       // 添加默认的top bottom
 
       return processing.addGroundCase({
@@ -222,6 +241,7 @@ export const attachInsert = (cad: CAD) => {
 
     
     [BAYCASE](line: WallLine, points: [Point, Point], l, top, bottom) {
+      let processing = cad.processing
       // 添加默认的top bottom
 
       return processing.addBayCase({
@@ -235,6 +255,7 @@ export const attachInsert = (cad: CAD) => {
     },
 
     [CASEMENT](line: WallLine, points: [Point, Point], l, top, bottom) {
+      let processing = cad.processing
 
 
       return processing.addCase({
@@ -247,6 +268,7 @@ export const attachInsert = (cad: CAD) => {
     },
 
     [COLUMN](line: WallLine, points: [Point, Point], rpoint: Point) {
+      let processing = cad.processing
       let [p31, p32] = getDisVerticalLinePoints(line, points[0], DEFAULT[COLUMN].width)
       let p3 = p32
       // let face = room.ground.map(pid => cad.processing.points.find(({id}) => id === pid).ele)
@@ -282,6 +304,7 @@ export const attachInsert = (cad: CAD) => {
     },
 
     [TAGGING](point: Point) {
+      let processing = cad.processing
       return processing.addTagging({
         pos: [point.x, point.y],
         title: '',
@@ -292,14 +315,17 @@ export const attachInsert = (cad: CAD) => {
     },
 
     [FURNCOLUMN](pos:Array<number>, room, top, bottom) {
+      let processing = cad.processing
       return processing.addFurnColumn({pos, angle: 0}).ele
     },
 
     [FURNFLUE](pos:Array<number>, room, top, bottom) {
+      let processing = cad.processing
       return processing.addFurnFlue({pos, angle: 0}).ele
     },
     
     [LINE](point: Point) {
+      let processing = cad.processing
       const width = DEFAULT[LINE].width
       let addLine = { points: [
         { x: point.x - width / 2, y: point.y },
@@ -341,6 +367,8 @@ export const attachInsert = (cad: CAD) => {
 
   let destroy = cad.destroy
   cad.destroy = function(...args) {
+    let processing = cad.processing
+    let renderer = processing.render
     renderer = null
     processing = null
     destroy.apply(this, args)

+ 148 - 75
src/CAD/core/additional/label.ts

@@ -13,123 +13,196 @@ export interface label{
   setAngle: (angle: number) => void
   setGaugeAttrs: (args: UpdateProps) => void
   setDireAttrs: (args: StyleProps) => void
-  setGaugeModel: (type: number) => Promise<void>
+  setGaugeModel: (type: number) => Promise<Array<void>>
   gauge?: Gauge
   direction: Direction
 }
 
 // 附加显示隐藏比例尺的api,添加当前位置的label
 export const attachGauge = (cad: CAD) => {
-  let gauge: Gauge
-
-  let walls = cad.processing.lines
-  let wallPush = walls.push
-  let points = cad.processing.points
-  let pointPush = points.push
-  // 拦截点修改
-  const attchPoint = (point: Point) => {
-    point.__label_intercept = point.intercept
-    point.intercept = (...args) => {
-      gauge.update()
-      return point.__label_intercept.apply(point, args)
+  let apis = {
+    processings: [],
+    setGaugeAttrs: [],
+    showGauge: [],
+    setGaugeModel: [],
+    hideGauge: [],
+    showDire: [],
+    hideDire: [],
+    setDireAttrs: [],
+    setAngle: []
+
+  }
+  let delProcessing = cad.delProcessing
+  cad.delProcessing = (proc, ...args) => {
+    let index = apis.processings.indexOf(proc)
+    console.error('-------', index)
+    if (~index) {
+      Object.keys(apis).forEach(key => {
+        apis[key].splice(index, 1)
+      })
     }
+    return delProcessing.call(cad, proc, ...args)
   }
-  const attchLine = (line: WallLine) => {
-    line.__label_intercept = line.drag
-    line.drag = (...args) => {
+  let addProcessing = cad.addProcessing
+  cad.addProcessing = (...args) => {
+    let processing = addProcessing.call(cad, ...args)
+
+    apis.processings.push(processing)
+    let gauge: Gauge
+
+    let walls = processing.lines
+    let wallPush = walls.push
+    let points = processing.points
+    let pointPush = points.push
+    // 拦截点修改
+    const attchPoint = (point: Point) => {
+      point.__label_intercept = point.intercept
+      point.intercept = (...args) => {
+        gauge.update()
+        return point.__label_intercept.apply(point, args)
+      }
+    }
+    const attchLine = (line: WallLine) => {
+      line.__label_intercept = line.drag
+      line.drag = (...args) => {
+        gauge.update()
+        return line.__label_intercept.apply(line, args)
+      }
+    }
+
+    apis.setGaugeAttrs.push((args) => {
+      gauge.__state.direct = true
+      Object.keys(args).forEach(key => {
+        gauge[key] = args[key]
+      })
+      gauge.__state.direct = false
       gauge.update()
-      return line.__label_intercept.apply(line, args)
+    })
+
+
+    const showGaugeFn = () => {
+      if (!gauge) {
+        gauge = new Gauge({ processing: processing })
+        cad.gauge = gauge
+      }
+      // 拦截添加
+      walls.push = (...args) => {
+        let ret = wallPush.apply(walls, args)
+        gauge.update()
+        args.forEach(({ele}) => attchLine(ele))
+        return ret
+      }
+      
+      points.forEach(({ele}) => attchPoint(ele))
+      walls.forEach(({ele}) => attchLine(ele))
+      points.push = (...args) => {
+        args.forEach(({ele}) => attchPoint(ele))
+        return pointPush.apply(points, args)
+      }
+
+      processing.render.push(gauge)
     }
-  }
 
-  cad.setGaugeAttrs = (args) => {
-    gauge.__state.direct = true
-    Object.keys(args).forEach(key => {
-      gauge[key] = args[key]
+    // 显示比例尺
+    apis.showGauge.push(showGaugeFn)
+
+    showGauge && showGaugeFn()
+
+    apis.setGaugeModel.push((type) => {
+      if (gauge) {
+        gauge.surround = type === 1
+        return new Promise(r => gauge.nextTick(r))
+      } else {
+        return new Promise(r => r(void 0))
+      }
+    })
+
+    // 隐藏比例尺
+    apis.hideGauge.push(() => {
+      walls.push = wallPush
+      points.push = pointPush
+      points.forEach(({ele}) => ele.intercept = ele.__label_intercept)
+
+      processing.render.remove(gauge)
+    })
+
+
+    let direction = new Direction({angle: 0, renderer: processing.render})
+
+    processing.direction = direction
+    
+    apis.showDire.push(() => {
+      direction.show = true
+      processing.render.push(direction)
+    })
+
+    apis.hideDire.push(() => {
+      direction.show = false
+      processing.render.remove(direction)
+    })
+
+    apis.setDireAttrs.push((args) => {
+      Object.keys(args).forEach(key => {
+        direction[key] = args[key]
+      })
+      return new Promise(r => direction.nextTick(r))
     })
-    gauge.__state.direct = false
-    gauge.update()
+
+
+    return processing
+  }
+  
+  
+  cad.setGaugeAttrs = (args) => {
+    console.error(apis.setGaugeAttrs)
+    return Promise.all(apis.setGaugeAttrs.map(fn => fn(args)))
   }
 
+  let showGauge = false
   // 显示比例尺
   cad.showGauge = () => {
-    if (!gauge) {
-      gauge = new Gauge({ cad })
-      cad.gauge = gauge
-    }
-    // 拦截添加
-    walls.push = (...args) => {
-      let ret = wallPush.apply(walls, args)
-      gauge.update()
-      args.forEach(({ele}) => attchLine(ele))
-      return ret
-    }
-    
-    points.forEach(({ele}) => attchPoint(ele))
-    walls.forEach(({ele}) => attchLine(ele))
-    points.push = (...args) => {
-      args.forEach(({ele}) => attchPoint(ele))
-      return pointPush.apply(points, args)
-    }
-
-    cad.processing.render.push(gauge)
+    if (showGauge) return;
+    showGauge = true
+    apis.showGauge.forEach(fn => fn())
   }
 
   cad.setGaugeModel = (type) => {
-    if (gauge) {
-      gauge.surround = type === 1
-      return new Promise(r => gauge.nextTick(r))
-    } else {
-      return new Promise(r => r())
-    }
+    return Promise.all(apis.setGaugeModel.map(fn => fn(type)))
   }
 
+
   // 隐藏比例尺
   cad.hideGauge = () => {
-    walls.push = wallPush
-    points.push = pointPush
-    points.forEach(({ele}) => ele.intercept = ele.__label_intercept)
-
-    cad.processing.render.remove(gauge)
+    if (!showGauge) return;
+    showGauge = true
+    apis.hideGauge.forEach(fn => fn())
   }
 
   let destroy = cad.destroy
   cad.destroy = function(...args) {
     cad.hideGauge()
-    walls = null
-    wallPush = null
-    points = null
-    pointPush = null
+    showGauge = false
     destroy.apply(this, args)
   }
 
 
-  let direction = new Direction({angle: 0, renderer: cad.processing.render})
-  
   cad.showDire = () => {
-    direction.show = true
-    cad.processing.render.push(direction)
+    apis.showDire.forEach(fn => fn())
   }
 
   cad.hideDire = () => {
-    direction.show = false
-    cad.processing.render.remove(direction)
+    apis.hideDire.forEach(fn => fn())
   }
 
   cad.setDireAttrs = (args) => {
-    Object.keys(args).forEach(key => {
-      direction[key] = args[key]
-    })
-    return new Promise(r => direction.nextTick(r))
+    return Promise.all(apis.setDireAttrs.map(fn => fn(args)))
   }
 
   cad.setAngle = (angle) => {
     cad.processing.data.dire = angle
-    direction.angle = angle
-    direction.nextTick(() => {
-      cad.preservation()
-    })
+    cad.processing.direction.angle = angle
+    // cad.processing.direction.nextTick(() => {
+    //   cad.preservation()
+    // })
   }
-
-  cad.direction = direction
 }

+ 19 - 14
src/CAD/core/additional/rote.ts

@@ -15,25 +15,35 @@ export interface Local{
 
 // 附加走过路径的label
 export const attachRote = (cad: CAD) => {
-  let rote = new Rote({renderer: cad.processing.render, local: []})
-  rote.zIndex = 2
-  cad.processing.render.push(rote)
-  
-  rote.setActive = active => {
-    cad.activeRoute(rote.local.indexOf(active))
+  let addProcessing = cad.addProcessing
+  cad.addProcessing = (...args) => {
+    let processing = addProcessing.call(cad, ...args)
+
+    let rote = new Rote({renderer: processing.render, local: []})
+    rote.zIndex = 2
+    processing.render.push(rote)
+    
+    rote.setActive = active => {
+      cad.activeRoute(rote.local.indexOf(active))
+    }
+    return processing;
   }
 
+
   cad.showRotes = () => {
+      let rote = cad.processing.rote
     rote.show = true
     return new Promise(r => rote.nextTick(r))
   }
 
   cad.hideRotes = () => {
+    let rote = cad.processing.rote
     rote.show = false
     return new Promise(r => rote.nextTick(r))
   }
 
   cad.setRoutes = points => {
+    let rote = cad.processing.rote
     const queryTemp = (i) => {
       let point = points.slice(0, i).reverse().find(point => !point.rangn)
       if (point) {
@@ -68,6 +78,7 @@ export const attachRote = (cad: CAD) => {
   }
   // 当前正在哪个点位
   cad.activeRoute = index => {
+    let rote = cad.processing.rote
     rote.nextTick(() => {
       rote.active = rote.local[index]
     })
@@ -75,21 +86,15 @@ export const attachRote = (cad: CAD) => {
 
   // 删除点位
   cad.popRoute = index => {
+    let rote = cad.processing.rote
     rote.local.splice(index, 1)
     rote.nextTick(() => rote.local = [...rote.local])
   }
   // 清除所有点位
   cad.clearRoutes = (cb) => {
+    let rote = cad.processing.rote
     rote.local = []
     rote.dialog = 0
     rote.nextTick(() => cb && cb())
   }
-
-  
-  let destroy = cad.destroy
-  cad.destroy = function(...args) {
-    cad.clearRoutes()
-    rote = null
-    destroy.apply(this, args)
-  }
 }

+ 10 - 11
src/CAD/core/additional/screenshot.ts

@@ -19,9 +19,9 @@ export interface Screenshot {
 
 // 附加截图功能
 export const attachScreenshot = (cad: CAD) => {
-  let render = cad.processing.render
 
-  cad.screenshot = async ({width = 2048, height = 2048, bgColor = 'rgba(0,0,0,0)', data, spadding}) => {
+  cad.screenshot = async ({width = 2048, height = 2048, bgColor = 'rgba(0,0,0,0)', data, spadding, format = 'image/png'}) => {
+    let render = cad.processing.render
     let props = {...render.props}
     let image = new Image()
     let canvas = document.createElement('canvas')
@@ -41,7 +41,7 @@ export const attachScreenshot = (cad: CAD) => {
     canvas.height = height
     context.fillStyle = bgColor
     context.fillRect(0, 0, canvas.width, canvas.height)
-    return new Promise(async (resolve) => {
+    return new Promise(async (resolve, reject) => {
       // cad.hideGauge && cad.hideGauge()
       image.onload = async () => {
         // img绘制到canvas
@@ -57,7 +57,7 @@ export const attachScreenshot = (cad: CAD) => {
         // }
         
         const data = {
-          file: convertBase64UrlToBlob(canvas.toDataURL('image/png')),
+          file: convertBase64UrlToBlob(canvas.toDataURL(format)),
           width,
           height,
           left: cad.processing.render.realPointToScreen({x: Math.min(...xs), y: 0}).x,
@@ -77,15 +77,14 @@ export const attachScreenshot = (cad: CAD) => {
         // await cad.showSign()
         resolve(data)
       }
+      image.onerror = function(e) {
+        render.props = props
+        cad.padding = padding
+        render.adaptLayer()
+        reject(e)
+      }
       // 将svg载入img
       image.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(render.svg.outerHTML)))
     })
   }
-
-
-  let destroy = cad.destroy
-  cad.destroy = function(...args) {
-    render = null
-    destroy.apply(this, args)
-  }
 }

+ 22 - 17
src/CAD/core/additional/sign.ts

@@ -17,34 +17,46 @@ export const attachSign = (cad: CAD) => {
     border: 2,
     r: 5
   }
-  Sign.Setting.set(cad.processing.render, signStyle)
-
-  let sign = new Sign({
-    pos: {x: -2, y: 5},
-    dire: 0,
-    renderer: cad.processing.render
-  })
-  sign.zIndex = 1
-  cad.processing.render.push(sign)
   
+  const addProcessing = cad.addProcessing
+  cad.addProcessing = (...args) => {
+    let processing = addProcessing.call(cad, ...args)
+    
+    Sign.Setting.set(processing.render, signStyle)
+
+    let sign = new Sign({
+      pos: {x: 0, y: 0},
+      dire: 0,
+      renderer: processing.render
+    })
+    sign.zIndex = 1
+    processing.render.push(sign)
+    
+    processing.sign = sign
+    return processing
+  }
+
   // 添加设置当前点位方向
   cad.setSign = (point, dire) => {
+    let sign = cad.processing.sign
     if (type.isNumber(dire)) sign.dire = dire
     sign.pos = point
   }
 
   cad.hideSign = () => {
-    console.log('-------')
+    let sign = cad.processing.sign
     sign.show = false
     return new Promise(r => sign.nextTick(r))
   }
 
   cad.showSign = () => {
+    let sign = cad.processing.sign
     sign.show = true
     return new Promise(r => sign.nextTick(r))
   }
   
   cad.setDefaultSignStyle = args => {
+    let sign = cad.processing.sign
     if (args.border) {
       signStyle.border = args.border
       sign.border = args.border
@@ -57,11 +69,4 @@ export const attachSign = (cad: CAD) => {
       sign.color = args.color
     }
   }
-
-  let destroy = cad.destroy
-  cad.destroy = function(...args) {
-    sign = null
-    destroy.apply(this, args)
-  }
-
 }

+ 13 - 3
src/CAD/core/additional/styleSet.ts

@@ -31,8 +31,6 @@ export const attachStyle = (cad: CAD) => {
     fillColor: 'rgba(245, 255, 0, 0.7)',
     storkeColor: 'rgba(245, 255, 255, 0.3)'
   }
-  FixedPoint.Setting.set(cad.processing.render, fixedPointStyle)
-  Point.Setting.set(cad.processing.render, pointStyle)
 
   cad.setDefaultPointStyle = (args) => {
     args.storkeColor && (fixedPointStyle.storkeColor = args.storkeColor)
@@ -51,7 +49,19 @@ export const attachStyle = (cad: CAD) => {
     width: 3,
     color: 'rgb(255,255,255)'
   }
-  Line.Setting.set(cad.processing.render, lineStyle)
+
+  
+  const addProcessing = cad.addProcessing
+  cad.addProcessing = (...args) => {
+    let processing = addProcessing.call(cad, ...args)
+    
+    FixedPoint.Setting.set(processing.render, fixedPointStyle)
+    Point.Setting.set(processing.render, pointStyle)
+    Line.Setting.set(processing.render, lineStyle)
+
+    return processing
+  }
+
 
   cad.setDefaultLineStyle = args => {
     args.width && (lineStyle.width = args.width)

+ 9 - 6
src/CAD/core/additional/transform.ts

@@ -9,11 +9,12 @@ export interface DOMTransform {
 
 // 给cad附加矩阵转换功能 如放大缩小
 export const attchDOMTranform = (cad: AttachCAD) => {
-  let render = cad.processing.render
 
 
   // 点击在cad上认为要平移
   const down = (dev: MouseEvent) => {
+    console.log(cad.processing)
+    let render = cad.processing.render
     if (dev.target !== render.svg) return;
     const left = render.props.left
     const top = render.props.top
@@ -40,6 +41,7 @@ export const attchDOMTranform = (cad: AttachCAD) => {
 
   // 缩放
   const wheel = (ev: any) => {
+    let render = cad.processing.render
     let delta = ev.wheelDelta ? //IE、chrome浏览器使用的是wheelDelta,并且值为“正负120”
       (window.opera ? -ev.wheelDelta / 120 : ev.wheelDelta / 120) : //因为IE、chrome等向下滚动是负值,FF是正值,为了处理一致性,在此取反处理
       (ev.detail ?  -ev.detail / 3 : 0); //FF浏览器使用的是detail,其值为“正负3”
@@ -55,21 +57,22 @@ export const attchDOMTranform = (cad: AttachCAD) => {
 
   // 开启缩放模式
   cad.openMouseHandle = () => {
-    render.layer.addEventListener('mousedown', down, false)
-    render.layer.addEventListener('mousewheel', wheel, false)
+    let layer = cad.layer
+    layer.addEventListener('mousedown', down, false)
+    layer.addEventListener('mousewheel', wheel, false)
   }
 
   // 关闭缩放模式
   cad.closeMouseHandle = () => {
-    render.layer.removeEventListener('mousedown', down, false)
-    render.layer.removeEventListener('mousewheel', wheel, false)
+    let layer = cad.layer
+    layer.removeEventListener('mousedown', down, false)
+    layer.removeEventListener('mousewheel', wheel, false)
   }
 
   
   let destroy = cad.destroy
   cad.destroy = function(...args) {
     cad.closeMouseHandle()
-    render = null
     destroy.apply(this, args)
   }
 }

+ 8 - 1
src/CAD/core/architecture/bayCase.ts

@@ -78,9 +78,16 @@ class BayCase extends LineArch<ArchProps> {
     let starts = getDisVerticalLinePoints(this.attachment, point1, half)
     let ends = getDisVerticalLinePoints(this.attachment, point2, half)
     
-    let start = this.within ? starts[0] : starts [1]
+    
+    let center = {x: 0,  y: 0}
+    let isInside = lineDis({points: [starts[0], center]}) < lineDis({points: [starts[1], center]})
+    
+    let start = this.within ? 
+    (!isInside ? starts[0] : starts [1]):
+      (isInside ? starts[0] : starts [1])
     let end
 
+    
 
     if (start) {
       end = ends[starts.indexOf(start)]

+ 9 - 8
src/CAD/core/architecture/casement.ts

@@ -9,6 +9,7 @@ import { getDisVerticalLinePoints } from '../geometry'
 
 export interface CastStyle {
   fill?: string,
+  bgColor?: string,
   seam?: string,
   width?: number,
   stamWidth?: number
@@ -37,10 +38,10 @@ class Casement extends LineArch<ArchProps> {
   clip3: SVGPathElement
   clip4: SVGPathElement
 
-  constructor({points, fill = 'rgba(0,0,0,0)', seam = 'rgba(255,255,255,0)', width = 6, stamWidth = 0.5, hover, ...args}: CaseProps) {
+  constructor({points, fill = 'rgba(0,0,0,0)', seam = 'rgba(255,255,255,0)', bgColor = 'rgba(255,255,255,0.5)', width = 6, stamWidth = 0.5, hover, ...args}: CaseProps) {
     let init = {fill, seam, width, stamWidth}
     hover = hover || {...init, fill: 'rgba(243, 255, 0, 0.8)'}
-    super({linePoints: points, hover, ...args, ...init})
+    super({linePoints: points, bgColor, hover, ...args, ...init})
     this.eleHover = false
   }
 
@@ -65,10 +66,6 @@ class Casement extends LineArch<ArchProps> {
     this.clip2 = document.createElementNS(SVGURI, 'path')
     this.clip3 = document.createElementNS(SVGURI, 'path')
     this.clip4 = document.createElementNS(SVGURI, 'path')
-    this.clip1.setAttribute('stroke', 'rgba(255,255,255,0.5)')
-    this.clip2.setAttribute('stroke', 'rgba(255,255,255,0.5)')
-    this.clip3.setAttribute('stroke', 'rgba(255,255,255,0.5)')
-    this.clip4.setAttribute('stroke', 'rgba(255,255,255,0.5)')
 
     node.appendChild(this.clip1)
     node.appendChild(this.clip2)
@@ -115,8 +112,8 @@ class Casement extends LineArch<ArchProps> {
 
   update() {
     if (this.outLine) {
-      this.outLine.width = Date.now()
-      this.innerline.width = Date.now()
+      this.outLine.width = this.outLine.width + 0.00000001
+      this.innerline.width =  this.innerline.width + 0.00000001
     }
     
     let [p1, p3] = getDisVerticalLinePoints(this.attachment, this.linePoints[0], this.width * 0.4 * this.multiple)
@@ -134,6 +131,10 @@ class Casement extends LineArch<ArchProps> {
     this.clip3.setAttribute('d', `M ${p5.x} ${p5.y} L ${p6.x} ${p6.y}`)
     this.clip4.setAttribute('stroke-width', (this.multiple).toString())
     this.clip4.setAttribute('d', `M ${p7.x} ${p7.y} L ${p8.x} ${p8.y}`)
+    this.clip1.setAttribute('stroke', this.bgColor)
+    this.clip2.setAttribute('stroke', this.bgColor)
+    this.clip3.setAttribute('stroke', this.bgColor)
+    this.clip4.setAttribute('stroke', this.bgColor)
     this.attachment.update()
   }
 

+ 27 - 7
src/CAD/core/architecture/door/index.ts

@@ -5,8 +5,8 @@ import { ElementProps } from '../../core/element'
 import LineArch, {LineArchProps} from '../linearch'
 import LinePoint from '../../core/linepoint'
 import {lineDis, getDisVectorPoints, verticalLine, getDisVerticalLinePoints, isClockWise, pointInside, lineDeg, faceCenter, lineStretch, lineVector} from '../../geometry'
-import defaultIcon from './cad_enter@3x'
-import darkIcon from './cad_enter_dark@3x'
+import * as defaultIcon from './cad_enter@3x.png'
+import * as darkIcon from './cad_enter_dark@3x.png'
 
 let icon = {
   defaultIcon, darkIcon
@@ -70,18 +70,25 @@ class Door extends LineArch<ArchProps> {
     node.appendChild(this.image)
 
     this.nextTick(() => {
-      node.appendChild(this.linePoints[0].real)
-      node.appendChild(this.linePoints[1].real)
+      if (this.linePoints) {
+        node.appendChild(this.linePoints[0].real)
+        node.appendChild(this.linePoints[1].real)
+      }
     })
 
     return node
   }
 
+
   getCalcPoint(r = lineDis({points: this.linePoints})) {
     let p1 = this.linePoints[0]
     let [p3] = getDisVectorPoints(verticalLine(this.attachment), p1, r)
     return p3
   }
+  click(ev) {
+    super.click(ev)
+    console.log(this.within)
+  }
 
   getDrawArgs(): [point, point, point, number, boolean] {
     let p1, p2;
@@ -91,13 +98,26 @@ class Door extends LineArch<ArchProps> {
       [p2, p1] = this.linePoints
     }
 
-    // let [p2, p1] = this.linePoints
     let r = lineDis({points: this.linePoints})
 
     let [p31, p32] = getDisVerticalLinePoints(this.attachment, p1, r)
+    // let xall = this.renderer.processing.points.map(p => p.ele.x)
+    // let yall = this.renderer.processing.points.map(p => p.ele.y)
+    let center = {
+      x: 0,
+      y: 0
+    }
+    let isInside = lineDis({points: [p31, center]}) < lineDis({points: [p32, center]})
+    let p3
+
+    if (this.within === 0 || this.within === 3) {
+      p3 = isInside ? p31 : p32
+    } else {
+      p3 = isInside ? p32 : p31
+    }
+
+    
     
-    let p3 = this.within === 0 || this.within === 1 ? p31 : p32
-    // console.log(p1.x, p1.y)
     return [p1, p2, p3, r, isClockWise([p1, p2, p3])]
   }
 

+ 100 - 0
src/CAD/core/architecture/doubleDoor.ts

@@ -0,0 +1,100 @@
+import Door, { DoorProps } from './door/index'
+import { SVGURI } from '../constant/Element'
+import { lineDis, verticalLine, getLineDisSelectPoint, lineCenter } from '../geometry'
+
+interface DoubleDoorProps extends DoorProps {
+}
+
+/**
+ * @category core
+ * @subcategory CAD_Architecture
+ */
+class DoubleDoor extends Door {
+  layer: SVGPathElement
+  clip1: SVGPathElement
+  clip2: SVGPathElement
+  path1: SVGPathElement
+  path2: SVGPathElement
+  left: SVGRectElement
+  right: SVGRectElement
+
+  constructor(args: DoubleDoorProps) {
+    super(args)
+  }
+
+
+  grentNode() {
+    let node = document.createElementNS(SVGURI, 'g')
+
+    this.arc1 = document.createElementNS(SVGURI, 'path')
+    this.outLine1 = document.createElementNS(SVGURI, 'path')
+    this.arc2 = document.createElementNS(SVGURI, 'path')
+    this.outLine2 = document.createElementNS(SVGURI, 'path')
+
+
+    node.appendChild(this.outLine1)
+    node.appendChild(this.arc1)
+    node.appendChild(this.outLine2)
+    node.appendChild(this.arc2)
+
+    this.nextTick(() => {
+      node.appendChild(this.linePoints[0].real)
+      node.appendChild(this.linePoints[1].real)
+    })
+
+    return node
+  }
+
+  update() {
+    this.real.style.display = this.show ? 'initial' : 'none'
+    let center = lineCenter({points: this.linePoints})
+
+    let [p1, p2, p3, r, clockwise] = this.getDrawArgs.call({
+      linePoints: [this.linePoints[0], center],
+      within: this.within === 1 ? 2 : this.within,
+      attachment: this.attachment
+    })
+
+    if (isNaN(p3.x)) {
+      this.destroy()
+      return;
+    }
+
+    this.arc1.setAttribute('d', `M ${p1.x} ${p1.y} L ${p3.x} ${p3.y} A ${r} ${r} 0 0 ${clockwise ? '1' : '0'} ${p2.x} ${p2.y} Z`)
+    this.arc1.setAttribute('stroke-width', (this.outWidth * this.multiple).toString())
+    this.arc1.setAttribute('stroke', this.stroke)
+    this.arc1.setAttribute('fill', this.fill)
+
+    this.outLine1.setAttribute('stroke', this.foorColor)
+    this.outLine1.setAttribute('fill', this.fill)
+    this.outLine1.setAttribute('stroke-width', (this.foorWidth * this.multiple).toString())
+    this.outLine1.setAttribute('stroke-linecap', this.linecap)
+    this.outLine1.setAttribute('d', `M ${this.linePoints[0].x} ${this.linePoints[0].y} L ${this.linePoints[1].x} ${this.linePoints[1].y}`);
+
+    [p1, p2, p3, r, clockwise] = this.getDrawArgs.call({
+      linePoints: [this.linePoints[1], center],
+      within: this.within === 1 ? 2 : this.within,
+      attachment: this.attachment
+    })
+
+    if (isNaN(p3.x)) {
+      this.destroy()
+      return;
+    }
+
+    this.arc2.setAttribute('d', `M ${p1.x} ${p1.y} L ${p3.x} ${p3.y} A ${r} ${r} 0 0 ${clockwise ? '1' : '0'} ${p2.x} ${p2.y} Z`)
+    this.arc2.setAttribute('stroke-width', (this.outWidth * this.multiple).toString())
+    this.arc2.setAttribute('stroke', this.stroke)
+    this.arc2.setAttribute('fill', this.fill)
+
+    this.outLine2.setAttribute('stroke', this.foorColor)
+    this.outLine2.setAttribute('fill', this.fill)
+    this.outLine2.setAttribute('stroke-width', (this.foorWidth * this.multiple).toString())
+    this.outLine2.setAttribute('stroke-linecap', this.linecap)
+    this.outLine2.setAttribute('d', `M ${this.linePoints[0].x} ${this.linePoints[0].y} L ${this.linePoints[1].x} ${this.linePoints[1].y}`)
+
+    this.attachment.update()
+  }
+}
+
+export default DoubleDoor

+ 1 - 1
src/CAD/core/architecture/groundCase.ts

@@ -67,7 +67,7 @@ class GroundCase extends LineArch<ArchProps> {
   }
 
   setUnHoverStyle() {
-    this.fill = '#fff'
+    this.fill = 'rgba(255,255,255,0.5)'
   }
 
 

+ 3 - 2
src/CAD/core/architecture/linearch.ts

@@ -259,8 +259,9 @@ class LineArch extends CADElement<LineArchProps> {
     let Archs = LineArch.attaArch.get(this.attachment)
     if (Archs) {
       Archs.splice(Archs.indexOf(this), 1)
-      this.linePoints[0].destroy()
-      this.linePoints[1].destroy()
+      console.log(this.linePoints[0], this)
+      this.linePoints[0] && this.linePoints[0].destroy && this.linePoints[0].destroy()
+      this.linePoints[1] && this.linePoints[1].destroy && this.linePoints[1].destroy()
       this.attachment = null
       this.linePoints = null
       this.update = null

+ 21 - 14
src/CAD/core/architecture/slideDoor.ts

@@ -43,22 +43,29 @@ class SlideDoor extends Door {
     
     let node = document.createElementNS(SVGURI, 'g')
 
-    node.innerHTML = `
-      <path class="slide-door-1" />
-      <path class="slide-door-2" />
-      <path class="slide-door-clip-1" />
-      <path class="slide-door-clip-2" />
-      <rect width="0.00001" height="0.00001" class="slide-door-left" />
-      <rect width="0.00001" height="0.00001" class="slide-door-right" />
-    `
     
-    this.clip1 = node.querySelector('.slide-door-clip-1')
-    this.clip2 = node.querySelector('.slide-door-clip-2')
-    this.path1 = node.querySelector('.slide-door-1')
-    this.path2 = node.querySelector('.slide-door-2')
-    this.left = node.querySelector('.slide-door-left')
-    this.right = node.querySelector('.slide-door-right')
+    this.clip1 = document.createElementNS(SVGURI, 'path')
+    node.appendChild(this.clip1)
 
+    this.clip2 = document.createElementNS(SVGURI, 'path')
+    node.appendChild(this.clip2)
+
+    this.path1 = document.createElementNS(SVGURI, 'path')
+    node.appendChild(this.path1)
+
+    this.path2 = document.createElementNS(SVGURI, 'path')
+    node.appendChild(this.path2)
+
+    this.left = document.createElementNS(SVGURI, 'rect')
+    this.left.setAttribute('width', '0.00001')
+    this.left.setAttribute('height', '0.00001')
+    node.appendChild(this.left)
+
+    this.right = document.createElementNS(SVGURI, 'rect')
+    this.right.setAttribute('width', '0.00001')
+    this.right.setAttribute('height', '0.00001')
+    node.appendChild(this.right)
+    
     this.nextTick(() => {
       node.appendChild(this.linePoints[0].real)
       node.appendChild(this.linePoints[1].real)

+ 38 - 17
src/CAD/core/base/cad.ts

@@ -9,28 +9,52 @@ interface CADProps extends StorageProps {
 
 
 class CAD {
+  edit: boolean
   isDestroy: boolean
   padding: number
   resizeHandle: () => void
   processing: ProcessingTS
+  processings: Array<ProcessingTS>
+  layer: HTMLElement
 
   constructor({dom, padding = 20}: CADProps) {
-    this.processing = new Processing({dom})
-    this.processing.cad = this as any
+    this.processings = []
+    Object.defineProperty(this, 'processing', {
+      get(this: CAD) {
+        return this.processings.find(p => p.show)
+      }
+    })
+
+    this.layer = dom
+
     this.padding = padding
     this.isDestroy = false
     this.resizeHandle = () => this.processing.data && this.adapt(this.processing.data)
     this.init()
   }
 
-  adapt(
-    data: Data = this.processing.data, 
-    width = this.processing.render.layer.offsetWidth || parseInt(getComputedStyle(this.processing.render.layer).width) || 100,
-    height = this.processing.render.layer.offsetHeight || parseInt(getComputedStyle(this.processing.render.layer).height) || 100
-  ) {
+  addProcessing() {
+    let processing = new Processing({dom: this.layer})
+    processing.cad = this as any
+
+    this.processings.push(processing)
+
+    return processing
+  }
+
+  delProcessing(proc: ProcessingTS) {
+    proc.render.elements.forEach(ele => ele.destroy())
+    this.processings.splice(this.processings.indexOf(proc), 1)
+  }
+
+  adapt(data: Data = this.processing.data, width?, height?, oData?) {
+    let processing = this.processings.find(proc => proc.data.id === data.id)
+
+    width = width || processing.render.layer.offsetWidth || parseInt(getComputedStyle(processing.render.layer).width) || 100,
+    height = height || processing.render.layer.offsetHeight || parseInt(getComputedStyle(processing.render.layer).height) || 100
+
     if (data.vertex.length === 0) {
-      console.log('------------1')
-      this.processing.render.props = getMapMultipleWH(width, height, {
+      processing.render.props = getMapMultipleWH(width, height, {
         vertex: [
           {x: -15, y: -15},
           {x: -15, y: 15},
@@ -39,13 +63,12 @@ class CAD {
         ]
       }, this.padding)
     } else {
-      console.log('------------2')
       if (width && height) {
-        this.processing.render.props = getMapMultipleWH(width, height, data, this.padding)
+        processing.render.props = getMapMultipleWH(width, height, data, this.padding)
       } 
 
-      if (this.processing.render.props.scale <= 0){
-        this.processing.render.props = {
+      if (processing.render.props.scale <= 0){
+        processing.render.props = {
           width: 0,
           height: 0,
           multiple: 0,
@@ -56,10 +79,8 @@ class CAD {
       }
     }
     // this.processing.render.props = {"width":10.066168623265742,"height":9,"multiple":0.0096051227321238,"left":1.0652498723957131,"top":3.9390821771611524,"scale":5.201832061068706}
-    this.processing.render.adaptLayer(width, height)
-    let eles = []
-
-    this.processing.attrs.forEach(attr => eles.concat(this.processing[attr].map(({ele}) => ele)))
+    processing.render.adaptLayer(width, height)
+    CADElement.update(processing.render)
   }
 
 

+ 43 - 1
src/CAD/core/base/processing/index.ts

@@ -3,6 +3,7 @@ import Point from '../../core/point'
 import WallLine from '../../core/wallline'
 import Casement from '../../architecture/casement'
 import Door from '../../architecture/door/index'
+import DoubleDoor from '../../architecture/doubleDoor'
 import Column from '../../architecture/column'
 import FurnColumn from '../../furniture/column'
 import FurnFlue from '../../furniture/flue'
@@ -16,12 +17,16 @@ import { methods as dataMethods, dataApi } from './toData'
 import { methods as pointOperMethods, PointOper } from './pointOper'
 import BayCase from '../../architecture/bayCase'
 import {AttachCAD} from '../../index'
+import Sign from '../../label/sign'
+import Direction from '../../label/direction'
+import Route from '../../label/route'
 
 
 export interface _Point { x: number, y:number, id: number }
 export interface _Line { p1: number, p2: number, id: number, border: boolean, exterior?: boolean }
 export interface _window { pos: Array<number>, line: number  }
 export interface _door { pos: Array<number>, line: number, within: number, show?: boolean, ctl?: Array<number>, start: boolean }
+export interface _doubledoor { pos: Array<number>, line: number, within: number, show?: boolean, ctl?: Array<number>, start: boolean }
 export interface _slideDoor { pos: Array<number>, line: number, within: number }
 export interface _groundCase { pos: Array<number>, line: number }
 export interface _bayCase { pos: Array<number>, line: number, within: number, ctl?: Array<number> }
@@ -33,6 +38,8 @@ export interface _hole {pos: Array<number>, top: number}
 export type _Ground = Array<number>
 export interface _room { id: number, ground: _Ground, hole: Array<_hole>, close: boolean }
 export interface Data {
+  show: boolean,
+  id: number,
   room?: Array<{
     wall: Array<number>,
     ground: Array<number>
@@ -44,6 +51,7 @@ export interface Data {
   door: Array<_door>,
   column: Array<_column>,
   furnColumn: Array<_furnColumn>,
+  doubleDoor: Array<_doubledoor>
   furnFlue: Array<_furnFlue>,
   slideDoor: Array<_slideDoor>
   groundCase: Array<_groundCase>,
@@ -51,6 +59,9 @@ export interface Data {
   tagging: Array<_tagging>,
   dire: number
 }
+export interface FloorData {
+  floors: Array<Data>
+}
 export interface StorageProps{ dom: HTMLElement }
 export interface CADState {elements: Array<Point>}
 export interface rhole extends _hole {bottom: number} 
@@ -65,6 +76,7 @@ export type FurnColumns = Array<{ele: FurnColumn}>
 export type FurnFlues = Array<{ele: FurnFlue}>
 export type Taggings = Array<{ele: Tagging}>
 export type BayCases = Array<{ele: BayCase}>
+export type DoubleDoors = Array<{ele: DoubleDoor}>
 
 export class _Processing {
   data: Data
@@ -72,19 +84,26 @@ export class _Processing {
   points: Points
   lines: Walls
   cases: Cases
+  id: number
+  show: boolean
   doors: Doors
   slideDoors: SlideDoors
   groundCases: GroundCases
   bayCases: BayCases
+  doubleDoors: DoubleDoors
   columns: Columns
   taggings: Taggings
   insertModel: boolean
   furnColumns: FurnColumns
   furnFlues: FurnFlues
+  direction: Direction
+  sign: Sign
+  rote: Route
   cad: AttachCAD
   
   constructor({dom}: StorageProps) {
     this.render = new Render({ layer: dom, processing: (this as unknown as ProcessingTS) })
+    this.id = 1
     this.points = []
     this.lines = []
     this.cases = []
@@ -96,8 +115,25 @@ export class _Processing {
     this.bayCases = []
     this.furnColumns = []
     this.furnFlues = []
+    this.doubleDoors = []
+    this.manageShow()
   }
 
+  private manageShow() {
+    let show = false
+
+    Object.defineProperty(this, 'show', {
+      get: () => show,
+      set: (val) => {
+        console.log('---------', show)
+        show = val
+        this.render.svg.style.display = show ? 'block': 'none'
+      }
+    })
+    
+  }
+
+
   // 删除元素
   rep(this: ProcessingTS, ele: CADElementTS) {
     this.attrs.forEach(attr => {
@@ -108,7 +144,10 @@ export class _Processing {
         this[attr].splice(index, 1)
       }
     })
-    this.render.remove(ele)
+    if (!this.render) {
+      console.error('掉用 rep')
+    }
+    this.render && this.render.remove(ele)
   }
 
   // Element加装Destroy方法
@@ -160,6 +199,8 @@ export class _Processing {
   destroy(this: ProcessingTS) {
     let elesArr = this.attrs.map(attr => this[attr])
     this.data = {
+      id: 1,
+      show: true,
       vertex: [],
       wall: [],
       window: [],
@@ -170,6 +211,7 @@ export class _Processing {
       tagging: [],
       groundCase: [],
       bayCase: [],
+      doubleDoor: [],
       furnColumn: [],
       furnFlue: [],
       dire: 0

+ 0 - 1
src/CAD/core/base/processing/pointOper.ts

@@ -61,7 +61,6 @@ export const methods: That = {
               if (pointLineDis(proLine.ele, arch.linePoints[0]) < 0.1 && pointLineDis(proLine.ele, arch.linePoints[1]) < 0.1) {
                 arch.setAttachment(proLine.ele)
               } else {
-                console.log('----------')
               }
 
             })

+ 14 - 3
src/CAD/core/base/processing/toData.ts

@@ -1,13 +1,14 @@
 import Point from '../../core/point'
 import WallLine from '../../core/wallline'
 import {LineArchClass as LineArch} from '../../architecture/linearch'
-import { _Point, _Line, _window, _door, _column, Data, That, _tagging, _groundCase, _bayCase, _furnColumn, _furnFlue, _slideDoor } from './index'
+import { _Point, _Line, _window, _door, _column, Data, That, _tagging, _groundCase, _bayCase, _furnColumn, _furnFlue, _slideDoor, _doubledoor } from './index'
 import Door from '../../architecture/door/index'
 import Casement from '../../architecture/casement'
 import Column from '../../architecture/column'
 import Tagging from '../../label/tagging'
 import GroundCase from '../../architecture/groundCase'
 import BayCase from '../../architecture/bayCase'
+import DoubleDoor from '../../architecture/doubleDoor'
 import FurnColumn from '../../furniture/column'
 import FurnFlue from '../../furniture/flue'
 import { FurnClass as Furn } from '../../furniture/furn'
@@ -23,6 +24,7 @@ export interface dataApi {
   pointToData: (ele: {ele: Point, id: number}) => _Point
   lineToData: (ele: {ele: WallLine, id: number}) => _Line
   doorToData: (ele: {ele: Door}) => _door
+  DoubleDoorToData: (ele: {ele: DoubleDoor}) => _doubledoor
   slideDoorToData: (ele: {ele: Door}) => _slideDoor
   caseToData: (ele: {ele: Casement}) => _window
   groundCaseToData: (ele: {ele: GroundCase}) => _groundCase
@@ -84,6 +86,12 @@ export const methods: That = {
     data.start = ele.start
     return data
   },
+  DoubleDoorToData ({ele}: {ele: Door}) {
+    let data = this.baseArchToData(ele)
+    data.within = ele.within
+    data.show = ele.show
+    return data
+  },
   slideDoorToData ({ele}: {ele: SlideDoor}) {
     let data = this.baseArchToData(ele)
     data.within = ele.within
@@ -115,7 +123,7 @@ export const methods: That = {
   },
   taggingToData ({ele}: {ele: Tagging}) {
     return {
-      pos: [ele.point.x, ele.point.y],
+      pos: [ele.x, ele.y],
       title: ele.title,
       content: ele.content,
       showTitle: ele.showTitle,
@@ -161,6 +169,7 @@ export const methods: That = {
     let groundCase = this.groundCases.map(a => this.groundCaseToData(a))
     let tagging = this.taggings.map(a => this.taggingToData(a))
     let bayCase = this.bayCases.map(a => this.BayCaseToData(a))
+    let doubleDoor = this.doubleDoors.map(a => this.DoubleDoorToData(a))
 
 
 
@@ -176,10 +185,12 @@ export const methods: That = {
 
 
     return {
+      id: this.id,
+      show: this.show,
       vertex, wall, 
       window, door, column, 
       surplus: this.data.surplus, 
-      slideDoor, groundCase, tagging, 
+      slideDoor, groundCase, tagging, doubleDoor, 
       bayCase, furnColumn, furnFlue,
       dire: this.data.dire
     }

+ 33 - 6
src/CAD/core/base/processing/toEle.ts

@@ -4,11 +4,12 @@ import Casement from '../../architecture/casement'
 import Door from '../../architecture/door/index'
 import SlideDoor from '../../architecture/slideDoor'
 import Column from '../../architecture/column'
+import DoubleDoor from '../../architecture/doubleDoor'
 import FurnColumn from '../../furniture/column'
 import FurnFlue from '../../furniture/flue'
 import Tagging from '../../label/tagging'
 import { CADElementTS } from '../../core/element'
-import { _Point, _Line, _window, _door, _column, Data, That, _tagging, _groundCase, _slideDoor, _bayCase, _room, _hole, _furnColumn, _furnFlue } from './index'
+import { _Point, _Line, _window, _door, _column, Data, That, _tagging, _groundCase, _slideDoor, _bayCase, _room, _hole, _furnColumn, _furnFlue, _doubledoor } from './index'
 import GroundCase from '../../architecture/groundCase'
 import BayCase from '../../architecture/bayCase'
 import Line from '../../core/wallline'
@@ -19,6 +20,7 @@ export interface ToEle {
   addLine: ({id, p1, p2, exterior, isOut}: _Line &{isOut: boolean}) => { id: number; ele: WallLine },
   addCase: ({pos, line}: _window) => {ele: Casement},
   addDoor: ({pos, line, start}: _door) => {ele: Door},
+  adddDoubleDoor: ({pos, line, start}: _doubledoor) => {ele: DoubleDoor},
   addSlideDoor: ({pos, line, within}: _slideDoor) => {ele: SlideDoor},
   addGroundCase: ({pos, line}: _groundCase) => {ele: SlideDoor},
   addBayCase: ({pos, line}: _bayCase) => {ele: BayCase},
@@ -69,7 +71,8 @@ export const methods: That = {
     this.generateElement(ret.ele)
 
     if (exterior) {
-      [ret.ele, ...ret.ele.points].forEach(point => point.real.setAttribute('pointer-events', 'none'))
+      ret.ele.points.forEach(point => point.real.setAttribute('pointer-events', 'none'))
+      ret.ele.zIndex = -1
     }
 
     return ret
@@ -106,6 +109,22 @@ export const methods: That = {
     this.generateElement(ret.ele)
     return ret
   },
+  adddDoubleDoor ({pos, line, top = null, bottom = null, within, show, start}) {
+    let ret = {
+      ele: new DoubleDoor({
+        show,
+        renderer: this.render,
+        attachment: this.lines.find(({id}) => id === line).ele,
+        points: [{x: pos[0], y: pos[1]}, {x: pos[2], y: pos[3]}],
+        top, bottom,
+        within: within,
+        start
+      })
+    }
+    this.doubleDoors.push(ret)
+    this.generateElement(ret.ele)
+    return ret
+  },
 
   addSlideDoor ({pos, line, top = null, bottom = null, within = 0}) {
     let ret = {
@@ -281,7 +300,7 @@ export const methods: That = {
   
   // 将数据转换为ele
   toEles (data: Data) {
-    let {vertex, wall, window, door, column, slideDoor, tagging, groundCase, bayCase, furnColumn, furnFlue} = data
+    let {vertex, wall, window, door, column, slideDoor, tagging, groundCase, bayCase, furnColumn, furnFlue, doubleDoor} = data
     let count = 0
     this.data = data
 
@@ -290,7 +309,8 @@ export const methods: That = {
       this.addLine({p1, p2, id: ++count, border: border, exterior: exterior, isOut: false})
     });
 
-    [window, door, column, slideDoor, groundCase, bayCase].forEach(objs => {
+    [window, door, column, slideDoor, groundCase, bayCase, doubleDoor] = 
+      [window, door, column, slideDoor, groundCase, bayCase, doubleDoor].map(objs => {
       objs.forEach(obj => {
         let aline = wall.find(({id}) => obj.line === id)
         if (!aline) {
@@ -304,7 +324,11 @@ export const methods: That = {
         })
         obj.line = line.id
       })
-    })
+
+      objs = objs.filter(obj => !obj.pos.some(z => z === null))
+
+      return objs
+    }) as any
 
 
 
@@ -316,6 +340,7 @@ export const methods: That = {
     groundCase.forEach(a => a.line !== 0 && this.addGroundCase(a))
     bayCase.forEach(a => a.line !== 0 && this.addBayCase(a))
     tagging.forEach(a => this.addTagging(a))
+    doubleDoor.forEach(a => this.adddDoubleDoor(a))
 
     
     furnColumn.forEach(a => {
@@ -327,6 +352,8 @@ export const methods: That = {
     
 
     this.referElements()
+    this.id = data.id
+    this.show = data.show
   },
 
   referElements() {
@@ -346,4 +373,4 @@ export const methods: That = {
 };
 
 
-(methods as any).attrs = [ 'cases', 'doors', 'slideDoors', 'columns', 'lines', 'points', 'groundCases', 'taggings', 'bayCases', 'furnColumns', 'furnFlues']
+(methods as any).attrs = [ 'cases', 'doors', 'slideDoors', 'doubleDoors', 'columns', 'lines', 'points', 'groundCases', 'taggings', 'bayCases', 'furnColumns', 'furnFlues']

+ 2 - 3
src/CAD/core/base/renderer.ts

@@ -12,7 +12,6 @@ interface RendererProps {
 }
 
 class Renderer {
-  edit: boolean
   svg: SVGSVGElement
   g: SVGGElement
   layer: HTMLElement
@@ -140,9 +139,9 @@ class Renderer {
     elements.forEach(element => {
       try {
         this.g.removeChild(element.real)
-        this.elements.splice(this.elements.indexOf(element), 1)
-      } catch {
+      } catch(e) {
       }
+      ~this.elements.indexOf(element) && this.elements.splice(this.elements.indexOf(element), 1)
     })
   }
 

+ 6 - 0
src/CAD/core/constant/Element.ts

@@ -4,6 +4,7 @@ export const SVGPATH = "http://www.w3.org/1999/xlink"
 export const STATE_CHILD = '__state'
 export const POINT = 'point'
 export const DOOR = 'door'
+export const DOUBLEDOOR = 'double_door'
 export const COLUMN = 'column'
 export const CASEMENT = 'casement'
 export const SLIDEDOOR = 'slideDoor'
@@ -18,6 +19,7 @@ export const SEFTLINE = 'seftline'
 export const ARCH = {
   [POINT]: i18n.t('modules.model.point'),
   [DOOR]: i18n.t('modules.model.door'),
+  [DOUBLEDOOR]: i18n.t('modules.model.double_door'),
   [COLUMN]: i18n.t('modules.model.column'),
   [CASEMENT]: i18n.t('modules.model.casement'),
   [SLIDEDOOR]: i18n.t('modules.model.slideDoor'),
@@ -35,6 +37,10 @@ export const DEFAULT = {
     width: 0.8,
     height: 2
   },
+  [DOUBLEDOOR]: {
+    width: 1.6,
+    height: 2
+  },
   [SLIDEDOOR]: {
     width: 1.5,
     height: 2

File diff suppressed because it is too large
+ 41 - 0
src/CAD/core/constant/Label.ts


+ 14 - 9
src/CAD/core/core/element.ts

@@ -119,6 +119,12 @@ class _CADElement<T = {}> {
     }
 
     this.real.id = 'ele' + id.toString()
+      this.nextTick(() => {
+        try {
+          this.update()
+        } catch(e) {
+        }
+      })
   }
   
   intercept(stick: Array<any>,args: SubState<T>, ret: SubState<T>, dire?): BeforeRet<T> | boolean {
@@ -127,11 +133,11 @@ class _CADElement<T = {}> {
 
   changeSelect(select: boolean) {
     if (this.select !== select) {
-      this.__state.direct = true
+      // this.__state.direct = true
       this.select = select
-      this.update && this.update()
-      this.__state.direct = false
+      // this.__state.direct = false
       this.wallSelect && this.wallSelect()
+      this.update && this.update()
 
       if (select) {
         _CADElement.examples.get(this.renderer).forEach(e => {
@@ -144,11 +150,6 @@ class _CADElement<T = {}> {
   }
   click(ev: SVGElementEventMap['click']) {
     this.changeSelect(true)
-
-    this.renderer.processing.attrs.forEach(attr => {
-      let obj = this.renderer.processing[attr].find(({ele}) => ele === this)
-      obj && console.log(obj)
-    })
     ev.stopPropagation()
   }
 
@@ -182,7 +183,11 @@ class _CADElement<T = {}> {
     this.__destroy = true
     this.unEvent()
     let element = _CADElement.examples.get(this.renderer)
-    ~element.indexOf(this) && element.splice(element.indexOf(this), 1)
+
+    if (~element.indexOf(this)) {
+      element.splice(element.indexOf(this), 1)
+      this.renderer.remove(this as any)
+    }
   }
 
   // 处理绑定事件

+ 9 - 8
src/CAD/core/core/fixedpoint.ts

@@ -47,16 +47,17 @@ class Point extends CADElement<PointProps, Point> {
 
     let strokeWidth = this.strokeWidth * this.multiple
 
+    // console.log(this)
     try {
-    this.real.setAttribute('cx', this.x.toString())
-    this.real.setAttribute('cy', this.y.toString())
-    this.real.setAttribute('fill', this.fillColor)
-    this.real.setAttribute('rx', r1.toString())
-    this.real.setAttribute('ry', r2.toString())
-    this.real.setAttribute('stroke-width', strokeWidth.toString())
-    this.real.setAttribute('stroke', this.storkeColor)
+      this.real.setAttribute('cx', this.x.toString())
+      this.real.setAttribute('cy', this.y.toString())
+      this.real.setAttribute('fill', this.fillColor)
+      this.real.setAttribute('rx', r1.toString())
+      this.real.setAttribute('ry', r2.toString())
+      this.real.setAttribute('stroke-width', strokeWidth.toString())
+      this.real.setAttribute('stroke', this.storkeColor)
     } catch (e) {
-      console.error(this)
+      console.error(this.x)
     }
 
 

+ 1 - 0
src/CAD/core/core/line.ts

@@ -22,6 +22,7 @@ class Line extends FixedLine {
   }
   
   setHoverStyle() {
+    console.log(this.hover)
     Object.keys(this.hover).forEach(k => this[k] = this.hover[k])
   }
 

+ 1 - 16
src/CAD/core/core/wallfixedline.ts

@@ -20,7 +20,6 @@ class WallLine extends FixedLine {
   ground: SVGGElement
   origin: SVGPathElement
   temp: SVGGElement
-  testText: SVGTextElement
   
   exterior: boolean
   static minWidth = 0.1
@@ -326,8 +325,6 @@ class WallLine extends FixedLine {
     node.appendChild(this.temp)
     this.temp.setAttribute('pointer-events', 'none')
 
-    this.testText = document.createElementNS(SVGURI, 'text')
-    node.appendChild(this.testText)
     
     return node
   }
@@ -344,7 +341,7 @@ class WallLine extends FixedLine {
     }
 
     if (this.exterior) {
-      this.origin.setAttribute('stroke', '#5e5e5e')
+      this.origin.setAttribute('stroke', this.color === this.hover.color ? this.color : '#5e5e5e')
       this.origin.setAttribute('stroke-dasharray', `${10 * this.multiple}, ${10 * this.multiple}`)
     } else {
       this.origin.setAttribute('stroke', this.color)
@@ -449,18 +446,6 @@ class WallLine extends FixedLine {
     
     this.temp.innerHTML = ''
 
-
-    setTimeout(() => {
-      let center = lineCenter(this)
-      this.testText.setAttribute('fill', 'red')
-      this.testText.setAttribute('text-anchor', 'middle')
-      this.testText.setAttribute('dominant-baseline', 'middle')
-      this.testText.setAttribute('x', center.x.toString())
-      this.testText.setAttribute('y', center.y.toString())
-      this.testText.setAttribute('font-size', (12*this.multiple).toString())
-      this.testText.textContent = this.renderer.processing.lines.find(({ele}) => (ele as any) === this).id + ''
-    })
-
     if (!this.showAngle && this.color !== this.hover.color) return;
 
     let joinLines = this.renderer.processing.lines.filter(line => 

+ 3 - 2
src/CAD/core/core/wallline.ts

@@ -36,8 +36,9 @@ class WallLine extends wallFixedLine {
 
   drag(screen) {
     let move = this.renderer.screenToRealPoint(screen)
-
-    this.changePos({ x: move.x - this.startPoint.x, y: move.y - this.startPoint.y });
+    if (!this.exterior) {
+      this.changePos({ x: move.x - this.startPoint.x, y: move.y - this.startPoint.y });
+    }
 
   }
 

+ 86 - 3
src/CAD/core/geometry.ts

@@ -309,7 +309,7 @@ export const getLineDisPoint = (line: Line, dis: number): Point => {
 export const getLineDisSelectPoint = (line: Line, point: Point, dis: number): Point => {
   let [p1, p2] = getDisPointLinePoints(line, point, dis)
 
-  
+
   if (pointLineDis(line, p1) < pointLineDis(line, p2)) {
     return p1
   } else {
@@ -460,6 +460,24 @@ export const pointInside = (face: Array<Point>, point: point) => {
   return inside;
 }
 
+export const isPointInPoly = function (points: Array<Point>, point: point) {
+  var x = point.x, y = point.y;
+  var inside = false;
+  for (var i = 0, j = points.length - 1; i < points.length; j = i++) {
+    var pt1 = points[i];
+    var pt2 = points[j];
+
+    var xi = pt1.x, yi = pt1.y;
+    var xj = pt2.x, yj = pt2.y;
+
+    var intersect = ((yi > y) != (yj > y))
+      && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
+    if (intersect) inside = !inside;
+  }
+
+  return inside;
+}
+
 
 /**
  * 判断一个点是否在面线上
@@ -677,7 +695,7 @@ export const lineDeg = (line: Line) => {
 }
 
 //两条相交的线段的夹角,永远小于180度
-export const getAngle = function(line1: Line, line2: Line) {
+export const getAngle = function (line1: Line, line2: Line) {
   let o, s, e, index
   if (~(index = line1.points.indexOf(line2.points[0]))) {
     o = line1.points[index]
@@ -709,4 +727,69 @@ export const getAngle = function(line1: Line, line2: Line) {
   else {
     return 360 - 180 * fi / Math.PI;
   }
-}
+}
+
+
+
+export const rotatePoint = (p, angle, center) => {
+  let p2 = {
+    x: p.x - center.x,
+    y: p.y - center.y
+  }
+  let p3 = {
+    x: Math.cos(angle) * p2.x - Math.sin(angle) * p2.y,
+    y: Math.sin(angle) * p2.x + Math.cos(angle) * p2.y
+  }
+  return {
+    x: p3.x + center.x, 
+    y: p3.y + center.y
+  }
+} 
+
+
+export const rotateData = (data, angle, center) => {
+  try {
+    const tarchs = ['window', 'door', 'slideDoor', 'groundCase', 'bayCase', 'doubleDoor']
+    const twarchs = ['furnColumn', 'furnFlue', 'column']
+
+    data = JSON.parse(JSON.stringify(data))
+    data["vertex"].forEach(p => {
+      let newP = rotatePoint(p, angle, center)
+      p.x = newP.x
+      p.y = newP.y
+    })
+    data["tagging"].forEach(p => {
+      let newP = rotatePoint({x: p.pos[0], y: p.pos[1]}, angle, center)
+      p.pos[0] = newP.x
+      p.pos[1] = newP.y
+    })
+    
+
+
+    tarchs.concat(twarchs).forEach(key => {
+      data[key].forEach(arch => {
+        let newP1 = rotatePoint({x: arch.pos[0], y: arch.pos[1]}, angle, center)
+        let newP2 = rotatePoint({x: arch.pos[2], y: arch.pos[3]}, angle, center)
+        arch.pos[0] = newP1.x
+        arch.pos[1] = newP1.y
+        arch.pos[2] = newP2.x
+        arch.pos[3] = newP2.y
+      })
+    })
+    
+    twarchs.forEach(key => {
+      data[key].forEach(arch => {
+        let newP1 = rotatePoint({x: arch.pos[4], y: arch.pos[5]}, angle, center)
+        let newP2 = rotatePoint({x: arch.pos[6], y: arch.pos[7]}, angle, center)
+        arch.pos[4] = newP1.x
+        arch.pos[5] = newP1.y
+        arch.pos[6] = newP2.x
+        arch.pos[7] = newP2.y
+      })
+    })
+
+    return data
+  } catch (e) {
+    return data
+  }
+}

+ 5 - 1
src/CAD/core/index.ts

@@ -4,6 +4,7 @@ import {insert, attachInsert} from './additional/insert'
 import {label, attachGauge} from './additional/label'
 import {sign, attachSign} from './additional/sign'
 import {Screenshot, attachScreenshot} from './additional/screenshot'
+import {Custom, attchCustom} from './additional/customized'
 import {transformRet, stackRet, autoPreservation, attchTransform, attchStack} from './additional/dataHandle'
 import {DOMTransform, attchDOMTranform} from './additional/transform'
 import {Disabled, attachDisabled} from './additional/disabled'
@@ -11,7 +12,7 @@ import {Local, attachRote} from './additional/rote'
 import {Style, attachStyle} from './additional/styleSet'
 import { Data } from './base/processing/index'
 
-export type BasicCAD = CAD & insert & stackRet & label & DOMTransform & Screenshot & Disabled & Local & Style & sign
+export type BasicCAD = CAD & insert & stackRet & label & DOMTransform & Screenshot & Disabled & Local & Style & sign & Custom
 export type AttachCAD = BasicCAD & transformRet
 export interface CADArgs {
   data: Data,
@@ -22,6 +23,7 @@ export interface CADArgs {
 export function structureCAD({data, layer, padding = 40}: CADArgs): AttachCAD {
   let cad = new CAD({ dom: layer, padding }) as AttachCAD
 
+  attchCustom(cad)
   attachInsert(cad)
   attchTransform(cad)
   attchStack(cad)
@@ -38,6 +40,8 @@ export function structureCAD({data, layer, padding = 40}: CADArgs): AttachCAD {
   cad.loadData(data)
   cad.openMouseHandle()
   cad.showGauge()
+
+
   
   return cad
 }

+ 111 - 0
src/CAD/core/label/SelectPoint.ts

@@ -0,0 +1,111 @@
+import {CADElement, ElementProps} from '../core/element'
+import {SVGURI} from '../constant/Element'
+import {Point} from '../geometry'
+import Renderer from '../base/renderer'
+import { point } from '../core/fixedpoint'
+
+export interface StyleProps {
+  border?: number,
+  r?: number,
+  show?: boolean,
+  selectColor?: string,
+  text?: string,
+  color?: string
+}
+
+export interface SeftProps extends ElementProps  {
+  points: Array<Point & {text: string}>
+  selectIndex: number,
+  room: Array<point>,
+  selectDom: boolean
+}
+
+class SelectPoint extends CADElement<SeftProps & StyleProps> {
+  pointEles: Array<[SVGCircleElement, SVGTextElement]>
+  polygon: SVGPathElement
+  
+  static Setting = new Map<Renderer, StyleProps>()
+
+  constructor({border = 1, r = 4, show = true, color = 'rgb(0, 200, 175)', selectDom = false, selectColor = 'rgb(0, 200, 175)', ...args} : SeftProps & StyleProps) {
+    super({border, r, show, color, selectColor, selectDom, ...args})
+    this.update()
+  }
+
+  grentNode() {
+    let node = document.createElementNS(SVGURI, 'g')
+
+    this.polygon = document.createElementNS(SVGURI, 'path')
+    this.polygon.setAttribute('stroke', this.selectColor)
+    this.polygon.setAttribute('d', `M ${this.room.map(point => point.x + ' ' + point.y).join(' L ')} Z`)
+    this.polygon.setAttribute('fill', 'rgba(0,0,0,0)')
+
+    this.pointEles = this.points.map(() => {
+      let inner = document.createElementNS(SVGURI, 'circle')
+      inner.setAttribute('stroke', '#fff')
+      
+      let text = document.createElementNS(SVGURI, 'text')
+      text.setAttribute('fill', '#fff')
+      text.setAttribute('text-anchor', 'middle')
+      text.setAttribute('dy', '.4em')
+
+      node.appendChild(inner)
+      node.appendChild(text)
+      return [inner, text]
+    })
+
+
+    node.appendChild(this.polygon)
+    return node
+  }
+
+  setHoverStyle() {
+    this.selectDom = true
+  }
+  setUnHoverStyle() {
+    this.selectDom = false
+  }
+
+  click(ev) {
+    let selectIndex = this.pointEles.findIndex(([ele, text]) => 
+      ele === ev.target ||
+      text === ev.target ||
+      ele.contains(ev.target) || 
+      text.contains(ev.target)
+    )
+
+    if (this.selectIndex === selectIndex) {
+      this.selectIndex = -1
+    } else {
+      this.selectIndex = selectIndex
+    }
+  }
+
+  update() {
+    
+    if (this.selectDom || ~this.selectIndex) {
+      this.polygon.setAttribute('stroke-width', (4 * this.multiple).toString())
+      this.polygon.style.display = 'block'
+    } else {
+      this.polygon.style.display = 'none'
+    }
+      this.polygon.style.display = 'none'
+
+    this.pointEles.forEach(([inner, text], i) => {
+      inner.setAttribute('fill', this.selectIndex === i ? this.selectColor : this.color)
+      inner.setAttribute('r', (this.r * this.multiple).toString())
+      inner.setAttribute('stroke-width', (this.border * this.multiple).toString())
+      inner.setAttribute('cx', this.points[i].x.toString())
+      inner.setAttribute('cy', this.points[i].y.toString())
+      
+      text.setAttribute('font-size', (12 * this.multiple).toString())
+      text.setAttribute('x', this.points[i].x.toString())
+      text.setAttribute('y', this.points[i].y.toString())
+      text.textContent = this.points[i].text
+      text.setAttribute('fill', '#fff')
+    })
+    
+    this.real.style.display = this.show ? 'inherit': 'none'
+  }
+}
+
+export default SelectPoint

+ 11 - 8
src/CAD/core/label/gauge.ts

@@ -9,6 +9,7 @@ import {
   lineDis,
   lineVector
 } from '../geometry'
+import { ProcessingTS } from '../base/processing'
 
 
 export interface SeftProps extends ElementProps, PublicProps {
@@ -26,7 +27,7 @@ export interface PublicProps {
 }
 
 export interface Props extends UpdateProps {
-  cad: CAD
+  processing: ProcessingTS
 }
 
 export interface UpdateProps extends PublicProps {
@@ -111,9 +112,10 @@ class Gauge extends CADElement<SeftProps> {
   right: SVGGElement
   bottom: SVGGElement
   spacing: number
+  processing: ProcessingTS
 
   constructor({
-    cad, 
+    processing, 
     padding = 10, 
     spacing = 4, 
     minPX = 50, 
@@ -127,9 +129,9 @@ class Gauge extends CADElement<SeftProps> {
     ...args
   }: Props) {
     super({
+      renderer: processing.render,
       minPX,
       width,
-      renderer: cad.processing.render,
       showBottom,
       showTop,
       showLeft,
@@ -138,16 +140,17 @@ class Gauge extends CADElement<SeftProps> {
       stroke,
       ...args
     })
-    this.cad = cad
     this.padding = padding
     this.spacing = spacing
+    this.processing = processing
 
     Object.defineProperty(this, 'points', {
       get() {
-        return cad.processing.points
+        return this.processing.points
       }
     })
     
+    
     this.update()
   }
 
@@ -168,7 +171,7 @@ class Gauge extends CADElement<SeftProps> {
 
   calcSplit() {
     // 一条线段最小间距
-    const render = this.cad.processing.render
+    const render = this.processing.render
     const minPX = this.minPX
     const minXDire = lineDis({points: [
       render.screenToRealPoint({x: 0, y: 0}),
@@ -213,9 +216,9 @@ class Gauge extends CADElement<SeftProps> {
   }
 
   update() {
-    if (this.points.length === 0 || this.cad.processing.render.props.width === 0) return;
+    if (this.points.length === 0 || this.processing.render.props.width === 0) return;
 
-    const render = this.cad.processing.render
+    const render = this.processing.render
     const fontSize = this.width * 10 * this.multiple
     const {left, right, top, bottom} = this.calcSplit()
     let ltpoint = render.screenToRealPoint({x: this.padding, y:  this.padding})

+ 66 - 0
src/CAD/core/label/mapping.ts

@@ -0,0 +1,66 @@
+import {CADElement, ElementProps} from '../core/element'
+import {SVGURI, SVGPATH} from '../constant/Element'
+import { getMaping } from '../constant/Label'
+import {Point as BasicPoint} from '../geometry'
+
+let id = 0
+
+export interface SeftProps extends ElementProps {
+  show?: boolean,
+  points: Array<BasicPoint>,
+  label: string
+}
+
+class Mapping extends CADElement<SeftProps> {
+  path: SVGPathElement
+  maping: SVGImageElement
+  pattern: SVGPatternElement
+
+  constructor(props : SeftProps) {
+    super(props)
+  }
+
+  grentNode() {
+    let pid = 'pattern-' + (++id)
+    let node = document.createElementNS(SVGURI, 'g')
+    this.path = document.createElementNS(SVGURI, 'path')
+    this.pattern = document.createElementNS(SVGURI, 'pattern');
+
+    this.maping = document.createElementNS(SVGURI, 'image')
+
+    this.pattern.append(this.maping)
+    
+    this.pattern.setAttribute('id', pid)
+    this.pattern.setAttribute('patternUnits', 'userSpaceOnUse')
+
+    this.path.setAttribute('fill', `url(#${pid})`)
+
+    node.appendChild(this.path)
+    node.appendChild(this.pattern)
+    return node
+  }
+
+  update() {
+    let locals = `M` + this.points.map(point => ` ${point.x} ${point.y} `).join('L') + 'z'
+    let endPoint = this.renderer.screenToRealPoint({x: 30, y: 30})
+    let startPoint = this.renderer.screenToRealPoint({x: 0, y: 0})
+    let imgWidth = Math.abs(endPoint.x - startPoint.x)
+    let imgHeight = Math.abs(endPoint.y - startPoint.y)
+    
+
+    if (!this.icon || this.icon !== this.firstIcon) {
+      this.icon = getMaping(this.label)
+      this.maping.href.baseVal = this.icon
+      this.firstIcon = this.icon
+    }
+
+    this.maping.setAttribute('width', imgWidth.toString())
+    this.maping.setAttribute('height', imgHeight.toString())
+    this.pattern.setAttribute('width', imgWidth.toString())
+    this.pattern.setAttribute('height', imgHeight.toString())
+
+    this.path.setAttribute('d', locals)
+  }
+}
+
+export default Mapping

+ 3 - 3
src/CAD/core/label/sign.ts

@@ -77,9 +77,9 @@ class Sign extends CADElement<SeftProps & StyleProps> {
     this.inner.setAttribute('cx', this.pos.x.toString())
     this.inner.setAttribute('cy', this.pos.y.toString())
 
-    const minArg = 2 * this.multiple
-    const ctrArg = 8 * this.multiple
-    const maxArg = 14 * this.multiple
+    const minArg = this.r * 0.4 * this.multiple
+    const ctrArg = this.r * 1.6 * this.multiple
+    const maxArg = this.r * 2.8 * this.multiple
 
     this.arc.setAttribute('d', `
       M ${this.pos.x} ${this.pos.y - minArg} 

+ 23 - 46
src/CAD/core/label/tagging.ts

@@ -1,8 +1,6 @@
 import {CADElement, ElementProps} from '../core/element'
 import {SVGURI} from '../constant/Element'
 import {Point as dataPoint} from '../geometry'
-import Point from '../core/point'
-import {strEascpeLen} from '../util'
 import { i18n } from '../../../../lang/index'
 export interface BasicProps extends ElementProps {
   title: string,
@@ -14,7 +12,8 @@ export interface BasicProps extends ElementProps {
 }
 
 export interface ParentProps extends BasicProps {
-  point: Point
+  x: number,
+  y: number,
   color?: string
 }
 
@@ -24,38 +23,29 @@ export interface SeftProps extends BasicProps {
 }
 
 class Tagging extends CADElement<ParentProps> {
-  point: Point
   inner: SVGCircleElement
   arc: SVGPathElement
   titleNode: SVGTextElement
   contentNode: SVGTextElement
 
   constructor({pos, renderer, fontSize = 12, color='#fff',...args}: SeftProps) {
-    let point = new Point({ 
-      x: pos.x,
-      y: pos.y,
-      renderer, 
-      r1: fontSize,
-      r: fontSize * args.title.length,
-      fillColor: 'rgba(0,0,0,0)',
-      hover: {
-        fillColor: 'rgba(255,255,255,0)'
-      }
-    })
-    super({...args, point, fontSize, renderer, color})
+    super({...args, x: pos.x, y: pos.y, fontSize, renderer, color})
     this.zIndex = -1
-
-    this.point.changeSelect = (...args) => {
-      this.changeSelect(...args)
-    }
-
-    renderer.push(this.point)
   }
 
   changeSelect(isSelect) {
     super.changeSelect(isSelect)
   }
 
+  dragStart() {
+    this.dragStartPoint = { x: this.x, y: this.y }
+  }
+  
+  drag(offset) {
+    this.x = this.dragStartPoint.x + offset.x * this.multiple
+    this.y = this.dragStartPoint.y + offset.y * this.multiple
+  }
+
   grentNode() {
     let node = document.createElementNS(SVGURI, 'g')
 
@@ -77,19 +67,24 @@ class Tagging extends CADElement<ParentProps> {
     return node
   }
 
+  setHoverStyle() {
+  }
+  setUnHoverStyle() {
+  }
+
   update() {
     let fontSize = this.fontSize * this.multiple
 
-    this.point.real.style.display = this.show ? 'inherit' : 'none'
+    // this.point.real.style.display = this.show ? 'inherit' : 'none'
     
-    this.titleNode.setAttribute('x', this.point.x.toString())
-    this.titleNode.setAttribute('y', this.point.y.toString())
+    this.titleNode.setAttribute('x', this.x.toString())
+    this.titleNode.setAttribute('y', this.y.toString())
     this.titleNode.setAttribute('font-size', fontSize.toString())
     this.titleNode.style.display = this.show && this.showTitle ? 'inherit' : 'none'
-    this.titleNode.textContent = this.title || i18n.t('modules.model.tagging_name_tips')
+    this.titleNode.textContent = this.title || i18n.t('modules.model.tagging_name_tips') as any
     
-    this.contentNode.setAttribute('x', this.point.x.toString())
-    this.contentNode.setAttribute('y', (this.point.y + fontSize).toString())
+    this.contentNode.setAttribute('x', this.x.toString())
+    this.contentNode.setAttribute('y', (this.y + fontSize + fontSize / 5).toString())
     this.contentNode.setAttribute('font-size', fontSize.toString())
     this.contentNode.style.display = this.show && this.showContent ? 'inherit' : 'none'
     this.contentNode.textContent = this.content
@@ -103,26 +98,8 @@ class Tagging extends CADElement<ParentProps> {
     }
   }
 
-  intercept (stick, {title, content}) {
-    if (title || content) {
-      title = title || this.title
-      content = content || this.content
-      
-      let width = Math.max(
-        strEascpeLen(title),
-        strEascpeLen(content)
-      ) / 4
-      
-      this.point.r = width * this.fontSize
-      this.point.r1 = this.fontSize
-    }
-    return true
-  }
-
   destroy() {
     super.destroy()    
-    this.point.destroy()
-    this.renderer.remove(this.point)
   }
 }
 

+ 34 - 27
src/CAD/eleAttr.ts

@@ -17,17 +17,17 @@ import {
 } from './core/geometry'
 import processing from './core/base/processing/index'
 
-// 拦截arch门窗柱子墙线条添加方法, 添加额外属性
-export default (cad: AttachCAD) => {
-  let addCase = cad.processing.addCase
-  let addDoor = cad.processing.addDoor
-  let addColumn = cad.processing.addColumn
-  let addLine = cad.processing.addLine
-  let addSlideDoor = cad.processing.addSlideDoor
-  let addBayCase = cad.processing.addBayCase
-  let addGroundCase = cad.processing.addGroundCase
-  let addFurnColumn = cad.processing.addFurnColumn
-  let addFurnFlue = cad.processing.addFurnFlue
+function attrAdd(cad, processing) {
+  let addCase = processing.addCase
+  let addDoor = processing.addDoor
+  let addColumn = processing.addColumn
+  let addLine = processing.addLine
+  let addSlideDoor = processing.addSlideDoor
+  let addBayCase = processing.addBayCase
+  let addGroundCase = processing.addGroundCase
+  let addFurnColumn = processing.addFurnColumn
+  let addFurnFlue = processing.addFurnFlue
+  let adddDoubleDoor = processing.adddDoubleDoor
 
   // 添加与宽度相关的属性
   let addWidthAttr = (ele: Column | Door | Casement ) => {
@@ -191,46 +191,51 @@ export default (cad: AttachCAD) => {
   }
 
 
-  cad.processing.addCase = function(...args) {
+  processing.addCase = function(...args) {
     let ret = addCase.call(this, ...args)
     addWidthAttr(ret.ele)
     return ret
   }
   
-  cad.processing.addBayCase = function(...args) {
+  processing.addBayCase = function(...args) {
     let ret = addBayCase.call(this, ...args)
     addWidthAttr(ret.ele)
     return ret
   }
   
-  cad.processing.addGroundCase = function(...args) {
+  processing.addGroundCase = function(...args) {
     let ret = addGroundCase.call(this, ...args)
     addWidthAttr(ret.ele)
     return ret
   }
 
-  cad.processing.addDoor = function(...args) {
+  processing.addDoor = function(...args) {
     let ret = addDoor.call(this, ...args)
     addWidthAttr(ret.ele)
     addStartAttr(ret.ele)
     return ret
   }
   
-  cad.processing.addSlideDoor = function(...args) {
+  processing.addSlideDoor = function(...args) {
     let ret = addSlideDoor.call(this, ...args)
     addWidthAttr(ret.ele)
     return ret
   }
 
+  processing.adddDoubleDoor = function(...args) {
+    let ret = adddDoubleDoor.call(this, ...args)
+    addWidthAttr(ret.ele)
+    return ret
+  }
 
-  cad.processing.addColumn = function(...args) {
+  processing.addColumn = function(...args) {
     let ret = addColumn.call(this, ...args)
     addWidthAttr(ret.ele)
     addTickAttr(ret.ele)
     return ret
   }
 
-  cad.processing.addLine = function(...args) {
+  processing.addLine = function(...args) {
     let ret = addLine.call(this, ...args)
     return ret
   }
@@ -307,7 +312,7 @@ export default (cad: AttachCAD) => {
   }
 
   
-  cad.processing.addFurnColumn = function(...args) {
+  processing.addFurnColumn = function(...args) {
     let ret = addFurnColumn.call(this, ...args)
     addFurnWidthAttr(ret.ele)
     addFurnTickAttr(ret.ele)
@@ -315,7 +320,7 @@ export default (cad: AttachCAD) => {
     return ret
   }
 
-  cad.processing.addFurnFlue = function(...args) {
+  processing.addFurnFlue = function(...args) {
     let ret = addFurnFlue.call(this, ...args)
     addFurnWidthAttr(ret.ele)
     addFurnTickAttr(ret.ele)
@@ -323,13 +328,15 @@ export default (cad: AttachCAD) => {
     return ret
   }
 
+}
+
+// 拦截arch门窗柱子墙线条添加方法, 添加额外属性
+export default (cad: AttachCAD) => {
+  const addProcessing = cad.addProcessing
+  cad.addProcessing = (...args) => {
+    let processing = addProcessing.call(cad, ...args)
 
-  let destroy = cad.destroy
-  cad.destroy = function(...args) {
-    addCase = null
-    addDoor = null
-    addColumn = null
-    addLine = null
-    destroy.apply(this, args)
+    attrAdd(cad, processing)
+    return processing
   }
 }

+ 13 - 5
src/CAD/index.ts

@@ -1,4 +1,4 @@
-//import 'core-js'
+import 'svg-innerhtml-polyfill'
 import {BasicCAD as CADTS, AttachCAD} from './core/index'
 import CAD from './core/base/cad'
 import {attachInsert} from './core/additional/insert'
@@ -10,6 +10,7 @@ import {attchDOMTranform} from './core/additional/transform'
 import {attachDisabled} from './core/additional/disabled'
 import {attachRote} from './core/additional/rote'
 import {attachStyle} from './core/additional/styleSet'
+import {Custom, attchCustom} from './core/additional/customized'
 import eleAttr from './eleAttr'
 import {other, Other} from './other'
 import Column from './core/architecture/column'
@@ -20,16 +21,20 @@ import Rote from './core/label/route'
 import screenAdapt from './screenAdapt'
 import toCanvas from './toCanvas'
 
+
 {
   const listen = CADElement.prototype.listen
   CADElement.prototype.listen = function (...args) {
-    if (this.render.edit || this instanceof Rote) {
+    let isEdit = this.render.processing.cad.edits.some(cls => this instanceof cls)
+    if (isEdit || this.render.processing.cad.edit || this instanceof Rote) {
       listen.call(this, ...args)
     }
   }
+
   const addEvent = Column.prototype.addEvent
   Column.prototype.addEvent = function (...args) {
-    this.render.edit && addEvent.call(this, ...args)
+    let isEdit = this.render.processing.cad.edits.some(cls => this instanceof cls);
+    (isEdit || this.render.processing.cad.edit) && addEvent.call(this, ...args)
   }
 }
 
@@ -43,14 +48,16 @@ export interface Args {
 
 import Point from './core/core/fixedpoint'
 import { Data } from './core/base/processing'
+import Tagging from './core/label/tagging'
 
 export function structureCAD({data, layer, edit = true, padding = 20}: Args): EXPCAD {
   let cad = new CAD({ dom: layer, padding }) as AttachCAD
-  cad.processing.render.edit = edit
+  cad.edit = edit
 
 
+  attachInsert(cad)
+  
   if (edit) {
-    attachInsert(cad)
     attchTransform(cad)
     attchStack(cad)
     autoPreservation(cad)
@@ -62,6 +69,7 @@ export function structureCAD({data, layer, edit = true, padding = 20}: Args): EX
     attchDOMTranform(cad)
   }
 
+  attchCustom(cad)
   attachStyle(cad)
   attachScreenshot(cad)
   attachSign(cad)

+ 18 - 7
src/CAD/other.ts

@@ -10,20 +10,31 @@ export interface Other{
 // 附加走过路径的label
 export const other = (cad: CAD) => {
   let show = false
-  let addTagging = cad.processing.addTagging
+  let addProcessing = cad.addProcessing
+  cad.addProcessing = (...args) => {
+    let processing = addProcessing.call(cad, ...args)
 
-  cad.processing.addTagging = (args) => {
-    (args as any).show = show
-    return addTagging.call(cad.processing, args)
-  }
+    let addTagging = processing.addTagging
 
+    processing.addTagging = (args) => {
+      (args as any).show = show
+      return addTagging.call(processing, args)
+    }
+  
+    return processing
+  }
+  
   cad.hideLabel = () => {
     show = false
-    cad.processing.taggings.forEach(t => t.ele.show = false)
+    cad.processings.forEach(processing => {
+      processing.taggings.forEach(t => t.ele.show = show)
+    })
   }
 
   cad.showLabel = () => {
     show = true
-    cad.processing.taggings.forEach(t => t.ele.show = show)
+    cad.processings.forEach(processing => {
+      processing.taggings.forEach(t => t.ele.show = show)
+    })
   }
 }

+ 175 - 139
src/CAD/screenAdapt.ts

@@ -1,7 +1,11 @@
 import {EXPCAD} from './index'
 import {roateDataY} from './core/additional/dataHandle'
+import { CADElement } from './core/core/element'
+import Mapping from './core/label/mapping'
+import calcRoom from './calcRoom'
+import {isFaceContain, pointInside} from './core/geometry'
 
-const setStyle = async (cad: EXPCAD, lineWidth) => {
+const setStyle = (cad: EXPCAD, lineWidth) => {
   const processing = cad.processing
   const doors = processing.doors
   const slideDoors = processing.slideDoors
@@ -22,72 +26,63 @@ const setStyle = async (cad: EXPCAD, lineWidth) => {
     ...cases,
     ...doors
   ]
-
-  const pros = []
-
-  pros.concat(tags.map(door => {
+  
+  tags.forEach(door => {
     let fontSize = lineWidth * 3
     door.ele.fontSize = fontSize < 12 ? 12 : fontSize
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }));
+  });
 
 
-  pros.concat(fcArchs.map(door => {
+  fcArchs.forEach(door => {
     door.ele.width = lineWidth * 0.33
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
+  })
 
-  pros.concat(slideDoors.map(door => {
+  slideDoors.forEach(door => {
     door.ele.foorWidth = lineWidth*2 / (door.ele.attachment.border ? 1 : 2)
     door.ele.bwithin = lineWidth / 2 / (door.ele.attachment.border ? 1 : 2)
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
-
-  pros.concat(cases.map(door => {
-    door.ele.width = lineWidth /2 * (door.ele.attachment.border ? 1 : 2)
-    door.ele.stamWidth = lineWidth * 0.166 / (door.ele.attachment.border ? 1 : 2)
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
-  pros.concat(pwidthArchs.map(door => {
+  })
+
+  cases.forEach(door => {
+    door.ele.width = (lineWidth * 4 /2) / (door.ele.attachment.border ? 1 : 1.5)
+    door.ele.stamWidth = (lineWidth * 0.1) / (door.ele.attachment.border ? 1 : 2)
+    door.ele.outLine.width = door.ele.width
+    door.ele.outLine.color = door.ele.fill
+    door.ele.innerline.width = door.ele.stamWidth
+    door.ele.innerline.color = door.ele.seam
+    door.ele.innerline.update()
+  })
+  pwidthArchs.forEach(door => {
     door.ele.width = lineWidth 
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
-  pros.concat(bayCases.map(door => {
+  })
+  bayCases.forEach(door => {
     door.ele.width = lineWidth * 0.33 / (door.ele.attachment.border ? 1 : 2)
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
-  pros.concat(groundCases.map(door => {
+  })
+  groundCases.forEach(door => {
     door.ele.width = lineWidth / 2 * (door.ele.attachment.border ? 1 : 2)
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
-  pros.concat(doors.map(door => {
+  })
+  doors.forEach(door => {
     door.ele.foorWidth = lineWidth * 2 / (door.ele.attachment.border ? 1 : 2)
     door.ele.outWidth = lineWidth * 0.33 / (door.ele.attachment.border ? 1 : 2)
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
-  pros.concat(points.map(door => {
+  })
+  points.forEach(door => {
     door.ele.r1 = lineWidth + 1
     door.ele.r = lineWidth + 1
-    return new Promise(resolve => door.ele.nextTick(resolve))
-  }))
-  pros.concat(pchildPoints.map(door => {
+  })
+  pchildPoints.forEach(door => {
     door.ele.linePoints[0].r1 = lineWidth + 1
     door.ele.linePoints[0].r = lineWidth + 1
     door.ele.linePoints[1].r1 = lineWidth + 1
     door.ele.linePoints[1].r = lineWidth + 1
-  }))
-
-  pros.push(
-    cad.setDireAttrs({
-      fontSize: 2.6 * lineWidth,
-      r: 16.6 * lineWidth,
-      border: lineWidth,
-      right: lineWidth * 6.3,
-      top: lineWidth * 6.3,
-      ArgDire: lineWidth * 5
-    })
-  )
-  await Promise.all(pros)
+  })
+
+  cad.setDireAttrs({
+    fontSize: 2.6 * lineWidth,
+    r: 16.6 * lineWidth,
+    border: lineWidth,
+    right: lineWidth * 6.3,
+    top: lineWidth * 6.3,
+    ArgDire: lineWidth * 5
+  })
 }
 
 
@@ -98,130 +93,175 @@ export default (cad: EXPCAD) => {
     width = 1920 * 3 / 2, 
     height = 1080 * 3 / 2, 
     primaryColor = '#fff',
+    archColor = 'rgba(0,0,0,0)',
     bgColor = 'rgba(0,0,0,0)', 
-    data = roateDataY((cad as any).getData(true, true)), 
+    textColor = '#fff',
+    archBorder = primaryColor,
+    data = (cad as any).getData(true, true), 
     padding = 3 * 15 * 20 / 2, 
     showGauge = true, 
     lineWidth = 20 / 2,
+    spliceGauge = false,
     showDire = false,
     showTags = true,
-    showDoorStart = true
+    showDoorStart = true,
+    showMapping = false,
+    format = 'image/png',
+    errreturn = false
   } = {}) => {
+    data = roateDataY(data.floors.find(floor => floor.show))
     const lwidth = cad.processing.lines[0] ? cad.processing.lines[0].ele.width : 3
     cad.processing.render.layer.style.opacity = '0'
 
-    cad.processing.lines.forEach(({ele: line}) => {
-      line.color = primaryColor
+    let mappings = []
+    let promiseAll = []
+    
+    CADElement.examples.get(cad.processing.render).forEach(ele => {
+      promiseAll.push(new Promise(r => ele.nextTick(r)))
+    })
+
+    await Promise.all(promiseAll)
+
+    
+    CADElement.examples.get(cad.processing.render).forEach(ele => {
+      ele.__state.direct = true
+      ele.changeSelect(false)
     })
 
+    
+    if (showMapping) {
+      let useTaggings = []
+      let rooms = calcRoom(data)
+      rooms = rooms
+        .map(points => points)
+        .sort((room1, room2) => isFaceContain(room1, room2) ? 1 : -1)
+
+      rooms.forEach((points, index) => {
+        let tagging = cad.processing.taggings.find(tag => pointInside(points, tag.ele) && !~useTaggings.indexOf(tag))
+        let mapping = new Mapping({
+          points,
+          label: tagging ? tagging.ele.title : '',
+          show: true,
+          renderer: cad.processing.render
+        })
+
+  
+        mapping.zIndex = -index - 3
+        mapping.update()
+        cad.processing.render.push(mapping)
+
+        mappings.push(mapping)
+        useTaggings.push(tagging)
+      })
+    }
+    
+
     let attrs: any = [
-      {key: 'stroke', attr: ['doors', 'columns', 'bayCases', 'furnColumns', 'furnFlues'], oldVals: []},
-      {key: 'fill', attr: ['cases', 'groundCases'], oldVals: []},
-      {key: 'foorColor', attr: ['slideDoors'], oldVals: []},
-      {key: 'color', attr: ['taggings'], oldVals: []},
-      {key: 'icon', attr: ['doors'], oldVals: []}
+      {key: 'stroke', attr: ['doors', 'columns', 'bayCases', 'furnColumns', 'furnFlues', 'doubleDoors'], oldVals: [], newColor: archBorder},
+      {key: 'fill', attr: ['groundCases'], oldVals: [], newColor: archBorder},
+      {key: 'seam', attr: ['cases'], oldVals: [], newColor: primaryColor},
+      {key: 'bgColor', attr: ['cases'], oldVals: [], newColor: primaryColor},
+      {key: 'color', attr: ['lines'], oldVals: [], newColor: primaryColor},
+      {key: 'icon', attr: ['doors'], oldVals: [], newColor: primaryColor},
+      {key: 'fill', attr: ['cases', 'doors', 'columns', 'bayCases', 'furnColumns', 'furnFlues', 'slideDoors', 'doubleDoors'], oldVals: [], newColor: archColor},
+      {key: 'foorColor', attr: ['slideDoors'], oldVals: [], newColor: archBorder},
+      {key: 'clipColor', attr: ['slideDoors'], oldVals: [], newColor: archColor},
+      {key: 'color', attr: ['taggings'], oldVals: [], newColor: textColor}
+      
     ]
-
-    attrs.forEach(({key, attr: kattr, oldVals}) => {
+    attrs.forEach(({key, attr: kattr, oldVals, newColor}) => {
       kattr.forEach((attr) => {
         oldVals.push(cad.processing[attr].map(({ele}) => ele[key]))
         cad.processing[attr].forEach(({ele}) => {
           if (key === 'icon') {
-            ele[key] = primaryColor !== '#fff' ? 'darkIcon' : 'defaultIcon' 
+            ele[key] = newColor !== '#fff' ? 'darkIcon' : 'defaultIcon' 
           } else {
-            ele[key] = primaryColor
+            ele[key] = newColor
           }
+          // console.log('修改属性', ele)
         })
       })
     })
     
+    
 
-    let direShow = cad.direction.show
-    if (!cad.direction.show && showDire) {
+    let direction = cad.processing.direction
+    let direShow = direction.show
+    if (!direction.show && showDire) {
       cad.showDire()
     } else if (!showDire) {
       cad.hideDire()
     }
     
     let tagShow = cad.processing.taggings[0] && cad.processing.taggings[0].ele.show
-    if (showTags && !tagShow) {
-      cad.processing.taggings.forEach(({ele: tag}) => tag.show = true);
-    }
-    cad.processing.attrs.forEach(key => {
-      cad.processing[key].forEach(obj => {
-        obj.ele.select && obj.ele.changeSelect(false)
-      })
-    })
-
+    cad.processing.taggings.forEach(({ele: tag}) => tag.show = showTags);
+    
 
     let pointFill = cad.processing.points[0].ele.fillColor
     let lineFill = cad.processing.lines[0].ele.init.color
-    await Promise.all(
-      cad.processing.points.map(({ele}) => {
-        ele.fillColor = 'rgba(0,0,0,0)'
-        return new Promise(r => ele.nextTick(r))
-      })
-    )
+    cad.processing.points.forEach(({ele}) => {
+      ele.fillColor = 'rgba(0,0,0,0)'
+    })
 
-    let clearPointArchs = [].concat(cad.processing.doors).concat(cad.processing.groundCases).concat(cad.processing.cases)
+    let clearPointArchs = [].concat(cad.processing.doors).concat(cad.processing.groundCases).concat(cad.processing.cases).concat(cad.processing.doubleDoors)
 
     for(let i = 0; i < clearPointArchs.length; i++) {
       let points = (clearPointArchs[i].ele.points || clearPointArchs[i].ele.linePoints)
       if (points) {
-        await Promise.all(
-          points.map(point => {
-            point.fillColor = 'rgba(0,0,0,0)'
-            return new Promise(r => point.nextTick(r))
-          })
-        )
+          points.forEach(point => point.fillColor = 'rgba(0,0,0,0)')
       }
     }
 
-    await setStyle(cad, lineWidth)
-    await cad.setGaugeModel(1)
+    cad.setGaugeModel(1)
     
-    let oldDireIcon = cad.direction.icon
-    await cad.setDireAttrs({ simple: true, icon: primaryColor !== '#fff' ? 'darkIcon' : 'defaultIcon' })
+    let oldDireIcon = direction.icon
+    cad.setDireAttrs({ simple: true, icon: primaryColor !== '#fff' ? 'darkIcon' : 'defaultIcon' })
 
 
     let doorStarts = cad.processing.doors.map(door => door.ele.showStart)
     
-    await Promise.all(
-      cad.processing.doors.map(door => {
-        door.ele.showStart = showDoorStart
-        return new Promise(r => door.ele.nextTick(r))
-      })
-    )
+    cad.processing.doors.forEach(door => door.ele.showStart = showDoorStart)
 
     let oldGaugeColor = cad.gauge && cad.gauge.stroke
+    let minPX = cad.gauge && cad.gauge.minPX
     if (showGauge) {
-      await cad.setGaugeAttrs({
-        minPX: Math.max(width, height),
+      let args: any = {
         width: lineWidth / 2,
-        showBottom: false,
+        showTop: false,
         showRight: false,
         padding: lineWidth * 3.3,
         stroke: primaryColor
-      })
+      }
+      if (!spliceGauge) {
+        args.minPX = Math.max(width, height)
+      } else {
+        args.minPX = 12 * lineWidth
+        console.log('---', args.minPX)
+      }
+      
+      cad.setGaugeAttrs(args)
     }
     
     
+    setStyle(cad, lineWidth)
 
-    cad.processing.attrs.forEach(key => {
-      cad.processing[key].forEach(obj => {
-        obj.ele.update()
-      })
-    })
-
-    await new Promise(r => setTimeout(r, 100))
+    CADElement.examples.get(cad.processing.render).forEach(ele => ele.update())
 
-    const ret = await screenshot.call(this, {width, height, bgColor, data, spadding: padding, showGauge, lineWidth})
+    let ret, err
+    try {
+      ret = await screenshot.call(this, {width, height, bgColor, data, spadding: padding, showGauge, lineWidth, format})
+    } catch(e) {
+      if (errreturn) {
+        return e
+      }
+      err = e
+    }
 
     if (showGauge) {
-      await cad.setGaugeAttrs({
+      cad.setGaugeAttrs({
         minPX: 50,
         width: 1,
-        showBottom: true,
+        showTop: true,
         showRight: true,
         padding: 10,
         stroke: oldGaugeColor
@@ -229,50 +269,31 @@ export default (cad: EXPCAD) => {
     }
 
     
-    attrs.forEach(({key, attr: kattr, oldVals}) => {
-      kattr.forEach((attr, index) => {
-        cad.processing[attr].forEach(({ele}, aindex) => {
-          ele[key] = oldVals[index][aindex]
-        })
-      })
-    })
     
 
-    await cad.setDireAttrs({ simple: false, icon: oldDireIcon })
+    cad.setDireAttrs({ simple: false, icon: oldDireIcon })
     
     for(let i = 0; i < clearPointArchs.length; i++) {
       let points = (clearPointArchs[i].ele.points || clearPointArchs[i].ele.linePoints)
       if (points) {
-        await Promise.all(
-          points.map(point => {
-            point.fillColor = pointFill
-            return new Promise(r => point.nextTick(r))
-          })
-        )
-        }
+          points.map(point => point.fillColor = pointFill)
+      }
     }
 
-    await setStyle(cad, lwidth)
-    await cad.setGaugeModel(0)
+    setStyle(cad, lwidth)
+    cad.setGaugeModel(0)
 
     cad.processing.points.forEach(({ele}) => ele.fillColor = pointFill)
-    await Promise.all(
-      cad.processing.lines.map(({ele}) => {
-        return new Promise(r => {
-          ele.color = lineFill
-          ele.nextTick(r)
-        })
-      })
-    )
+    cad.processing.lines.forEach(({ele}) => ele.color = lineFill)
 
-
-    
+    cad.processing.render.remove(...mappings)
 
     if (direShow) {
-      await cad.showDire()
+      cad.showDire()
     } else {
-      await cad.hideDire()
+      cad.hideDire()
     }
+
     if (tagShow) {
       cad.processing.taggings.forEach(({ele: tag}) => tag.show = true);
     } else {
@@ -284,7 +305,22 @@ export default (cad: EXPCAD) => {
     })
 
     cad.processing.render.layer.style.opacity = '1'
-
+    
+    attrs.forEach(({key, attr: kattr, oldVals}) => {
+      kattr.forEach((attr, index) => {
+        cad.processing[attr].forEach(({ele}, aindex) => {
+          ele[key] = oldVals[index][aindex]
+        })
+      })
+    })
+    
+    CADElement.examples.get(cad.processing.render).forEach(ele => {
+      ele.__state.direct = false
+      ele.update()
+    })
+    if (err) {
+      throw err
+    }
     return ret
   }
 }

+ 22 - 14
src/CAD/toCanvas.ts

@@ -2,14 +2,11 @@ import { EXPCAD } from "./index";
 
 
 const toCanvas = async (cad: EXPCAD, cb?: Function) => {
-  if (!!(window as any).ActiveXObject || "ActiveXObject" in window) {
-    return;
-  }
-  
+  let mut = 3
   let $layer = cad.processing.render.layer
   let $layout = cad.processing.render.g
-  let width = (cad.processing.render.layer.offsetWidth || parseInt(getComputedStyle(cad.processing.render.layer).width)) * 3
-  let height = (cad.processing.render.layer.offsetHeight || parseInt(getComputedStyle(cad.processing.render.layer).height)) * 3
+  let width = ((cad.processing.render.layer.offsetWidth || parseInt(getComputedStyle(cad.processing.render.layer).width))) * mut
+  let height = ((cad.processing.render.layer.offsetHeight || parseInt(getComputedStyle(cad.processing.render.layer).height))) * mut
 
   $layer.style.visibility = 'hidden'
 
@@ -34,23 +31,34 @@ const toCanvas = async (cad: EXPCAD, cb?: Function) => {
   await Promise.all(doms.map(({ele}) => new Promise(r => ele.nextTick(r))))
 
   let $sign = $layer.querySelector('.sign') as SVGGElement
+
   await cad.hideSign()
 
-  let {file} = await cad.screenshot({width, height, bgColor:'rgba(0,0,0,0)', padding: cad.padding, showGauge: false, lineWidth: 2, showDire: false, showTags: false, showDoorStart: false})
-  $layer.style.backgroundImage = `url(${URL.createObjectURL(file)})`
+  try {
+    let {file} = await cad.screenshot({width, height, bgColor:'rgba(0,0,0,0)', padding: cad.padding * mut, showGauge: false, lineWidth: 2, showDire: false, showTags: false, showDoorStart: false, errreturn: true})
+    $layer.style.backgroundImage = `url(${URL.createObjectURL(file)})`
 
-  for (let i = 0; i < $layout.children.length; i++) {
-    if ($layout.children[i] !== $sign) {
-      $layout.removeChild($layout.children[i--])
+    for (let i = 0; i < $layout.children.length; i++) {
+      if ($layout.children[i] !== $sign) {
+        $layout.removeChild($layout.children[i--])
+      }
     }
-  }
+  } catch(e) {
+    console.error(e)
+    cad.padding = cad.padding * mut
+    cad.processing.render.layer.style.transformOrigin = 'left top';
+    cad.processing.render.layer.style.transform = 'scale(' + 1 / mut + ')'
+    cad.setDefaultSignStyle({ r: 5 * mut })
+    cad.adapt(cad.processing.data, width, height)
 
-  await cad.showSign()
+  }
+  
   $sign.style.display = 'block'
   $layer.style.visibility = 'visible'
 
-  cb && cb()
+  await cad.showSign()
 
+  cb && cb()
 }
 
 export default toCanvas

File diff suppressed because it is too large
+ 1 - 1
static/data.js


File diff suppressed because it is too large
+ 699 - 445
static/data.json


+ 768 - 0
static/data1.json

@@ -0,0 +1,768 @@
+{
+  "vertex": [
+    {
+      "id": 3,
+      "x": -2.02,
+      "y": 2.18
+    },
+    {
+      "id": 17,
+      "x": 3.6,
+      "y": -3.73
+    },
+    {
+      "id": 18,
+      "x": 7.48,
+      "y": 4.11
+    },
+    {
+      "id": 21,
+      "x": 0.55,
+      "y": -3.73
+    },
+    {
+      "id": 22,
+      "x": -3.95,
+      "y": -3.73
+    },
+    {
+      "id": 23,
+      "x": -7.56,
+      "y": -3.73
+    },
+    {
+      "id": 25,
+      "x": 0.55,
+      "y": -1.71
+    },
+    {
+      "id": 26,
+      "x": -7.57,
+      "y": 3.78
+    },
+    {
+      "id": 28,
+      "x": 0.53,
+      "y": 1.55
+    },
+    {
+      "id": 30,
+      "x": 5.09,
+      "y": -3.73
+    },
+    {
+      "id": 31,
+      "x": -7.57,
+      "y": 0.18
+    },
+    {
+      "id": 38,
+      "x": -3.64,
+      "y": -3.78
+    },
+    {
+      "id": 39,
+      "x": -3.67,
+      "y": -2.19
+    },
+    {
+      "id": 62,
+      "x": -2.02,
+      "y": 3.8
+    },
+    {
+      "id": 65,
+      "x": 0.53,
+      "y": 3.8
+    },
+    {
+      "id": 83,
+      "x": -3.97,
+      "y": -1.76
+    },
+    {
+      "id": 86,
+      "x": 0.53,
+      "y": 0.18
+    },
+    {
+      "id": 96,
+      "x": -2.55,
+      "y": -2.18
+    },
+    {
+      "id": 97,
+      "x": -2.55,
+      "y": -3.78
+    },
+    {
+      "id": 103,
+      "x": -3.65,
+      "y": -3.78
+    },
+    {
+      "id": 136,
+      "x": 3.6,
+      "y": 1.67
+    },
+    {
+      "id": 139,
+      "x": 7.48,
+      "y": 0.98
+    },
+    {
+      "id": 148,
+      "x": 3.6,
+      "y": -1.76
+    },
+    {
+      "id": 153,
+      "x": 0.53,
+      "y": 2.18
+    },
+    {
+      "id": 159,
+      "x": -6.79,
+      "y": -3.73
+    },
+    {
+      "id": 174,
+      "x": 0.53,
+      "y": 4.11
+    },
+    {
+      "id": 189,
+      "x": 5.09,
+      "y": 1.67
+    },
+    {
+      "id": 195,
+      "x": 5.09,
+      "y": -1.76
+    },
+    {
+      "id": 196,
+      "x": 7.48,
+      "y": -3.73
+    },
+    {
+      "id": 197,
+      "x": 7.48,
+      "y": -0.01
+    },
+    {
+      "id": 198,
+      "x": 5.09,
+      "y": 0.98
+    }
+  ],
+  "wall": [
+    {
+      "id": 1,
+      "p1": 17,
+      "p2": 21,
+      "border": true
+    },
+    {
+      "id": 2,
+      "p1": 159,
+      "p2": 23,
+      "border": true
+    },
+    {
+      "id": 3,
+      "p1": 174,
+      "p2": 18,
+      "border": true
+    },
+    {
+      "id": 5,
+      "p1": 22,
+      "p2": 83,
+      "border": true
+    },
+    {
+      "id": 6,
+      "p1": 103,
+      "p2": 38,
+      "border": true
+    },
+    {
+      "id": 8,
+      "p1": 86,
+      "p2": 28,
+      "border": false
+    },
+    {
+      "id": 9,
+      "p1": 62,
+      "p2": 3,
+      "border": true
+    },
+    {
+      "id": 13,
+      "p1": 96,
+      "p2": 97,
+      "border": true
+    },
+    {
+      "id": 14,
+      "p1": 39,
+      "p2": 103,
+      "border": true
+    },
+    {
+      "id": 15,
+      "p1": 96,
+      "p2": 39,
+      "border": true
+    },
+    {
+      "id": 16,
+      "p1": 97,
+      "p2": 103,
+      "border": true
+    },
+    {
+      "id": 17,
+      "p1": 148,
+      "p2": 17,
+      "border": false
+    },
+    {
+      "id": 18,
+      "p1": 18,
+      "p2": 139,
+      "border": true
+    },
+    {
+      "id": 19,
+      "p1": 148,
+      "p2": 25,
+      "border": false
+    },
+    {
+      "id": 20,
+      "p1": 83,
+      "p2": 25,
+      "border": true
+    },
+    {
+      "id": 21,
+      "p1": 21,
+      "p2": 25,
+      "border": true
+    },
+    {
+      "id": 22,
+      "p1": 3,
+      "p2": 153,
+      "border": true
+    },
+    {
+      "id": 23,
+      "p1": 62,
+      "p2": 26,
+      "border": true
+    },
+    {
+      "id": 24,
+      "p1": 153,
+      "p2": 28,
+      "border": true
+    },
+    {
+      "id": 26,
+      "p1": 22,
+      "p2": 159,
+      "border": true
+    },
+    {
+      "id": 27,
+      "p1": 86,
+      "p2": 31,
+      "border": true
+    },
+    {
+      "id": 28,
+      "p1": 174,
+      "p2": 65,
+      "border": true
+    },
+    {
+      "id": 29,
+      "p1": 195,
+      "p2": 148,
+      "border": false
+    },
+    {
+      "id": 30,
+      "p1": 197,
+      "p2": 196,
+      "border": true
+    },
+    {
+      "id": 31,
+      "p1": 136,
+      "p2": 148,
+      "border": false
+    },
+    {
+      "id": 32,
+      "p1": 198,
+      "p2": 189,
+      "border": false
+    },
+    {
+      "id": 33,
+      "p1": 189,
+      "p2": 136,
+      "border": false
+    },
+    {
+      "id": 34,
+      "p1": 17,
+      "p2": 30,
+      "border": true
+    },
+    {
+      "id": 35,
+      "p1": 196,
+      "p2": 30,
+      "border": true
+    },
+    {
+      "id": 36,
+      "p1": 197,
+      "p2": 139,
+      "border": true
+    },
+    {
+      "id": 37,
+      "p1": 23,
+      "p2": 31,
+      "border": true
+    },
+    {
+      "id": 38,
+      "p1": 26,
+      "p2": 31,
+      "border": true
+    },
+    {
+      "id": 39,
+      "p1": 65,
+      "p2": 62,
+      "border": true
+    },
+    {
+      "id": 40,
+      "p1": 65,
+      "p2": 153,
+      "border": true
+    },
+    {
+      "id": 41,
+      "p1": 30,
+      "p2": 195,
+      "border": false
+    },
+    {
+      "id": 42,
+      "p1": 139,
+      "p2": 198,
+      "border": false
+    },
+    {
+      "id": 43,
+      "p1": 195,
+      "p2": 198,
+      "border": false
+    }
+  ],
+  "window": [
+    {
+      "line": 1,
+      "pos": [
+        2.88,
+        -3.73,
+        1.47,
+        -3.73
+      ],
+      "top": null,
+      "bottom": null
+    },
+    {
+      "line": 39,
+      "pos": [
+        -0.12,
+        3.8,
+        -1.22,
+        3.8
+      ],
+      "top": null,
+      "bottom": null
+    },
+    {
+      "line": 34,
+      "pos": [
+        4.78,
+        -3.73,
+        4.04,
+        -3.73
+      ],
+      "top": null,
+      "bottom": null
+    }
+  ],
+  "door": [
+    {
+      "line": 22,
+      "pos": [
+        -0.34,
+        2.18,
+        -1.12,
+        2.18
+      ],
+      "top": null,
+      "bottom": null,
+      "within": 0,
+      "show": true,
+      "ctl": [
+        -0.33999999999999997,
+        2.96
+      ],
+      "start": false
+    },
+    {
+      "line": 30,
+      "pos": [
+        7.48,
+        -3.21,
+        7.48,
+        -1.56
+      ],
+      "top": null,
+      "bottom": -1.7899999999999998,
+      "within": 0,
+      "show": true,
+      "ctl": [
+        9.13,
+        -3.21
+      ],
+      "start": true
+    }
+  ],
+  "column": [
+    {
+      "line": 3,
+      "pos": [
+        4.3,
+        4.11,
+        3.82,
+        4.11,
+        4.3,
+        3.45,
+        3.82,
+        3.45
+      ]
+    }
+  ],
+  "surplus": [],
+  "slideDoor": [
+    {
+      "line": 20,
+      "pos": [
+        -0.17,
+        -1.72,
+        -1.64,
+        -1.74
+      ],
+      "top": null,
+      "bottom": null,
+      "within": 0,
+      "show": true
+    },
+    {
+      "line": 33,
+      "pos": [
+        4.78,
+        1.67,
+        4.22,
+        1.67
+      ],
+      "top": null,
+      "bottom": null,
+      "within": 0,
+      "show": true
+    },
+    {
+      "line": 23,
+      "pos": [
+        -3.19,
+        3.8,
+        -4.69,
+        3.8
+      ],
+      "top": null,
+      "bottom": null,
+      "within": 0,
+      "show": true
+    }
+  ],
+  "groundCase": [
+    {
+      "line": 14,
+      "pos": [
+        -3.65,
+        -3.63,
+        -3.67,
+        -2.28
+      ],
+      "top": null,
+      "bottom": null
+    },
+    {
+      "line": 37,
+      "pos": [
+        -7.56,
+        -2.8,
+        -7.56,
+        -2.03
+      ],
+      "top": null,
+      "bottom": null
+    }
+  ],
+  "tagging": [
+    {
+      "pos": [
+        4.6696262315895725,
+        -0.44050951340355526
+      ],
+      "title": "客厅",
+      "content": "15m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        5.812415018356425,
+        2.710697444696963
+      ],
+      "title": "客厅",
+      "content": "",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        -1.0853396826466815,
+        -0.6167567850943294
+      ],
+      "title": "过道",
+      "content": "2m²",
+      "showTitle": false,
+      "showContent": false
+    },
+    {
+      "pos": [
+        -4.830543816484649,
+        2.4040375434941224
+      ],
+      "title": "主卧",
+      "content": "20m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        -3.1241121037851602,
+        -2.7655335830941334
+      ],
+      "title": "玄关",
+      "content": "3m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        1.8443022576840964,
+        -2.3707029347160518
+      ],
+      "title": "儿童房",
+      "content": "5m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        9.392885059239232,
+        0.044999311641024664
+      ],
+      "title": "整套",
+      "content": "",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        -5.423283359369536,
+        -1.386850300612184
+      ],
+      "title": "主卧",
+      "content": "15m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        -0.7985077758865916,
+        3.0368480835888922
+      ],
+      "title": "卫生间",
+      "content": "",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        6.7418324036108315,
+        -0.4226128168630363
+      ],
+      "title": "儿童房",
+      "content": "12m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        4.5634725658047985,
+        -2.330357448520323
+      ],
+      "title": "入房花园",
+      "content": "14m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        6.649612771811144,
+        -2.2955884450868846
+      ],
+      "title": "客餐厅",
+      "content": "12m²",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        -2.876860107524503,
+        1.4412109870555982
+      ],
+      "title": "",
+      "content": "",
+      "showTitle": true,
+      "showContent": true
+    },
+    {
+      "pos": [
+        -5.602584127967432,
+        -2.2385164405423574
+      ],
+      "title": "",
+      "content": "",
+      "showTitle": true,
+      "showContent": true
+    }
+  ],
+  "doubleDoor": [
+    {
+      "line": 3,
+      "pos": [
+        5.54,
+        4.11,
+        4.87,
+        4.11
+      ],
+      "top": null,
+      "bottom": null,
+      "within": 1,
+      "show": true
+    },
+    {
+      "line": 27,
+      "pos": [
+        -3.58,
+        0.18,
+        -4.36,
+        0.18
+      ],
+      "top": null,
+      "bottom": null,
+      "within": 0,
+      "show": true
+    },
+    {
+      "line": 3,
+      "pos": [
+        2.25,
+        4.11,
+        1.52,
+        4.11
+      ],
+      "top": null,
+      "bottom": null,
+      "within": 0,
+      "show": true
+    }
+  ],
+  "bayCase": [],
+  "furnColumn": [
+    {
+      "pos": [
+        4.1,
+        2.14,
+        4.75,
+        2.14,
+        4.75,
+        2.79,
+        4.1,
+        2.79
+      ],
+      "angle": 0
+    }
+  ],
+  "furnFlue": [
+    {
+      "pos": [
+        1.09,
+        -0.59,
+        1.74,
+        -0.59,
+        1.74,
+        0.06,
+        1.09,
+        0.06
+      ],
+      "angle": 0
+    }
+  ],
+  "dire": 90,
+  "img": {
+    "file": "images/imagest-ng3bQKf/floorplan.png",
+    "width": 2880,
+    "height": 1620,
+    "left": 509.13276578073084,
+    "top": 324.67884980988583,
+    "bottom": 318.9336501901139,
+    "right": 508.429734219269,
+    "bound": {
+      "left": -7.57,
+      "top": -4.11,
+      "bottom": 3.78,
+      "right": 7.48
+    },
+    "upload": true
+  }
+}

+ 3 - 3
static/index.html

@@ -107,8 +107,8 @@
     let args = getQueryStringArgs()
     window.test_debugger = true
     $.ajax({
-      // url: 'https://4dkk.4dage.com/data/data' + args.m + '/floor.json?m=36',
-      url: '/static/data.json',
+      url: 'https://4dkk.4dage.com/data/data' + args.m + '/floor.json?m=36',
+      // url: '/static/t-knpQzAP.json',
       method: 'GET',
       success(data) {
         let $layer = document.querySelector('#cad')
@@ -125,7 +125,7 @@
           }, layer: $layer
         });
 
-        cad.loadData(data);
+        cad.loadData(JSON.parse(data));
 
         // cad.
         setTimeout(() => cad.getData(true), 500)

+ 108 - 0
static/t-knpQzAP.json

@@ -0,0 +1,108 @@
+{
+  "floors": [
+    {
+      "id": 0,
+      "show": true,
+      "vertex-xy": [
+        {
+          "id": 0,
+          "x": 3.086,
+          "y": -4.378
+        },
+        {
+          "id": 1,
+          "x": 3.086,
+          "y": 0.24
+        },
+        {
+          "id": 2,
+          "x": 4.902,
+          "y": 0.24
+        },
+        {
+          "id": 3,
+          "x": 4.902,
+          "y": 3.755
+        },
+        {
+          "id": 4,
+          "x": -2.562,
+          "y": 3.755
+        },
+        {
+          "id": 5,
+          "x": -2.562,
+          "y": 0.24
+        },
+        {
+          "id": 6,
+          "x": -0.882,
+          "y": 0.24
+        },
+        {
+          "id": 7,
+          "x": -0.882,
+          "y": -4.378
+        }
+      ],
+      "segment": [
+        {
+          "id": 0,
+          "a": 0,
+          "b": 1,
+          "border": true,
+          "exterior": false
+        },
+        {
+          "id": 1,
+          "a": 1,
+          "b": 2,
+          "border": true,
+          "exterior": false
+        },
+        {
+          "id": 2,
+          "a": 2,
+          "b": 3,
+          "border": true,
+          "exterior": false
+        },
+        {
+          "id": 3,
+          "a": 3,
+          "b": 4,
+          "border": true,
+          "exterior": false
+        },
+        {
+          "id": 4,
+          "a": 4,
+          "b": 5,
+          "border": true,
+          "exterior": false
+        },
+        {
+          "id": 5,
+          "a": 5,
+          "b": 6,
+          "border": true,
+          "exterior": false
+        },
+        {
+          "id": 6,
+          "a": 6,
+          "b": 7,
+          "border": true,
+          "exterior": false
+        },
+        {
+          "id": 7,
+          "a": 7,
+          "b": 0,
+          "border": true,
+          "exterior": false
+        }
+      ]
+    }
+  ]
+}