/* * ******************************************************************************************************************** * * :*$@@%$*: ;: ;; ;; * :@@%! :!@@%: %! ;%%@@%$ =@@@@@@@%; @%@@@%%%%@@@@@ * :@%; :$= %%$$$%$$ ;$$ ;$@= !@$ * =@! %! @ $=;% !@@@%: !$$$$$$$$$$$$$$= * =@* %! @ $= % %@= =%@! %= * *$%%! @@= ;=$%%%$*: %! @ $= % =%%%%%%@$ *%: =% * %@@!: !@@@%=$@@@@%! :*@@$: %! @ $= % $* ;@ @* :%* * ;@@! ;!!!;: ;@%: =======@%========* @ $$ % $%*****$@ :@$=*********=@$ * $@* ;@@@%=!: *@* * =@$ ;;;!=%@@@@=! =@! * %@$: =@%: :*@@@* %@= Copyright (c) 2016-2019. 北京上格云技术有限公司 * ;%@@$=$@@%* *@@@$=%@@%; * ::;:: ::;:: All rights reserved. * * ******************************************************************************************************************** */ import { FloorScene } from "./FloorScene"; import { SPoint, SRect } from "@saga-web/draw/lib"; import { SceneMarkItem } from "./items/SceneMarkItem"; import { ZoneItem } from "./items/ZoneItem"; import { Zone } from "./types/Zone"; import { SMouseEvent } from "@saga-web/base/lib"; 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"; // @ts-ignore import { intersect } from "polybooljs"; import { ShadeItem } from "./items/ShadeItem"; import { Point } from "./types/Point"; import { LikeSpaceItem } from "./items/LikeSpaceItem"; /** * 划分业务空间 * * @author 郝建龙 */ export class DivideFloorScene extends FloorScene { /** 是否开启用户标记 */ _isMarking: boolean = false; get isMarking(): boolean { return this._isMarking; } // Get isMarking set isMarking(v: boolean) { if (this._isMarking === v) { return; } this._isMarking = v; } // Set isMarking /** 蒙版item */ sceneMark: SceneMarkItem | null = null; /** 业务空间list */ zoneList: ZoneItem[] = []; /** 遮罩List */ shadeList: ShadeItem[] = []; /** 划分item */ cutItem: ShadeItem | null = null; /** 类空间itemList */ likeSpaceList: LikeSpaceItem[] = []; /** 高亮item */ highLight: HighlightItem = new HighlightItem(null); /** 是否开启切分 */ isCutting: boolean = false; /** 业务空间是否可选 */ _isZoneSelectable: boolean = true; get isZoneSelectable(): boolean { return this._isZoneSelectable; } // Get isZoneSelectable set isZoneSelectable(v: boolean) { if (this._isZoneSelectable === v) { return; } this._isZoneSelectable = v; this.zoneList.map((t: ZoneItem) => { t.selectable = this._isZoneSelectable; if (!t.selectable) { t.selected = false; } return t; }); } // Set isZoneSelectable /** 是否开启吸附 */ private _isAbsorbing: boolean = false; get isAbsorbing(): boolean { return this._isAbsorbing; } // Get isAbsorbing 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 /** * 构造函数 * */ constructor() { super(); this.addItem(this.highLight); } // Constructor /** * 添加轮廓线 * * @param data */ addSceneMark(data: SPoint[]): void { if (data.length) { let outline = data.map(t => { t.y = -t.y; return t; }); let sceneMark = new SceneMarkItem(null, outline); this.addItem(sceneMark); this.sceneMark = sceneMark; } } // Function addSceneMark() /** * 清除蒙版 * */ clearSceneMark(): void { if (this.sceneMark) { this.grabItem = null; this.removeItem(this.sceneMark); this.sceneMark = null; this.isMarking = false; } } // Function clearSceneMark() /** * 清除划分区域 * */ clearCut(): void { if (this.cutItem) { this.grabItem = null; this.removeItem(this.cutItem); this.cutItem = null; this.isCutting = false; } } // Function clearCut() /** * 添加所有遮罩层 * * @param data 遮罩数据 */ addAllShade(data: SPoint[][]): void { if (data.length) { data.map(t => { this.addShade(t); }); } } // Function addAllShade() /** * 添加单个遮罩 * * @param data 遮罩数据 */ addShade(data: SPoint[]): void { let outLine = data.map(t => { t.y = -t.y; return t; }); let item = new ShadeItem(null, outLine); this.shadeList.push(item); this.addItem(item); } // Function addShade() /** * 添加所有类空间item * * @param data 所有数据 */ addAllLikeSpace(data: Point[][][]): void { if (data.length) { data.map(t => { this.addLikeSpace(t); }); } } // Function addAllLikeSpace() /** * 添加单个类空间item * * @param data 单个类空间item数据 */ addLikeSpace(data: Point[][]): void { let item = new LikeSpaceItem(null, data); item.selectable = true; item.selected = true; this.likeSpaceList.push(item); this.addItem(item); } // Function addLikeSpace() /** * 清除所有类空间item * */ clearLikeSpaces(): void { if (this.likeSpaceList.length) { this.likeSpaceList.map(t => { this.removeItem(t); }); this.likeSpaceList = []; } } // Function clearLikeSpaces() /** * 获取选中的类空间 */ getSelectedLikeSpace(): LikeSpaceItem[] { let arr: LikeSpaceItem[] = []; this.likeSpaceList.map(t => { if (t.selected) { arr.push(t); } }); return arr; } // Function getSelectedLikeSpace() /** * 鼠标按下事件 * * @param event 保存事件参数 * @return boolean */ onMouseDown(event: SMouseEvent): boolean { 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.isPointInShade(event.x, event.y)) { return true; } 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.isCutting) { // 判断是否开启吸附,并且有吸附的点 if (this.isAbsorbing && this.highLight.visible) { event.x = this.highLight.point.x; event.y = this.highLight.point.y; } if ( this.sceneMark && this.sceneMark.contains(event.x, event.y) ) { return true; } if (this.cutItem) { this.cutItem.onMouseDown(event); } else { let point = new SPoint(event.x, event.y); let cut = new ShadeItem(null, point); this.addItem(cut); this.cutItem = cut; this.grabItem = cut; } } 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 { super.onMouseDown(event); } } else { super.onMouseDown(event); } return false; } // Function onMouseDown() /** * 鼠标抬起事件 * * @param event 保存事件参数 * @return boolean */ onMouseUp(event: SMouseEvent): boolean { if (this.rectSelectItem) { this.isRectSelection = false; this.groupSelectSpace(); 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) { if (!this.absorbShade(event)) { this.absorbSpace(event); } } return false; } // Function onMouseMove() /*** * 键盘弹起事件 * * @param event 保存事件参数 */ onKeyUp(event: KeyboardEvent): void { if (this.isMarking || this.isCutting) { if (this.grabItem) { this.grabItem.onKeyUp(event); } } else { super.onKeyUp(event); } } // Function onKeyUp() /*** * 注册鼠标点击事件 * * @param _this 接收者 * @param fn 处理函数 */ click(_this: any, fn: Function): void { this.spaceList.map(t => { t.connect("click", _this, fn); }); this.zoneList.map(t => { t.connect("click", _this, fn); }); } // Function click() /** * 添加业务空间到scene 中 * * @param zone 业务空间list */ addZoneList(zone: Zone[]): void { zone.map(t => { this.addZone(t); }); } // Function addZoneList() /** * 添加业务空间到scene 中 * * @param zone 业务空间 */ addZone(zone: Zone): void { let item = new ZoneItem(null, zone); item.selectable = this.isZoneSelectable; this.zoneList.push(item); this.addItem(item); } // Function addZone() /** * 清空选中的空间 * */ clearSpaceSelection(): void { this.spaceList.map(t => { t.selected = false; return t; }); } // Function clearSpaceSelection() /** * 清空选中的业务空间 * */ clearZoneSelection(): void { this.zoneList.map(t => { t.selected = false; return t; }); } // Function clearZoneSelection() /** * 删除所有业务空间 */ removeAllZone(): void { if (this.zoneList.length) { this.zoneList.map(t => { this.removeItem(t); }); this.zoneList = []; } } // Function removeAllZone() /** * 吸附空间 * * @param event 鼠标事件对象 * @return boolean 是否找到吸附的对象 */ absorbSpace(event: SMouseEvent): boolean { let absorbLen = 1000; if (this.view) { absorbLen = 10 / this.view.scale; } let P = this.absorbSpacePoint(event, absorbLen); if (P.Point) { this.highLight.distance = P.MinDis; this.highLight.point = new SPoint(P.Point.X, -P.Point.Y); this.highLight.visible = true; return true; } else { let L = this.absorbSpaceLine(event, absorbLen); if (L.Line && L.Point) { this.highLight.distance = L.MinDis; this.highLight.point = L.Point; this.highLight.line = L.Line; this.highLight.visible = true; return true; } return false; } } // Function absorbSpace() /** * 点是否在吸附区域内 * * @param p 要判断的点 * @param minX 空间区域 * @param minY 空间区域 * @param maxX 空间区域 * @param maxY 空间区域 */ static isPointInAbsorbArea( p: SPoint, minX: number, maxX: number, minY: number, maxY: number ): boolean { let rect = new SRect( minX - 1000, minY - 1000, maxX - minX + 2000, maxY - minY + 2000 ); return rect.contains(p.x, p.y); } // Function isPointInAbsorbArea() /** * 吸附空间点 * * @param event 鼠标事件对象 * @param absorbLen 吸附距离 * @return MinDis 吸附的点 */ absorbSpacePoint(event: SMouseEvent, absorbLen: number): MinDis { let minPointDis = Number.MAX_SAFE_INTEGER; let Point; this.spaceList.map(space => { if ( DivideFloorScene.isPointInAbsorbArea( new SPoint(event.x, event.y), space.minX, space.maxX, space.minY, space.maxY ) ) { space.data.OutLine.map(item => { let minDis = SMathUtil.getMinDisPoint( new SPoint(event.x, event.y), item ); if ( minDis && minDis.MinDis < absorbLen && minDis.MinDis < minPointDis ) { minPointDis = minDis.MinDis; Point = minDis.Point; } }); } }); let minPoint = { MinDis: minPointDis, Point: Point }; return minPoint; } // Function absorbSpacePoint() /** * 吸附空间线 * * @param event 鼠标事件对象 * @param absorbLen 吸附距离 * @return PointToLine 吸附的线 */ absorbSpaceLine(event: SMouseEvent, absorbLen: number): PointToLine { let minPointDis = Number.MAX_SAFE_INTEGER; let Point, Line; this.spaceList.map(space => { if ( DivideFloorScene.isPointInAbsorbArea( new SPoint(event.x, event.y), space.minX, space.maxX, space.minY, space.maxY ) ) { space.data.OutLine.map(item => { let minDisLine = SMathUtil.getMinDisLine( new SPoint(event.x, event.y), item ); if ( minDisLine && minDisLine.MinDis < absorbLen && minDisLine.MinDis < minPointDis ) { minPointDis = minDisLine.MinDis; Point = minDisLine.Point; Line = minDisLine.Line; } }); } }); let minPointLine = { MinDis: minPointDis, Point: Point, Line: Line }; return minPointLine; } // Function absorbSpaceLine() /** * 吸附遮罩 * * @param event 鼠标事件对象 * @return boolean 是否找到吸附的对象 */ absorbShade(event: SMouseEvent): boolean { let absorbLen = 1000; if (this.view) { absorbLen = 10 / this.view.scale; } let P = this.absorbShadePoint(event, absorbLen); if (P.Point) { this.highLight.distance = P.MinDis; this.highLight.point = new SPoint(P.Point.X, -P.Point.Y); this.highLight.visible = true; return true; } else { let L = this.absorbShadeLine(event, absorbLen); if (L.Line && L.Point) { this.highLight.distance = L.MinDis; this.highLight.point = L.Point; this.highLight.line = L.Line; this.highLight.visible = true; return true; } return false; } } // Function absorbSpace() /** * 吸附遮罩点 * * @param event 鼠标事件对象 * @param absorbLen 吸附距离 * @return MinDis 吸附的点 */ absorbShadePoint(event: SMouseEvent, absorbLen: number): MinDis { let minPointDis = Number.MAX_SAFE_INTEGER; let Point; this.shadeList.map(shade => { let PointArr = shade.outLine.map(item => { return { X: item.x, Y: -item.y, Z: 0 }; }); let minDis = SMathUtil.getMinDisPoint( new SPoint(event.x, event.y), PointArr ); if ( minDis && minDis.MinDis < absorbLen && minDis.MinDis < minPointDis ) { minPointDis = minDis.MinDis; Point = minDis.Point; } }); let minPoint = { MinDis: minPointDis, Point: Point }; return minPoint; } // Function absorbSpacePoint() /** * 吸附遮罩线 * * @param event 鼠标事件对象 * @param absorbLen 吸附距离 * @return PointToLine 吸附的线 */ absorbShadeLine(event: SMouseEvent, absorbLen: number): PointToLine { let minPointDis = Number.MAX_SAFE_INTEGER; let Point, Line; this.shadeList.map(shade => { let PointArr = shade.outLine.map(item => { return { X: item.x, Y: -item.y, Z: 0 }; }); let minDisLine = SMathUtil.getMinDisLine( new SPoint(event.x, event.y), PointArr ); if ( minDisLine && minDisLine.MinDis < absorbLen && minDisLine.MinDis < minPointDis ) { minPointDis = minDisLine.MinDis; Point = minDisLine.Point; Line = minDisLine.Line; } }); let minPointLine = { MinDis: minPointDis, Point: Point, Line: Line }; return minPointLine; } // Function absorbSpaceLine() /** * 计算绘制区域与选中空间交集 * */ getIntersect(): SPoint[][] { let arr: SPoint[][] = []; let poly2 = { regions: [], inverted: false }; if (this.cutItem) { poly2.regions.push( // @ts-ignore SMathUtil.transferToArray(this.cutItem.outLine) ); } else if (this.sceneMark) { poly2.regions.push( // @ts-ignore SMathUtil.transferToArray(this.sceneMark.outLine) ); } if (poly2.regions.length) { this.spaceList.map(t => { if (t.selected) { let poly1 = { regions: [], inverted: false }; // @ts-ignore poly1.regions = t.pointArr.map(item => { return SMathUtil.transferToArray(item); }); console.log(poly1); let intersectObj = intersect(poly1, poly2); if (intersectObj.regions.length) { intersectObj.regions.map((t: number[][]) => { arr.push(SMathUtil.transferToSPoint(t)); }); } } }); } return arr; } // Function getIntersect() /** * 计算绘制区域与选中类空间交集 * */ getLikeIntersect(): SPoint[][] { let arr: SPoint[][] = []; let poly2 = { regions: [], inverted: false }; if (this.cutItem) { poly2.regions.push( // @ts-ignore SMathUtil.transferToArray(this.cutItem.outLine) ); } else if (this.sceneMark) { poly2.regions.push( // @ts-ignore SMathUtil.transferToArray(this.sceneMark.outLine) ); } if (poly2.regions.length) { this.likeSpaceList.map(t => { if (t.selected) { let poly1 = { regions: [], inverted: false }; // @ts-ignore poly1.regions = t.pointArr.map(item => { return SMathUtil.transferToArray(item); }); console.log(poly1); let intersectObj = intersect(poly1, poly2); if (intersectObj.regions.length) { intersectObj.regions.map((t: number[][]) => { arr.push(SMathUtil.transferToSPoint(t)); }); } } }); } return arr; } // Function getIntersect() /** * 框选区域,选中与之相交的空间 * */ groupSelectSpace(): void { if (this.rectSelectItem) { let item = this.rectSelectItem; let poly2 = { regions: [ [ [item.startPoint.x, item.startPoint.y], [item.startPoint.x, item.endPoint.y], [item.endPoint.x, item.endPoint.y], [item.endPoint.x, item.startPoint.y] ] ], inverted: false }; this.spaceList.map(t => { let poly1 = { regions: [], inverted: false }; // @ts-ignore poly1.regions = t.pointArr.map(item => { return SMathUtil.transferToArray(item); }); let intersectObj = intersect(poly1, poly2); t.selected = intersectObj.regions.length ? true : false; }); } } // Function groupSelectSpace() /** * 判断点是否在遮罩区域内 * * @param x 点x坐标 * @param y 点y坐标 * @return boolean */ isPointInShade(x: number, y: number): boolean { if (this.shadeList.length) { for (let i = 0; i < this.shadeList.length; i++) { if (this.shadeList[i].contains(x, y)) { return true; } } } return false; } // Function isPointInShade() } // Class DivideFloorScene