diff --git a/src/Add-on/DrawBoard/DrawLayerBoard.ts b/src/Add-on/DrawBoard/DrawLayerBoard.ts index 80eb30b03..540e60145 100644 --- a/src/Add-on/DrawBoard/DrawLayerBoard.ts +++ b/src/Add-on/DrawBoard/DrawLayerBoard.ts @@ -1,9 +1,9 @@ -import { Vector3 } from 'three'; +import { Vector3, Matrix4, Raycaster } from 'three'; import { app } from '../../ApplicationServices/Application'; import { Board, BoardType } from '../../DatabaseServices/Board'; import { Command } from '../../Editor/CommandMachine'; import { PromptStatus } from '../../Editor/PromptResult'; -import { MoveMatrix } from '../../Geometry/GeUtils'; +import { MoveMatrix, equaln } from '../../Geometry/GeUtils'; import { GeneralSpaceParse } from '../../Geometry/SpaceParse/GeneralSpaceParse'; import { LayerBoardStore, ModalState, LayerPosType, LayerBoardOption } from '../../UI/Store/BoardStore'; import { BoardModalType } from '../../UI/Components/Board/BoardModal'; @@ -12,11 +12,138 @@ import { Box3Ext } from '../../Geometry/Box'; export class DrawLayerBoard implements Command { async exec() + { + this.SelectBoards(); + + } + buildBoard(box: Box3Ext, opt: LayerBoardOption, ro: Matrix4) + { + let size = box.getSize(new Vector3()); + let width = opt.isTotalWidth ? size.y : parseFloat(opt.width); + let count = parseInt(opt.count); + let type = opt.posType; + let dist = parseFloat(opt.dist); + let frontShrink = parseFloat(opt.frontShrink); + let board = Board.CreateBoard(size.x, width, parseFloat(opt.thickness), BoardType.Layer); + + for (let i = 1; i <= count; i++) + { + let b = board.Clone() as Board; + if (type === LayerPosType.Top) + b.ApplyMatrix(MoveMatrix(box.min.clone().add(new Vector3(size.x, frontShrink, size.z - (dist / 100 * i))))); + else if (type === LayerPosType.Bottom) + b.ApplyMatrix(MoveMatrix(box.min.clone().add(new Vector3(size.x, frontShrink, (dist / 100) * i)))); + else + b.ApplyMatrix(MoveMatrix(box.min.clone().add(new Vector3(size.x, frontShrink, size.z / (count + 1) * i)))); + + b.ApplyMatrix(ro); + app.m_Database.ModelSpace.Append(b); + } + } + async selectBox(spaces: Box3Ext[]) + { + if (spaces.length === 1) + return spaces[0]; + + spaces.sort((b1, b2) => + { + if (equaln(b2.min.z, b1.min.z)) + { + return b1.min.y - b2.min.y; + } + return b1.min.z - b2.min.z + }); + + if (spaces.length > 2) + { + let keyWord = await app.m_Editor.GetKeyWords({ + Msg: "输入位置:", + KeyWordList: [{ key: "1", msg: "靠上" }, { key: "2", msg: "靠下" }] + }); + + if (keyWord.StringResult == "1") + { + spaces = spaces.splice(spaces.length / 2, spaces.length / 2) + } + else if (keyWord.StringResult == "2") + { + spaces = spaces.splice(0, spaces.length / 2) + } + + keyWord = await app.m_Editor.GetKeyWords({ + Msg: "输入位置:", + KeyWordList: [{ key: "3", msg: "靠前" }, { key: "4", msg: "靠后" }] + }); + if (keyWord.StringResult == "3") + { + spaces[0].min.y < spaces[1].min.y ? spaces.pop() : spaces.shift(); + } + else if (keyWord.StringResult == "4") + { + spaces[0].min.y > spaces[1].min.y ? spaces.pop() : spaces.shift(); + } + } + else + { + if (spaces[0].min.z === spaces[1].min.z) + { + let keyWord = await app.m_Editor.GetKeyWords({ + Msg: "输入位置:", + KeyWordList: [{ key: "3", msg: "靠前" }, { key: "4", msg: "靠后" }] + }); + if (keyWord.StringResult == "3") + { + spaces[0].min.y < spaces[1].min.y ? spaces.pop() : spaces.shift(); + } + else if (keyWord.StringResult == "4") + { + spaces[0].min.y > spaces[1].min.y ? spaces.pop() : spaces.shift(); + } + } + else + { + let keyWord = await app.m_Editor.GetKeyWords({ + Msg: "输入位置:", + KeyWordList: [{ key: "1", msg: "靠上" }, { key: "2", msg: "靠下" }] + }); + + if (keyWord.StringResult == "1") + { + spaces = spaces.splice(spaces.length / 2, spaces.length / 2) + } + else if (keyWord.StringResult == "2") + { + spaces = spaces.splice(0, spaces.length / 2) + } + } + } + return spaces[0]; + } + async PointSelect() + { + let ptRes = await app.m_Editor.GetPoint({ Msg: "点选画板区域" }); + let view = app.m_Viewer; + if (ptRes.Status !== PromptStatus.Cancel) + { + let pt = ptRes.Value; + let raycaster = new Raycaster(); + raycaster.setFromCamera({ + x: (pt.x / view.Width) * 2 - 1, //-1 到 1 所以 (x-(w/2))/(w/2) => + y: - (pt.y / view.Height) * 2 + 1 //y轴相反 + }, view.Camera); + raycaster.ray.origin.sub(raycaster.ray.direction.clone().multiplyScalar(1e3)); + + + + } + + } + + async SelectBoards() { let exSsRes = await app.m_Editor.GetSelection({ Msg: "请选择对象<全部选择>:", UseSelect: true }); if (exSsRes.Status === PromptStatus.Cancel) return; - let boardCus = exSsRes.SelectSet.SelectEntityList.filter(en => en instanceof Board) as Board[]; @@ -39,52 +166,21 @@ export class DrawLayerBoard implements Command return; } let opt = store.layerBoardOption; + let ro = new Matrix4().extractRotation(spaceParse.OCS); - for (let box of spaceParse.Spaces) - { - this.buildBoard(box, opt); - } + let spaces = spaceParse.Spaces; + let box = await this.selectBox(spaces); + + this.buildBoard(box, opt, ro); + + // for (let box of spaceParse.Spaces) + // { + // this.buildBoard(box, opt, ro); + // } } else { app.m_Editor.m_CommandStore.Prompt("请选择板件") } } - buildBoard(box: Box3Ext, opt: LayerBoardOption) - { - let size = box.getSize(new Vector3()); - let width = opt.isTotalWidth ? size.y : parseFloat(opt.width); - let count = parseInt(opt.count); - let type = opt.posType; - let dist = parseFloat(opt.dist); - let frontShrink = parseFloat(opt.frontShrink); - let board = Board.CreateBoard(size.x, width, parseFloat(opt.thickness), BoardType.Layer); - - switch (type) - { - case LayerPosType.Top: - for (let i = 1; i <= count; i++) - { - let b = board.Clone() as Board; - b.ApplyMatrix(MoveMatrix(box.min.clone().add(new Vector3(size.x, frontShrink, size.z - (dist / 100 * i))))); - app.m_Database.ModelSpace.Append(b); - } - break; - case LayerPosType.Bottom: - for (let i = 1; i <= count; i++) - { - let b = board.Clone() as Board; - b.ApplyMatrix(MoveMatrix(box.min.clone().add(new Vector3(size.x, frontShrink, (dist / 100) * i)))); - app.m_Database.ModelSpace.Append(b); - } - break; - case LayerPosType.Mid: - for (let i = 1; i <= count; i++) - { - let b = board.Clone() as Board; - b.ApplyMatrix(MoveMatrix(box.min.clone().add(new Vector3(size.x, frontShrink, size.z / (count + 1) * i)))); - app.m_Database.ModelSpace.Append(b); - } - } - } } diff --git a/src/Editor/PointPick.ts b/src/Editor/PointPick.ts index 16aa9b60e..5824eea4e 100644 --- a/src/Editor/PointPick.ts +++ b/src/Editor/PointPick.ts @@ -54,7 +54,6 @@ export function PointPick(ptVcs: Vector3, view: Viewer | PreViewer, selectObject if (pickObj) return [pickObj]; - let selectList = []; let pCenter = new THREE.Vector2(ptVcs.x, ptVcs.y); let selectSize = new THREE.Vector2(10, 10); diff --git a/src/Geometry/SpaceParse/GeneralSpaceParse.ts b/src/Geometry/SpaceParse/GeneralSpaceParse.ts index ce7902bf6..668b0c6d5 100644 --- a/src/Geometry/SpaceParse/GeneralSpaceParse.ts +++ b/src/Geometry/SpaceParse/GeneralSpaceParse.ts @@ -6,6 +6,8 @@ import { Line } from "../../DatabaseServices/Line"; import { Box3Ext } from "../Box"; import { MoveMatrix, equal, equaln } from "../GeUtils"; import { testBox3 } from "../../Add-on/testEntity/TestCurve"; +import { arrayLast } from "../../Common/ArrayExt"; + /** *通用空间分析;类 @@ -34,13 +36,211 @@ export class GeneralSpaceParse extends SpaceParse this.parseBoards(boards, unionBoxes, spliteBoxes); } else if (boards.length === 1) + { + let b = boards[0].Clone() as Board; + b.ApplyMatrix(new Matrix4().extractRotation(b.BoardOCSInv)) + let box = b.BoundingBox; + box.spliteType = boards[0].BoardType; + spliteBoxes.push(box); + } + } + this.SpliteBoxs(this.MergeSpaces(unionBoxes) as Box3Ext, spliteBoxes); + } + + private MergeSpaces(spaces: Box3Ext[]) + { + let b1 = spaces.shift(); + let isInt = false; + for (let box of spaces) + { + if (b1.intersectsBox(box)) + { + isInt = true; + b1.intersect(box); + } + } + if (!isInt && spaces.length === 2) + { + b1 = spaces[0]; + let b2 = spaces[1]; + if (b1.intersectsBox(b2)) + { + return b1.intersect(b2); + } + return undefined; + } + + return b1; + } + private SpliteBoxs(box: Box3Ext, spliteBoxes: Box3Ext[]) + { + if (spliteBoxes.length === 0) + this.m_Spaces = [box]; + else + { + let boxes = [box]; + for (let i = 0; i < boxes.length; i++) + { + let box = boxes[i]; + for (let j = 0; j < spliteBoxes.length; j++) + { + let bs = box.substract(spliteBoxes[j]); + if (bs.length > 0) + { + boxes.splice(i, 1, ...bs); + i -= (bs.length - 1); + break; + } + else if (j === spliteBoxes.length - 1) + { + this.m_Spaces.push(box); + } + } + } + } + } + //分析2个盒子之间的空间 + private parseBox3(b1: Box3Ext, b2: Box3Ext, boardType: BoardType) + { + let dist: number; + switch (boardType) + { + case BoardType.Layer: + return this.getSpace(b1, b2, "z"); + case BoardType.Vertical: + return this.getSpace(b1, b2, "x"); + case BoardType.Behind: + return this.getSpace(b1, b2, "y"); + } + } + //获取2个盒子之间的空间 + getSpace(b1: Box3Ext, b2: Box3Ext, axis: string) + { + [b1, b2] = b1.min[axis] < b2.min[axis] ? [b1, b2] : [b2, b1]; + let dist = b2.min[axis] - b1.min[axis]; + if (dist <= b1.getSize(new Vector3())[axis]) + { + return new Box3Ext(); + } + let vec = new Vector3(); + vec[axis] = -dist; + b2.applyMatrix4(MoveMatrix(vec)); + if (b1.intersectsBox(b2)) + { + b1.intersect(b2); + } + else + { + b1.union(b2); + } + + let vec1 = new Vector3(); + vec1[axis] = b1.getSize(new Vector3())[axis]; + + let vec2 = new Vector3(); + vec2[axis] = dist - b2.getSize(new Vector3())[axis]; + + return new Box3Ext(b1.min.add(vec1), b1.max.add(vec2)); + } + //分析多块板 + private parseBoards(boards: Board[], uniSpaces: Box3Ext[], spliteSPs: Box3Ext[]) + { + let boxMap: Map = new Map(); + + for (let br of boards) + { + let b = br.Clone() as Board; + b.ApplyMatrix(new Matrix4().extractRotation(br.BoardOCSInv)) + let box = b.BoundingBox; + boxMap.set(br, box); + } + + switch (boards[0].BoardType) + { + case BoardType.Layer: + this.sortAndMerge(boards, boxMap, "z"); + break; + case BoardType.Vertical: + this.sortAndMerge(boards, boxMap, "x"); + break; + case BoardType.Behind: + this.sortAndMerge(boards, boxMap, "y"); + } + + if (boards.length >= 2) + { + let b1 = boards[0]; + let box1 = boxMap.get(b1).clone(); + let b2 = arrayLast(boards); + let box2 = boxMap.get(b2).clone(); + + let box = this.parseBox3(box1, box2, b1.BoardType) + if (!box.isEmpty()) + { + uniSpaces.push(box); + } + } + } + //排序归并板件 + private sortAndMerge(boards: Board[], boxMap: Map, type: string) + { + boards.sort((a, b) => boxMap.get(a).min[type] - boxMap.get(b).min[type]); + + for (let i = 0; i < boards.length; i++) + { + let b1 = boards[i]; + let box1 = boxMap.get(b1); + for (let j = i + 1; j < boards.length; j++) + { + let b2 = boards[j]; + let box2 = boxMap.get(b2); + if (equaln(box1.min[type], box2.min[type])) + { + let b = box1.clone(); + box1.union(box2) + boards.splice(j, 1); + j--; + } + else + { + i = j - 1; + break; + } + } + } + } + +} + +export class GeneralSpaceParse1 extends SpaceParse +{ + private m_Spaces: Box3Ext[] = []; + get Spaces() + { + return this.m_Spaces; + } + SpaceParse() + { + super.SpaceParse(); + let unionBoxes: Box3Ext[] = []; + let spliteBoxes: Box3Ext[] = []; + for (let key of this.boardMap.keys()) + { + let boards = this.boardMap.get(key); + if (boards.length > 1) + { + // this.parseBoards(boards, unionBoxes, spliteBoxes); + this.parseBoards2(boards, unionBoxes, spliteBoxes); + } + else if (boards.length === 1) { let box = boards[0].BoundingBox as Box3Ext; box.spliteType = boards[0].BoardType; spliteBoxes.push(box); } } - this.SpliteBoxs(this.MergeSpaces(unionBoxes), spliteBoxes); + // this.SpliteBoxs(this.MergeSpaces(unionBoxes), spliteBoxes); + this.SpliteBoxs2(unionBoxes, spliteBoxes); } private MergeSpaces(spaces: Box3Ext[]) { @@ -91,6 +291,31 @@ export class GeneralSpaceParse extends SpaceParse } } + } + private SpliteBoxs2(boxes: Box3Ext[], spliteBoxes: Box3Ext[]) + { + if (spliteBoxes.length === 0) + this.m_Spaces = boxes; + else + for (let i = 0; i < boxes.length; i++) + { + let box = boxes[i]; + for (let j = 0; j < spliteBoxes.length; j++) + { + let bs = box.substract(spliteBoxes[j]); + if (bs.length > 1) + { + boxes.splice(i, 1, ...bs); + i -= (bs.length - 1); + break; + } + else if (j === spliteBoxes.length - 1) + { + this.m_Spaces.push(box); + } + } + } + } //分析2个盒子之间的空间 private parseBox3(b1: Box3Ext, b2: Box3Ext, boardType: BoardType) @@ -180,6 +405,81 @@ export class GeneralSpaceParse extends SpaceParse } } + } + private parseBoards2(boards: Board[], uniSpaces: Box3Ext[], spliteSPs: Box3Ext[]) + { + let boxMap: Map = new Map(); + + for (let br of boards) + { + let box = br.BoundingBox as Box3Ext; + box.applyMatrix4(new Matrix4().extractRotation(br.BoardOCSInv)); + boxMap.set(br, box); + } + + switch (boards[0].BoardType) + { + case BoardType.Layer: + this.sortAndMerge(boards, boxMap, "z"); + break; + case BoardType.Vertical: + this.sortAndMerge(boards, boxMap, "x"); + break; + case BoardType.Behind: + this.sortAndMerge(boards, boxMap, "y"); + } + + if (boards.length === 1) + { + let box = boxMap.get(boards[0]); + box.spliteType = boards[0].BoardType; + spliteSPs.push(box); + } + if (uniSpaces.length === 0) + { + for (let i = 0; i < boards.length - 1; i++) + { + let b1 = boards[i]; + let box1 = boxMap.get(b1); + + let b2 = boards[i + 1]; + let box2 = boxMap.get(b2).clone(); + let box = this.parseBox3(box1, box2, b1.BoardType) + if (!box.isEmpty()) + { + box.spliteType = b1.BoardType; + uniSpaces.push(box); + } + } + } + else + { + for (let i = 0; i < boards.length - 1; i++) + { + let b1 = boards[i]; + let box1 = boxMap.get(b1); + let b2 = boards[i + 1]; + let box2 = boxMap.get(b2).clone(); + let box = this.parseBox3(box1.clone(), box2.clone(), b1.BoardType) + if (!box.isEmpty()) + { + if (uniSpaces.every(b => !b.intersectsBox(box))) + { + this.m_Spaces.push(box); + continue; + } + box1.spliteType = b1.BoardType; + spliteSPs.push(box1) + } + + if (i === boards.length - 2) + { + box2.spliteType = b1.BoardType; + spliteSPs.push(box2) + } + } + } + } //排序归并板件 private sortAndMerge(boards: Board[], boxMap: Map, type: string) @@ -209,4 +509,7 @@ export class GeneralSpaceParse extends SpaceParse } } } + } + + diff --git a/src/Geometry/SpaceParse/SpaceParse.ts b/src/Geometry/SpaceParse/SpaceParse.ts index 1070d3a60..43c44349c 100644 --- a/src/Geometry/SpaceParse/SpaceParse.ts +++ b/src/Geometry/SpaceParse/SpaceParse.ts @@ -35,7 +35,7 @@ export class SpaceParse get OCS() { - return this.m_StandardBoard ? this.m_StandardBoard.BoardOCS : new Matrix4(); + return this.m_Boards[0].BoardOCS; } SpaceParse() {