Explorar o código

修改门画法 添加框选item及操作 添加下载json功能

haojianlong %!s(int64=5) %!d(string=hai) anos
pai
achega
ef2f0f51a8

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
     "name": "@saga-web/cad-engine",
-    "version": "2.0.345",
+    "version": "2.0.366",
     "description": "上格云 CAD图形引擎。",
     "main": "lib/index.js",
     "types": "lib/index.d.js",

+ 79 - 51
src/DivideFloorScene.ts

@@ -29,6 +29,7 @@ import { HighlightItem } from "./items/HighlightItem";
 import { SMathUtil } from "./utils/SMathUtil";
 import { MinDis } from "./types/MinDis";
 import { PointToLine } from "./types/PointToLine";
+import { RectSelectItem } from "./items/RectSelectItem";
 
 /**
  * 划分业务空间
@@ -53,7 +54,7 @@ export class DivideFloorScene extends FloorScene {
     /** 业务空间list   */
     zoneList: ZoneItem[] = [];
 
-    /** 业务空间是否可选  */
+    /** 业务空间是否可选    */
     _isZoneSelectable: boolean = true;
     get isZoneSelectable(): boolean {
         return this._isZoneSelectable;
@@ -65,12 +66,15 @@ export class DivideFloorScene extends FloorScene {
         this._isZoneSelectable = v;
         this.zoneList.map((t: ZoneItem) => {
             t.selectable = this._isZoneSelectable;
+            if (!t.selectable) {
+                t.selected = false;
+            }
             return t;
         });
     } // Set isZoneSelectable
 
     /** 高亮item  */
-    hightLight: HighlightItem = new HighlightItem(null);
+    highLight: HighlightItem = new HighlightItem(null);
     /** 是否开启吸附  */
     private _isAbsorbing: boolean = false;
     get isAbsorbing(): boolean {
@@ -79,6 +83,18 @@ export class DivideFloorScene extends FloorScene {
     set isAbsorbing(v: boolean) {
         this._isAbsorbing = v;
     } // Set isAbsorbing
+
+    /** 矩形选择区域  */
+    rectSelectItem: RectSelectItem | null = null;
+    /** 是否开启用户选择    */
+    _isRectSelection: boolean = false;
+    get isRectSelection(): boolean {
+        return this._isRectSelection;
+    } // Get isRectSelection
+    set isRectSelection(v: boolean) {
+        this._isRectSelection = v;
+    } // Set isRectSelection
+
     /**
      * 构造函数
      *
@@ -86,7 +102,7 @@ export class DivideFloorScene extends FloorScene {
      */
     constructor() {
         super();
-        this.addItem(this.hightLight);
+        this.addItem(this.highLight);
     } // Constructor
 
     /**
@@ -122,20 +138,35 @@ export class DivideFloorScene extends FloorScene {
      * @return  boolean
      */
     onMouseDown(event: SMouseEvent): boolean {
-        if (this.isMarking && event.buttons == 1) {
-            // 判断是否开启吸附,并且有吸附的点
-            if (this.isAbsorbing && this.hightLight.visible) {
-                event.x = this.hightLight.point.x;
-                event.y = this.hightLight.point.y;
-            }
-            if (this.sceneMark) {
-                this.sceneMark.onMouseDown(event);
+        if (event.buttons == 1) {
+            if (this.isMarking) {
+                // 判断是否开启吸附,并且有吸附的点
+                if (this.isAbsorbing && this.highLight.visible) {
+                    event.x = this.highLight.point.x;
+                    event.y = this.highLight.point.y;
+                }
+                if (this.sceneMark) {
+                    this.sceneMark.onMouseDown(event);
+                } else {
+                    let point = new SPoint(event.x, event.y);
+                    let sceneMark = new SceneMarkItem(null, point);
+                    this.addItem(sceneMark);
+                    this.sceneMark = sceneMark;
+                    this.grabItem = sceneMark;
+                }
+            } else if (this.isRectSelection) {
+                if (this.rectSelectItem) {
+                    this.isRectSelection = false;
+                    this.removeItem(this.rectSelectItem);
+                    this.rectSelectItem = null;
+                } else {
+                    let point = new SPoint(event.x, event.y);
+                    let rect = new RectSelectItem(null, point);
+                    this.addItem(rect);
+                    this.rectSelectItem = rect;
+                }
             } else {
-                let point = new SPoint(event.x, event.y);
-                let sceneMark = new SceneMarkItem(null, point);
-                this.addItem(sceneMark);
-                this.sceneMark = sceneMark;
-                this.grabItem = sceneMark;
+                super.onMouseDown(event);
             }
         } else {
             super.onMouseDown(event);
@@ -150,9 +181,32 @@ export class DivideFloorScene extends FloorScene {
      * @return  boolean
      */
     onMouseUp(event: SMouseEvent): boolean {
+        if (this.rectSelectItem) {
+            this.isRectSelection = false;
+            this.removeItem(this.rectSelectItem);
+            this.rectSelectItem = null;
+        }
         return false;
     } // Function onMouseUp()
 
+    /**
+     *  吸附空间
+     *
+     *  @param  event   鼠标事件对象
+     */
+    onMouseMove(event: SMouseEvent): boolean {
+        if (this.rectSelectItem) {
+            this.rectSelectItem.onMouseMove(event);
+            return false;
+        }
+        super.onMouseMove(event);
+        this.highLight.visible = false;
+        if (this.isAbsorbing) {
+            this.absorbSpace(event);
+        }
+        return false;
+    } // Function onMouseMove
+
     /***
      * 键盘按下事件
      *
@@ -229,34 +283,6 @@ export class DivideFloorScene extends FloorScene {
     } // Function clearZoneSelection
 
     /**
-     *  切换业务空间
-     *
-     *  @param  zoneitem    需要隐藏的业务空间
-     */
-    changeSelectZone(zoneitem: ZoneItem): void {
-        this.zoneList.map(zone => {
-            zone.selected = false;
-            zone.unselectFlag = true;
-            return zone;
-        });
-        zoneitem.visible = false;
-    } // Function changeSelectZone
-
-    /**
-     *  吸附空间
-     *
-     *  @param  event   鼠标事件对象
-     */
-    onMouseMove(event: SMouseEvent): boolean {
-        super.onMouseMove(event);
-        this.hightLight.visible = false;
-        if (this.isAbsorbing) {
-            this.absorbSpace(event);
-        }
-        return false;
-    } // Function onMouseMove
-
-    /**
      *  吸附空间
      *
      *  @param  event   鼠标事件对象
@@ -268,16 +294,16 @@ export class DivideFloorScene extends FloorScene {
         }
         let P = this.absorbPoint(event, absorbLen);
         if (P.Point) {
-            this.hightLight.distance = P.MinDis;
-            this.hightLight.point = new SPoint(P.Point.X, -P.Point.Y);
-            this.hightLight.visible = true;
+            this.highLight.distance = P.MinDis;
+            this.highLight.point = new SPoint(P.Point.X, -P.Point.Y);
+            this.highLight.visible = true;
         } else {
             let L = this.absorbLine(event, absorbLen);
             if (L.Line && L.Point) {
-                this.hightLight.distance = L.MinDis;
-                this.hightLight.point = L.Point;
-                this.hightLight.line = L.Line;
-                this.hightLight.visible = true;
+                this.highLight.distance = L.MinDis;
+                this.highLight.point = L.Point;
+                this.highLight.line = L.Line;
+                this.highLight.visible = true;
             }
         }
     } // Function absorbSpace
@@ -394,4 +420,6 @@ export class DivideFloorScene extends FloorScene {
         };
         return minPointLine;
     } // Function absorbLine
+
+    /** */
 } // Class DivideFloorScene

+ 4 - 0
src/FloorScene.ts

@@ -45,6 +45,8 @@ import { SPoint } from "@saga-web/draw/lib";
 export class FloorScene extends SGraphyScene {
     /** item数据  */
     data: FloorData | null = null;
+    /** json数据  */
+    json: string | null = null;
     /** 是否显示空间  */
     private _isShowSpace: boolean = true;
     get isShowSpace(): boolean {
@@ -227,6 +229,7 @@ export class FloorScene extends SGraphyScene {
                     that.data = unGzipData.entityList
                         ? unGzipData.entityList[0].Elements
                         : unGzipData.EntityList[0].Elements;
+                    this.json = JSON.stringify(unGzipData);
                     resolve(that.data);
                 } catch (e) {
                     console.log(e);
@@ -252,6 +255,7 @@ export class FloorScene extends SGraphyScene {
             })
                 .then((res: any) => {
                     if (res.data.Result == "success") {
+                        this.json = JSON.stringify(res);
                         let floordata = res.data.EntityList[0].Elements;
                         that.data = floordata;
                         that.addBaseMapItem(floordata);

+ 14 - 1
src/FloorView.ts

@@ -19,7 +19,7 @@
  */
 
 import { SGraphyView } from "@saga-web/graphy/lib";
-import { SMouseButton, SMouseEvent } from "@saga-web/base/lib";
+import { SMouseButton, SMouseEvent, SNetUtil } from "@saga-web/base/lib";
 import { SPoint } from "@saga-web/draw/lib";
 
 /**
@@ -34,6 +34,19 @@ export class FloorView extends SGraphyView {
     private spaceKey: boolean = false;
 
     /**
+     * 保存底图json
+     *
+     * @param   name    文件名
+     */
+    saveFloorJson(name: string): void {
+        // @ts-ignore
+        if (!this.scene || !this.scene.json) return;
+        // @ts-ignore
+        let url = URL.createObjectURL(new Blob([this.scene.json]));
+        SNetUtil.downLoad(name, url);
+    } // Function saveSceneSvg()
+
+    /**
      * 按键按下事件
      *
      * @param   event       事件参数

+ 29 - 46
src/items/DoorItem.ts

@@ -21,7 +21,7 @@
 import { Door } from "../types/Door";
 import { Opt } from "../types/Opt";
 import { SGraphyItem } from "@saga-web/graphy/lib";
-import { SPainter, SPoint, SRect } from "@saga-web/draw/lib";
+import { SColor, SPainter, SPoint, SRect } from "@saga-web/draw/lib";
 import { SMathUtil } from "../utils/SMathUtil";
 import { ItemOrder } from "../types/ItemOrder";
 
@@ -59,49 +59,32 @@ export class DoorItem extends SGraphyItem {
                 return new SPoint(t.X, -t.Y);
             });
 
-            let p1, p2;
-            if (this.pointArr[0].x < this.pointArr[1].x) {
-                p1 = this.pointArr[0];
+            let p1 = this.pointArr[0],
                 p2 = this.pointArr[1];
-            } else if (this.pointArr[0].x == this.pointArr[1].x) {
-                if (this.pointArr[0].y <= this.pointArr[1].y) {
-                    p1 = this.pointArr[0];
-                    p2 = this.pointArr[1];
-                } else {
-                    p1 = this.pointArr[1];
-                    p2 = this.pointArr[0];
-                }
-            } else {
-                p1 = this.pointArr[1];
-                p2 = this.pointArr[0];
+            // 旋转点
+            this.p = p1;
+            // 向量点乘 => x1 * x2 + y1 * y2,大于0同向
+            let dotProduct =
+                (p2.x - p1.x) * this.data.HandDirection.X +
+                (p2.y - p1.y) * -this.data.HandDirection.Y;
+            if (dotProduct > 0) {
+                this.p = p2;
+                p2 = p1;
+                p1 = this.p;
             }
-
-            let fo = Math.atan(
-                -this.data.FaceDirection.Y / this.data.FaceDirection.X
-            );
             // 两点间距离
             this.r = SMathUtil.pointDistance(p1.x, p1.y, p2.x, p2.y);
             // 门朝向角度
+            let fo = Math.atan(
+                -this.data.FaceDirection.Y / this.data.FaceDirection.X
+            );
             this.ang = this.data.FaceDirection.X > 0 ? fo : fo + Math.PI;
-            // 旋转点
-            this.p = p1;
-            if (
-                Math.abs(this.data.HandDirection.X) >
-                Math.abs(this.data.HandDirection.Y)
-            ) {
-                if (this.data.HandDirection.X > 0) {
-                    this.p = p2;
-                    if (this.data.FaceDirection.X > 0) {
-                        this.startAng = 0;
-                    }
-                }
-            } else {
-                if (this.data.HandDirection.Y > 0) {
-                    this.p = p2;
-                    if (this.data.FaceDirection.X > 0) {
-                        this.startAng = 0;
-                    }
-                }
+            // 向量叉乘 => x1 * y2 - x2 * y1,小于0是顺时针
+            let direction =
+                (p2.x - p1.x) * -this.data.FaceDirection.Y -
+                (p2.y - p1.y) * this.data.FaceDirection.X;
+            if (direction > 0) {
+                this.startAng = 0;
             }
         }
     } // Constructor
@@ -118,13 +101,13 @@ export class DoorItem extends SGraphyItem {
         painter.pen.color = Opt.doorColor;
         painter.drawLine(0, 0, this.r, 0);
         painter.pen.lineDash = [50, 100];
-        // painter.drawArc(
-        //     -this.r,
-        //     -this.r,
-        //     this.r * 2,
-        //     this.r * 2,
-        //     this.startAng,
-        //     this.startAng + Math.PI / 2
-        // );
+        painter.drawArc(
+            -this.r,
+            -this.r,
+            this.r * 2,
+            this.r * 2,
+            this.startAng,
+            this.startAng + Math.PI / 2
+        );
     } // Function onDraw()
 } // Class DoorItem

+ 0 - 1
src/items/MarkItem.ts

@@ -93,7 +93,6 @@ export class MarkerItem extends SGraphyItem {
      * Item绘制操作
      *
      * @param   painter       painter对象
-     * @param   rect          绘制区域
      */
     onDraw(painter: SPainter): void {
         painter.drawImage(this.Img, -14, -33, this.width, this.height);

+ 74 - 0
src/items/RectSelectItem.ts

@@ -0,0 +1,74 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                      :*$@@%$*:                         ;:                ;;    ;;
+ *                    :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                   :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                   =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                   =@*                                  %!              @ $= % %@=   =%@!      %=
+ *              *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *            %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *          ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *          $@*   ;@@@%=!:                *@*
+ *          =@$    ;;;!=%@@@@=!           =@!
+ *           %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *            ;%@@$=$@@%*       *@@@$=%@@%;
+ *               ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+import { SGraphyItem } from "@saga-web/graphy/lib";
+import { SPainter, SPoint } from "@saga-web/draw/lib";
+import { SMouseEvent } from "@saga-web/base/lib";
+import { ItemOrder } from "../types/ItemOrder";
+import { Opt } from "../types/Opt";
+
+/**
+ * 矩形选择item
+ *
+ * @author  郝建龙
+ */
+export class RectSelectItem extends SGraphyItem {
+    /** 起点  */
+    startPoint: SPoint = new SPoint();
+    /** 终点  */
+    endPoint: SPoint = new SPoint();
+
+    /**
+     * 构造函数
+     *
+     * @param parent    指向父对象
+     * @param point     起点数据
+     */
+    constructor(parent: SGraphyItem | null, point: SPoint) {
+        super(parent);
+        this.startPoint = point;
+        this.endPoint = new SPoint(point.x, point.y);
+        this.zOrder = ItemOrder.rectSelectOrder;
+    } // Constructor
+
+    /**
+     * 鼠标移动事件
+     *
+     * @param	event         事件参数
+     * @return	boolean
+     */
+    onMouseMove(event: SMouseEvent): boolean {
+        this.endPoint.x = event.x;
+        this.endPoint.y = event.y;
+        return true;
+    } // Function onMouseMove()
+
+    /**
+     * Item绘制操作
+     *
+     * @param   painter       painter对象
+     */
+    onDraw(painter: SPainter): void {
+        painter.pen.lineWidth = painter.toPx(2);
+        painter.pen.color = Opt.rectSelectOutColor;
+        painter.brush.color = Opt.rectSelectInColor;
+        painter.drawRect(this.startPoint, this.endPoint);
+    } // Function onDraw()
+} // RectSelectItem

+ 1 - 1
src/items/WallItem.ts

@@ -22,7 +22,7 @@ import { SGraphyItem } from "@saga-web/graphy/lib";
 import { SPainter, SPoint, SRect } from "@saga-web/draw/lib";
 import { Wall } from "../types/Wall";
 import { Opt } from "../types/Opt";
-import {ItemOrder} from "../types/ItemOrder";
+import { ItemOrder } from "../types/ItemOrder";
 
 /**
  * 墙item

+ 2 - 4
src/items/ZoneItem.ts

@@ -39,8 +39,6 @@ import { ItemOrder } from "../types/ItemOrder";
 export class ZoneItem extends SGraphyItem {
     /** 空间所有数据  */
     data: Zone;
-    /** 不可选标志  */
-    unselectFlag = false;
     /** 空间轮廓线坐标list  */
     private readonly pointArr: SPoint[][][] = [];
     /** X坐标最小值  */
@@ -131,7 +129,7 @@ export class ZoneItem extends SGraphyItem {
      * @return  boolean
      */
     onClick(event: SMouseEvent): boolean {
-        if (!this.unselectFlag && this.selectable) {
+        if (this.selectable) {
             this.selected = !this.selected;
             this.clickPoint = new SPoint(event.x, event.y);
             this.$emit("click", event);
@@ -178,7 +176,7 @@ export class ZoneItem extends SGraphyItem {
      */
     onDraw(painter: SPainter, rect?: SRect): void {
         painter.pen.color = SColor.Transparent;
-        if (this.unselectFlag) {
+        if (!this.selectable) {
             painter.brush.color = this.unselectColor;
         } else {
             painter.brush.color = this.selected

+ 3 - 1
src/types/ItemOrder.ts

@@ -40,8 +40,10 @@ export class ItemOrder {
     static windowOrder = 8;
     /** 位置标签对象层级 */
     static markOrder = 99;
+    /** 框选矩形对象层级 */
+    static rectSelectOrder = 999;
     /** 高亮对象层级 */
-    static highLightOrder = 999;
+    static highLightOrder = 9999;
     /** 蒙版层级 */
     static sceneMarkOrder = Number.MAX_SAFE_INTEGER;
 } // Interface ItemOrder

+ 4 - 0
src/types/Opt.ts

@@ -44,4 +44,8 @@ export class Opt {
     static highLightPointColor = new SColor("#ff8d00");
     /** 高亮item吸附线颜色    */
     static highLightLineColor = new SColor("#409EFF");
+    /** 矩形选择对象边框颜色    */
+    static rectSelectOutColor = new SColor("#3e78f9e8");
+    /** 矩形选择对象填充颜色    */
+    static rectSelectInColor = new SColor("#8cf2fd73");
 } // Interface Opt

+ 20 - 2
src/utils/SMathUtil.ts

@@ -18,7 +18,7 @@
  * ********************************************************************************************************************
  */
 
-import { SLine, SPoint } from "@saga-web/draw/lib";
+import { SLine, SPoint, SRect } from "@saga-web/draw/lib";
 import { MinDis } from "../types/MinDis";
 import { Point } from "../types/Point";
 import { PointToLine } from "../types/PointToLine";
@@ -146,4 +146,22 @@ export class SMathUtil {
         }
         return PTL;
     } // Function getMinDisPoint()
-}
+
+    /**
+     * 计算矩形是否有交集(外包矩形算法)
+     *
+     * @param   rect1   矩形1
+     * @param   rect2   矩形2
+     * @return  boolean
+     * */
+    static rectIntersection(rect1: SRect, rect2: SRect): boolean {
+        let minX = rect1.x < rect2.x ? rect1.x : rect2.x;
+        let minY = rect1.y < rect2.y ? rect1.y : rect2.y;
+        let maxX = rect1.right > rect2.right ? rect1.right : rect2.right;
+        let maxY = rect1.bottom > rect2.bottom ? rect2.bottom : rect2.bottom;
+        return (
+            rect1.width + rect2.width > maxX - minX &&
+            rect1.height + rect2.height > maxY - minY
+        );
+    } // Function rectIntersection()
+} // Class SMathUtil