Explorar el Código

增加CAD跟3维互动

zhibin hace 6 años
padre
commit
9b13601d03
Se han modificado 3 ficheros con 261 adiciones y 79 borrados
  1. 22 6
      index.html
  2. 196 72
      js/CAD.js
  3. 43 1
      model/data.js

+ 22 - 6
index.html

@@ -11,19 +11,35 @@
       padding: 0;
       border: 0;
     }
-
-  canvas {
-    width: 800px;
-    height: 800px;
-  }
+    html, body {
+      width: 100%;
+      height: 100%;
+      overflow: hidden;
+    }
+    #myCanvas {
+      position: absolute;
+      left: 100px;
+      top: 100px;
+      width: 400px;
+      height: 400px;
+    }
   </style>
 </head>
 <body>
-  <canvas id="myCanvas" width="800" height="800">
+  <canvas id="myCanvas" width="700" height="700" >
     Your browser does not support the HTML5 canvas tag.
   </canvas>
 
   <script src="js/CAD.js"></script>
   <script src="model/data.js"></script>
+  <script>
+    var $canvas = document.getElementById("myCanvas")
+    // $canvas.setAttribute('width', window.innerWidth)
+    // $canvas.setAttribute('height', window.innerHeight)
+    // $canvas.style.width = window.innerWidth + 'px'
+    // $canvas.style.height = window.innerHeight + 'px'
+
+    var wall = grendCAD($canvas, wallData, wallCamera)
+  </script>
 </body>
 </html>

+ 196 - 72
js/CAD.js

@@ -1,10 +1,14 @@
 var grendCAD = (function grentWall() {
   var util = {
+    isInfinity(num) {
+      return num === Infinity || num === -Infinity
+    },
+
     /**
      * 获取一组坐标的XY坐标区间
      * @param {*} points 
      */
-    getSection (points) {
+    getSection(points) {
       var ret = {
         minx: points[0].x,
         maxx: points[0].x,
@@ -34,7 +38,12 @@ var grendCAD = (function grentWall() {
      * 计算垂直向量
      * @param {向量} arr
      */
-    verticalLine (arr) {
+    verticalLine(line) {
+      var arr = [
+        line.points[1].x - line.points[0].x,
+        line.points[1].y - line.points[0].y
+      ]
+
       if (arr.length !== 0) {
         var x, y;
 
@@ -51,7 +60,7 @@ var grendCAD = (function grentWall() {
      * @param {*} section 指定范围
      * @returns Array 转化后的值
      */
-    tranProp (points, section) {
+    tranProp(points, section) {
       var args = util.getSection(points)
       var xlen = args.maxx - args.minx
       var ylen = args.maxy - args.miny
@@ -75,7 +84,7 @@ var grendCAD = (function grentWall() {
      * @param {*} point 
      * @param {*} section 
      */
-    tranPoint (point, section) {
+    tranPoint(point, section) {
       return {
         x: point.x + section.minx,
         y: point.y + section.miny
@@ -88,7 +97,7 @@ var grendCAD = (function grentWall() {
      * @param {*} line 线段
      * @param {*} width 线宽
      */
-    isContainPoint (point, line, width) {
+    isContainPoint(point, line, width) {
       var dis = 0
       var s1 = line[1].x - line[0].x
       var s2 = point.x - line[0].x
@@ -113,7 +122,7 @@ var grendCAD = (function grentWall() {
         var py = line[0].y + k1 * r;
         dis = Math.sqrt((point.x - px) * (point.x - px) + (py - point.y) * (py - point.y));
       }
-      
+
       return dis >= min && dis <= max
     },
 
@@ -122,7 +131,7 @@ var grendCAD = (function grentWall() {
      * @param {*} line1 
      * @param {*} line2 
      */
-    isLineIntersect (line1, line2) {
+    isLineIntersect(line1, line2) {
       var a1 = line1[1].y - line1[0].y;
       var b1 = line1[0].x - line1[1].x;
       var c1 = a1 * line1[0].x + b1 * line1[0].y;
@@ -165,7 +174,7 @@ var grendCAD = (function grentWall() {
      * @param {*} point1 
      * @param {*} poin2 
      */
-    equalPoint (point1, poin2) {
+    equalPoint(point1, poin2) {
       return point1.x === poin2.x && point1.y === poin2.y
     },
 
@@ -184,7 +193,7 @@ var grendCAD = (function grentWall() {
           var line2 = [face2[j], face2[next]]
           var isIntersect1 = util.isLineIntersect(line2, line1)
           var isIntersect2 = util.isLineIntersect(line1, line2)
-          
+
           if (isIntersect1 && isIntersect2) {
             return true
           }
@@ -200,16 +209,16 @@ var grendCAD = (function grentWall() {
     pointInside(point, face) {
       var inside = false;
       var x = point.x,
-          y = point.y;
+        y = point.y;
 
       for (var i = 0, j = face.length - 1; i < face.length; j = i++) {
         var xi = face[i].x,
-            yi = face[i].y;
+          yi = face[i].y;
         var xj = face[j].x,
-            yj = face[j].y;
+          yj = face[j].y;
 
-        if(((yi > y) != (yj > y)) &&
-           (x < (xj - xi) * (y - yi) / (yj - yi) + xi)) {
+        if (((yi > y) != (yj > y)) &&
+          (x < (xj - xi) * (y - yi) / (yj - yi) + xi)) {
           inside = !inside;
         }
       }
@@ -218,7 +227,7 @@ var grendCAD = (function grentWall() {
   }
 
   var drawShape = {
-    line (context, line, width) {
+    line(context, line, width) {
       context.strokeStyle = 'red';
       context.lineWidth = width;
       context.beginPath();
@@ -227,7 +236,7 @@ var grendCAD = (function grentWall() {
       context.closePath();
       context.stroke();
     },
-    camera (context, point, width) {
+    camera(context, point, width) {
       context.fillStyle = "#00cc00";
       context.fillRect(point.x - width / 2, point.y - width / 2, width, width);
     }
@@ -248,8 +257,8 @@ var grendCAD = (function grentWall() {
         return item.id === iteration.linkedLineID[1]
       })
     } while (start !== iteration)
-    
-   
+
+
     return ret
   }
 
@@ -261,7 +270,8 @@ var grendCAD = (function grentWall() {
       x: 0,
       y: 0
     }
-    while (dom === parent || dom === document.documentElement) {
+    while (dom && dom !== parent && dom !== document.documentElement) {
+      console.log(dom)
       ret.x += dom.offsetLeft
       ret.y += dom.offsetTop
       dom = dom.offsetParent
@@ -270,49 +280,71 @@ var grendCAD = (function grentWall() {
     return ret
   }
 
-  function addMouseEvent (dom, event) {
+  function addMouseEvent(dom, event) {
     dom.addEventListener('mousedown', function downHandle(ev) {
-      var prevPoint = {x: ev.offsetX, y: ev.offsetY}
+      var prevPoint = {
+        x: ev.pageX,
+        y: ev.pageY
+      }
       var con = event.down(prevPoint)
       if (!con) return;
 
-      document.documentElement.addEventListener('mousemove', moveHandle, {passive: false})
-      document.documentElement.addEventListener('mouseup', endHandle, {passive: false})
+      document.documentElement.addEventListener('mousemove', moveHandle, {
+        passive: false
+      })
+      document.documentElement.addEventListener('mouseup', endHandle, {
+        passive: false
+      })
 
-      function moveHandle (ev) {
-        event.move({x: ev.offsetX, y: ev.offsetY}, prevPoint)
-        prevPoint = { x: ev.offsetX, y: ev.offsetY }
+      function moveHandle(ev) {
+        event.move({
+          x: ev.pageX,
+          y: ev.pageY
+        }, prevPoint)
+        prevPoint = {
+          x: ev.pageX,
+          y: ev.pageY
+        }
       }
 
-      function endHandle (ev) {
-        document.documentElement.removeEventListener('mousemove', moveHandle, {passive: false})
-        document.documentElement.removeEventListener('mouseup', endHandle, {passive: false})
+      function endHandle(ev) {
+        document.documentElement.removeEventListener('mousemove', moveHandle, {
+          passive: false
+        })
+        document.documentElement.removeEventListener('mouseup', endHandle, {
+          passive: false
+        })
         event.up()
       }
     }, false)
   }
 
+
   function Wall(canvas, data, cameras, cal) {
-    this.width = canvas.width
-    this.height = canvas.height
     this.canvas = canvas
     this.context = canvas.getContext('2d')
     this.origin = data
-    this.context.translate(this.width / 2, this.height / 2);
-    this.screenOffset = getPosition(this.canvas)
     this.lineWidth = 2
     this.cameras = cameras
     this.cal = cal
+    this.stateStack = []
     this.init()
     this.draw()
   }
 
 
   Wall.prototype.init = function () {
+    this.width = this.canvas.width
+    this.height = this.canvas.height
+    this.wMultiple = this.canvas.width / this.canvas.offsetWidth
+    this.hMultiple = this.canvas.height / this.canvas.offsetHeight
+    this.context.translate(this.width / 2, this.height / 2);
+    this.screenOffset = getPosition(this.canvas)
+    
     var points = []
     var faces = {}
 
-    this.origin.forEach(function(line) {
+    this.origin.forEach(function (line) {
       if (faces[line.roomIndex]) {
         faces[line.roomIndex].push(line)
       } else {
@@ -333,7 +365,10 @@ var grendCAD = (function grentWall() {
   }
 
   Wall.prototype.transScreenPoint = function (point) {
-    var spoint = {x: point.x, y: point.y}
+    var spoint = {
+      x: point.x,
+      y: point.y
+    }
     spoint.x += this.status.offset.x
     spoint.y += this.status.offset.y
 
@@ -346,7 +381,7 @@ var grendCAD = (function grentWall() {
   Wall.prototype.transRealPoint = function (point) {
     return {
       x: (point.x * this.status.prop) / (this.status.range * this.width / 2) - this.status.offset.x,
-      y: (point.y * this.status.prop) / (this.status.range * this.width / 2) - this.status.offset.y
+      y: (point.y * this.status.prop) / (this.status.range * this.height / 2) - this.status.offset.y
     }
   }
 
@@ -362,14 +397,20 @@ var grendCAD = (function grentWall() {
     var dirct = null
 
     var event = {
-      down (offset) {
+      down(offset) {
+        console.log(offset, this.screenOffset)
+        offset.x = (offset.x - this.screenOffset.x) * this.wMultiple
+        offset.y = (offset.y - this.screenOffset.y) * this.hMultiple
         startPoint = this.transRealPoint(util.tranPoint(offset, section))
         sinfo = this._down(startPoint)
         prevPoint = startPoint
 
         return !!sinfo
       },
-      move (move) {
+      move(move) {
+        console.log(move)
+        move.x = (move.x - this.screenOffset.x) * this.wMultiple
+        move.y = (move.y - this.screenOffset.y) * this.hMultiple
         var point = this.transRealPoint(util.tranPoint(move, section))
 
         if (!dirct) {
@@ -378,7 +419,7 @@ var grendCAD = (function grentWall() {
         this._move(point, prevPoint, sinfo, dirct)
         prevPoint = point
       },
-      up () {
+      up() {
         dirct = null
         startPoint = null
       }
@@ -392,19 +433,16 @@ var grendCAD = (function grentWall() {
   }
 
   Wall.prototype._down = function (point) {
-    console.log(point)
+    this.preservationState()
     for (var key in this.faces) {
       var face = this.faces[key]
 
       for (var i = 0, line; line = face[i]; i++) {
-        if (util.isContainPoint(point, line.points, 10 / this.status.prop)) {
+        if (util.isContainPoint(point, line.points, (this.lineWidth + 4) / this.status.prop)) {
           return {
             face: face,
             line: line,
-            dire: util.verticalLine([
-              line.points[1].x - line.points[0].x,
-              line.points[1].y - line.points[0].y,
-            ])
+            dire: util.verticalLine(line)
           }
         }
       }
@@ -412,6 +450,8 @@ var grendCAD = (function grentWall() {
   }
 
   Wall.prototype.updateLine = function (line, x, y) {
+    if (!x && !y) return;
+
     var face
     for (var key in this.faces) {
       var index = this.faces[key].findIndex(function (item) {
@@ -423,33 +463,59 @@ var grendCAD = (function grentWall() {
         break
       }
     }
-    
+
     if (!face) return
-    
-    var leftPoint = face.find(function (item) {
-      return item.id === line.linkedLineID[0]
+
+    var prevLine = face.find(function (cLine) {
+      return line.linkedLineID[0] === cLine.id
     })
-    var rightPoint = face.find(function (item) {
-      return item.id === line.linkedLineID[1]
+    var lastLine = face.find(function (cLine) {
+      return line.linkedLineID[1] === cLine.id
     })
+    var prevK = (prevLine.points[1].y - prevLine.points[0].y) / (prevLine.points[1].x - prevLine.points[0].x)
+    var lastK = (lastLine.points[1].y - lastLine.points[0].y) / (lastLine.points[1].x - lastLine.points[0].x)
+    var prevX, prevY, lastX, lastY
+
+    if (x) {
+      prevX = prevLine.points[1].x + x
+      prevY = (prevX - prevLine.points[0].x) * prevK + prevLine.points[0].y
+      lastX = lastLine.points[0].x + x
+      lastY = (lastX - lastLine.points[0].x) * lastK + lastLine.points[0].y
+    } else {
+      prevY = prevLine.points[1].y + y
+      prevX = (prevY - prevLine.points[0].y) / prevK + prevLine.points[0].x
+      lastY = lastLine.points[0].y + y
+      lastX = (lastY - lastLine.points[0].y) / lastK + lastLine.points[0].x
+    }
 
-    line.points[0].x += x
-    line.points[0].y += y
-    line.points[1].x += x
-    line.points[1].y += y
-    leftPoint.points[1].x = line.points[0].x
-    leftPoint.points[1].y = line.points[0].y
-    rightPoint.points[0].x = line.points[1].x
-    rightPoint.points[0].y = line.points[1].y
+    if (util.isInfinity(prevX) ||
+      util.isInfinity(prevY) ||
+      util.isInfinity(lastX) ||
+      util.isInfinity(lastY)) {
+      console.log('???')
+      prevX = prevLine.points[1].x + x
+      prevY = prevLine.points[1].y + y
+      lastX = lastLine.points[0].x + x
+      lastY = lastLine.points[0].y + y
+    }
 
+    prevLine.points[1].x = prevX
+    prevLine.points[1].y = prevY
+    lastLine.points[0].x = lastX
+    lastLine.points[0].y = lastY
+    line.points[0].x = prevLine.points[1].x
+    line.points[0].y = prevLine.points[1].y
+    line.points[1].x = lastLine.points[0].x
+    line.points[1].y = lastLine.points[0].y
   }
 
+
   Wall.prototype._move = function (point, prevPoint, movePosition, dirct) {
     var xdis = point.x - prevPoint.x
     var ydis = point.y - prevPoint.y
     var revoke = false
 
-  
+
     if (dirct === 'X') {
       this.updateLine(movePosition.line, xdis, 0)
     } else {
@@ -458,7 +524,7 @@ var grendCAD = (function grentWall() {
 
     var activeFacePoint = getFacePoints(movePosition.face)
     for (let key in this.faces) {
-      if (this.faces[key] !== movePosition.face && 
+      if (this.faces[key] !== movePosition.face &&
         util.isFaceIntersect(activeFacePoint, getFacePoints(this.faces[key]))) {
         revoke = true;
         break;
@@ -474,7 +540,7 @@ var grendCAD = (function grentWall() {
         }
       }
     }
-    
+
 
     if (revoke) {
       if (dirct === 'X') {
@@ -484,8 +550,8 @@ var grendCAD = (function grentWall() {
       }
     } else {
       this.cal && this.cal.changePoint && this.cal.changePoint(movePosition.line)
+      this.draw()
     }
-    this.draw()
   }
 
   Wall.prototype.draw = function () {
@@ -495,7 +561,7 @@ var grendCAD = (function grentWall() {
       var face = this.faces[key]
       for (var i = 0, line; line = face[i]; i++) {
         drawShape.line(
-          this.context, 
+          this.context,
           [
             this.transScreenPoint(line.points[0]),
             this.transScreenPoint(line.points[1])
@@ -514,13 +580,53 @@ var grendCAD = (function grentWall() {
     }
   }
 
+  Wall.prototype.preservationState = function () {
+    var state = {}
+    for (var key in this.faces) {
+      state[key] = {}
+      for (var i = 0; i < this.faces[key].length; i++) {
+        var line = this.faces[key][i]
+        state[key][line.id] = [
+          {x: line.points[0].x, y: line.points[0].y},
+          {x: line.points[1].x, y: line.points[1].y}
+        ]
+      }
+    }
+    this.stateStack.push(state)
+  }
+
+  Wall.prototype.revokeState = function () {
+    var state = this.stateStack.pop()
+
+    for (var key in state) {
+      for (var id in state[key]) {
+        var cline = state[key][id]
+        var line = this.faces[key].find(function (line) {
+          return line.id === id
+        })
+        line.points[0].x = cline[0].x
+        line.points[0].y = cline[0].y
+        line.points[1].x = cline[1].x
+        line.points[1].y = cline[1].y
+      }
+    }
+
+    this.draw();
+  }
 
-  
   return function (dom, line2Ds, cameras) {
-    window. wall = new Wall(dom, line2Ds, cameras, {
-      changePoint: function(line2D) {
+    function getLine(id) {
+      return line2Ds.find(function (line) {
+        return line.id === id
+      })
+    }
+
+    let wall = new Wall(dom, line2Ds, cameras, {
+      changePoint: function (line2D) {
         if (line2D.updateLine3D) {
           line2D.updateLine3D()
+          getLine(line2D.linkedLineID[0]).updateLine3D()
+          getLine(line2D.linkedLineID[1]).updateLine3D()
         } else {
           console.error('当前线条没有注册3D线条方法')
         }
@@ -528,11 +634,29 @@ var grendCAD = (function grentWall() {
     });
 
     line2Ds.forEach(function (line2D) {
-      let fn = line2D.draw
-      line2D.draw = function () {
-        wall.draw()
-        fn && fn.bind(this)();
+      var update = line2D.update
+      line2D.update = function (dirs, len) {
+        var args = [{
+            x: 0,
+            y: 0
+          },
+          {
+            x: 0,
+            y: 0
+          },
+          {
+            line: this,
+            face: wall.faces[this.roomIndex]
+          }
+        ]
+
+        args[0][dirs[0]] = len;
+
+        wall._move.apply(wall, args.concat([dirs[1]]))
+        update && update.bind(this)()
       }
     })
+
+    return wall;
   }
-})();
+})();

+ 43 - 1
model/data.js

@@ -370,5 +370,47 @@ var wallCamera = {
 }
 
 
+var floorJson = {
+  "vertex": [
+    { "x": -1.198, "y": 4.705 }
+    , { "x": 8.877, "y": 6.05 }
+    , { "x": 9.877, "y": -5.295 }
+    , { "x": -1.198, "y": -5.295 }
+    , { "x": -1.198, "y": -4.745 }
+    , { "x": -9.973, "y": -4.745 }
+    , { "x": -9.973, "y": 5.305 }
+    , { "x": -1.198, "y": 5.305 }
+  ], "wall": [
+    { "p1": 0, "p2": 1, "room": 1 }
+    , { "p1": 1, "p2": 2, "room": 1 }
+    , { "p1": 2, "p2": 3, "room": 1 }
+    , { "p1": 4, "p2": 5, "room": 2 }
+    , { "p1": 5, "p2": 6, "room": 2 }
+    , { "p1": 6, "p2": 7, "room": 2 }
+    //,	{"p1":3,"p2":7}
+    , { "p1": 3, "p2": 0, "room": 1 }
+    , { "p1": 7, "p2": 4, "room": 2 }
+  ]
+}
+
+var test = floorJson.wall.map((item, index) => {
+  return {
+    "id": item.room + "_" + index,
+    "roomIndex": item.room,
+    "points": [floorJson.vertex[item.p1], floorJson.vertex[item.p2]],
+    "linkedLineID": ["0_6", "0_1"]
+  }
+})
+
+test.forEach(item => {
+  var prev = test.find(item1 => {
+    return item.points[0] === item1.points[1]
+  })
+  var last = test.find(item1 => {
+    return item.points[1] === item1.points[0]
+  })
+  item.linkedLineID = [prev.id, last.id]
+})
 
-grendCAD(document.getElementById("myCanvas"), wallData, wallCamera)
+// wallData = test
+// wallCamera = {}