mirror of https://gitee.com/cf-fz/WebCAD.git
parent
dfe37d0b0d
commit
2888003a43
@ -0,0 +1,475 @@
|
||||
import { Matrix4, Mesh, Object3D, Ray, Raycaster, Vector2, Vector3 } from 'three';
|
||||
import { app } from '../../ApplicationServices/Application';
|
||||
import { arrayRemoveIf } from '../../Common/ArrayExt';
|
||||
import { Vec3DTo2D } from '../../Common/CurveUtils';
|
||||
import { Board, BoardType } from '../../DatabaseServices/Board';
|
||||
import { Command } from '../../Editor/CommandMachine';
|
||||
import { PromptStatus } from '../../Editor/PromptResult';
|
||||
import { SelectLine } from '../../Editor/SelectBox';
|
||||
import { Box3Ext } from '../../Geometry/Box';
|
||||
import { equaln } from '../../Geometry/GeUtils';
|
||||
import { GeneralSpaceParse, GeneralSpaceParse2 } from '../../Geometry/SpaceParse/GeneralSpaceParse';
|
||||
import { Viewer } from '../../GraphicsSystem/Viewer';
|
||||
import { BoardModalType } from '../../UI/Components/Board/BoardModal';
|
||||
import { BehindBoardStore, LayerBoardStore, VerticalBoardStore, BoardStore } from '../../UI/Store/BoardStore';
|
||||
import { ModalState, BoardOption } from '../../UI/Store/BoardInterface';
|
||||
|
||||
export abstract class DrawBoardTool implements Command
|
||||
{
|
||||
//画板件类型,默认画层板
|
||||
protected drawType = BoardType.Layer;
|
||||
async exec()
|
||||
{
|
||||
//原来禁用捕捉开启状态
|
||||
let oldSnapState = app.m_Editor.m_GetpointServices.snapServices.m_Disabled;
|
||||
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = true;
|
||||
|
||||
let store: LayerBoardStore | VerticalBoardStore | BehindBoardStore;
|
||||
let modalType: BoardModalType;
|
||||
switch (this.drawType)
|
||||
{
|
||||
case BoardType.Layer:
|
||||
store = LayerBoardStore.Store();
|
||||
modalType = BoardModalType.Ly;
|
||||
break;
|
||||
case BoardType.Vertical:
|
||||
store = VerticalBoardStore.Store();
|
||||
modalType = BoardModalType.Ve;
|
||||
break;
|
||||
case BoardType.Behind:
|
||||
store = BehindBoardStore.Store();
|
||||
modalType = BoardModalType.Be;
|
||||
|
||||
}
|
||||
app.m_Editor.m_ModalManage.RenderBoardModal(store, modalType);
|
||||
|
||||
let state = await store.GetBoardOption();
|
||||
|
||||
if (state !== ModalState.Ok)
|
||||
return;
|
||||
|
||||
await this.SelectPoint(store, modalType)
|
||||
|
||||
//恢复原先状态
|
||||
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = oldSnapState;
|
||||
}
|
||||
private async SelectPoint(store: BoardStore, type: BoardModalType)
|
||||
{
|
||||
// 板件数据
|
||||
let opt = store.m_BoardOption;
|
||||
|
||||
let view = app.m_Viewer;
|
||||
|
||||
while (true)
|
||||
{
|
||||
let ptRes = await app.m_Editor.GetPoint({
|
||||
Msg: "点选画板区域",
|
||||
KeyWordList: [{ msg: "框选", key: "S" }, { msg: "全选", key: "A" }, { msg: "放弃", key: "U" }]
|
||||
});
|
||||
|
||||
if (ptRes.Status === PromptStatus.OK)
|
||||
{
|
||||
let brs: Board[] = [];
|
||||
|
||||
let mousePt = ptRes.Value.clone();
|
||||
|
||||
view.WorldToScreen(mousePt);
|
||||
|
||||
//是否选到背板
|
||||
let en = this.pointPick(mousePt, view);
|
||||
//选中面法向量
|
||||
let normal: Vector3;
|
||||
//鼠标在面上的交点
|
||||
let origin: Vector3;
|
||||
if (en.pickObj && (<Board>en.pickObj.userData).BoardType === BoardType.Behind)
|
||||
{
|
||||
brs.push(en.pickObj.userData);
|
||||
let res = this.getPtSurroundBoardsByPick(en, view, brs);
|
||||
normal = res.normal;
|
||||
origin = res.origin;
|
||||
}
|
||||
else
|
||||
{
|
||||
//选择上下左右的板
|
||||
this.getPtSurroundBoardsByMouse(mousePt, view, brs);
|
||||
}
|
||||
//分析点周围的空间
|
||||
if (brs.length > 1)
|
||||
{
|
||||
let spaceParse = new GeneralSpaceParse(brs);
|
||||
await spaceParse.SpaceParse();
|
||||
|
||||
if (spaceParse.Spaces.length === 0)
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("生成b板件失败,没分析出有效空间");
|
||||
continue;
|
||||
}
|
||||
|
||||
//柜子旋转矩阵
|
||||
let ro = new Matrix4().extractRotation(spaceParse.OCS);
|
||||
|
||||
//存在的空间
|
||||
let spaces = spaceParse.Spaces;
|
||||
|
||||
if (spaces.length > 1)
|
||||
{
|
||||
let ray: Ray;
|
||||
//构造射线,取和射线相交的空间
|
||||
if (normal)
|
||||
{
|
||||
ray = new Ray(origin, normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
let raycaster = new Raycaster();
|
||||
raycaster.setFromCamera({
|
||||
x: (mousePt.x / view.Width) * 2 - 1,
|
||||
y: - (mousePt.y / view.Height) * 2 + 1
|
||||
}, view.Camera);
|
||||
ray = raycaster.ray;
|
||||
ray.origin.sub(raycaster.ray.direction.clone().multiplyScalar(1e3));
|
||||
}
|
||||
arrayRemoveIf(spaces, box =>
|
||||
{
|
||||
let b = box.clone().applyMatrix4(ro);
|
||||
return !Boolean(ray.intersectBox(b, new Vector3()))
|
||||
});
|
||||
}
|
||||
if (spaces.length > 0)
|
||||
{
|
||||
let box = spaces[0];
|
||||
this.buildBoard(box, opt, ro);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("请选择有效的板件,或者周围没有效板件");
|
||||
}
|
||||
|
||||
}
|
||||
else if (ptRes.Status === PromptStatus.Keyword)
|
||||
{
|
||||
if (ptRes.StringResult === "S")
|
||||
{
|
||||
await this.SelectBoxes(opt);
|
||||
break;
|
||||
}
|
||||
else if (ptRes.StringResult === "A")
|
||||
{
|
||||
//TODO:未完善功能
|
||||
await this.DrawInALlBoxes(opt);
|
||||
break;
|
||||
}
|
||||
else if (ptRes.StringResult === "U")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!store.isContinuous)
|
||||
{
|
||||
app.m_Editor.m_ModalManage.RenderBoardModal(store, type);
|
||||
let state = await store.GetBoardOption();
|
||||
if (state !== ModalState.Ok) break;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*获取鼠标点周围的板
|
||||
* @private
|
||||
* @param {Vector3} mousePt
|
||||
* @param {Viewer} view
|
||||
* @param {Board[]} brs
|
||||
* @memberof DrawLayerBoard
|
||||
*/
|
||||
private getPtSurroundBoardsByMouse(mousePt: Vector3, view: Viewer, brs: Board[])
|
||||
{
|
||||
let { vMeshs, lMeshs } = this.getMeshs(view);
|
||||
//获取上下左右的板
|
||||
const getBoard = (pt: Vector2, objs: Object3D[], type: string) =>
|
||||
{
|
||||
let sl = new SelectLine(view, Vec3DTo2D(mousePt), pt);
|
||||
sl.Select(objs);
|
||||
this.selectSurroundBoard(sl.Enlity as Board[], type, brs)
|
||||
}
|
||||
|
||||
let leftPt = Vec3DTo2D(mousePt).setX(0);
|
||||
getBoard(leftPt, vMeshs, "left");
|
||||
|
||||
let rightPt = Vec3DTo2D(mousePt).setX(view.Width);
|
||||
getBoard(rightPt, vMeshs, "right");
|
||||
|
||||
let topPt = Vec3DTo2D(mousePt).setY(0);
|
||||
getBoard(topPt, lMeshs, "top");
|
||||
|
||||
let bottomPt = Vec3DTo2D(mousePt).setY(view.Height);
|
||||
getBoard(bottomPt, lMeshs, "bottom")
|
||||
|
||||
}
|
||||
private getPtSurroundBoardsByPick(en: { pickObj: Object3D, intersect: any }, view: Viewer, brs: Board[])
|
||||
{
|
||||
let { vMeshs, lMeshs } = this.getMeshs(view);
|
||||
let ro = new Matrix4().extractRotation(en.intersect.object.matrix);
|
||||
let normal = en.intersect.face.normal.clone() as Vector3;
|
||||
let leftDir = new Vector3().setX(normal.z);
|
||||
let topDir = new Vector3().setY(normal.z)
|
||||
|
||||
normal.applyMatrix4(ro);
|
||||
leftDir.applyMatrix4(ro);
|
||||
topDir.applyMatrix4(ro);
|
||||
|
||||
let origin = en.intersect.point as Vector3;
|
||||
let leftRay = new Raycaster(origin, leftDir);
|
||||
let rightRay = new Raycaster(origin, leftDir.clone().negate());
|
||||
//原点往法向量方向偏移一点,保证相交
|
||||
let fuzzVec = normal.clone().multiplyScalar(1e-3);
|
||||
let topRay = new Raycaster(origin.clone().add(fuzzVec), topDir);
|
||||
let bottomRay = new Raycaster(origin.clone().add(fuzzVec), topDir.clone().negate());
|
||||
|
||||
const getBoard = (ray, meshs) =>
|
||||
{
|
||||
let ints = ray.intersectObjects(meshs, false);
|
||||
if (ints.length > 0)
|
||||
{
|
||||
brs.push(ints[0].object.userData)
|
||||
}
|
||||
}
|
||||
getBoard(leftRay, vMeshs);
|
||||
getBoard(rightRay, vMeshs);
|
||||
getBoard(topRay, lMeshs);
|
||||
getBoard(bottomRay, lMeshs);
|
||||
|
||||
return { normal, origin };
|
||||
}
|
||||
private getMeshs(view: Viewer)
|
||||
{
|
||||
let meshs = view.Scene.children.filter(o => o instanceof Mesh && o.userData && o.userData instanceof Board);
|
||||
let vMeshs = meshs.filter(o => (<Board>o.userData).BoardType === BoardType.Vertical);
|
||||
let lMeshs = meshs.filter(o => (<Board>o.userData).BoardType === BoardType.Layer);
|
||||
return { vMeshs, lMeshs }
|
||||
}
|
||||
private selectSurroundBoard(ens: Board[], dir: string, brs: Board[])
|
||||
{
|
||||
if (ens.length === 0) return;
|
||||
|
||||
let boxMap: Map<Board, Vector3> = new Map();
|
||||
ens.forEach(b =>
|
||||
{
|
||||
let pt = b.MinPoint;
|
||||
app.m_Viewer.WorldToScreen(pt);
|
||||
boxMap.set(b, pt);
|
||||
})
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case "left":
|
||||
ens.sort((a, b) => boxMap.get(b).x - boxMap.get(a).x);
|
||||
break;
|
||||
case "right":
|
||||
ens.sort((a, b) => boxMap.get(a).x - boxMap.get(b).x);
|
||||
break;
|
||||
case "top":
|
||||
ens.sort((a, b) => boxMap.get(b).y - boxMap.get(a).y);
|
||||
break;
|
||||
case "bottom":
|
||||
ens.sort((a, b) => boxMap.get(a).y - boxMap.get(b).y);
|
||||
break;
|
||||
}
|
||||
|
||||
let en = ens[0];
|
||||
if (en && !brs.includes(en))
|
||||
{
|
||||
brs.push(en)
|
||||
}
|
||||
}
|
||||
private async SelectBoxes(opt: BoardOption)
|
||||
{
|
||||
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[];
|
||||
|
||||
if (boardCus.length > 0)
|
||||
{
|
||||
let spaceParse = new GeneralSpaceParse(boardCus);
|
||||
await spaceParse.SpaceParse();
|
||||
|
||||
if (spaceParse.Spaces.length === 0)
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("生成层板失败");
|
||||
return;
|
||||
}
|
||||
let ro = new Matrix4().extractRotation(spaceParse.OCS);
|
||||
|
||||
let spaces = spaceParse.Spaces;
|
||||
let box = await this.selectBox(spaces);
|
||||
|
||||
this.buildBoard(box, opt, ro);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("请选择板件")
|
||||
}
|
||||
}
|
||||
private async DrawInALlBoxes(opt: BoardOption)
|
||||
{
|
||||
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[];
|
||||
|
||||
if (boardCus.length > 0)
|
||||
{
|
||||
let spaceParse = new GeneralSpaceParse2(boardCus);
|
||||
spaceParse.SpaceParse();
|
||||
|
||||
if (spaceParse.Spaces.length === 0)
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("生成层板失败");
|
||||
return;
|
||||
}
|
||||
let ro = new Matrix4().extractRotation(spaceParse.OCS);
|
||||
|
||||
let spaces = spaceParse.Spaces;
|
||||
for (let box of spaces)
|
||||
{
|
||||
this.buildBoard(box, opt, ro);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("请选择板件")
|
||||
}
|
||||
}
|
||||
|
||||
private pointPick(ptVcs: Vector3, view: Viewer)
|
||||
{
|
||||
let selectObjects = view.Scene.children;
|
||||
|
||||
selectObjects = selectObjects.filter(o => o instanceof Mesh && o.userData && o.userData instanceof Board);
|
||||
|
||||
let raycaster = new Raycaster();
|
||||
raycaster.setFromCamera({
|
||||
x: (ptVcs.x / view.Width) * 2 - 1,
|
||||
y: - (ptVcs.y / view.Height) * 2 + 1
|
||||
}, view.Camera);
|
||||
raycaster.ray.origin.sub(raycaster.ray.direction.clone().multiplyScalar(1e3));
|
||||
|
||||
let pickObj: Object3D;
|
||||
let minDis: number;
|
||||
let intersect;
|
||||
for (let obj of selectObjects)
|
||||
{
|
||||
let intersects = [];
|
||||
if (!obj.visible) continue;
|
||||
obj.raycast(raycaster, intersects)
|
||||
if (intersects.length > 0)
|
||||
if (!minDis || minDis > intersects[0].distance)
|
||||
{
|
||||
pickObj = obj;
|
||||
minDis = intersects[0].distance
|
||||
intersect = intersects[0];
|
||||
}
|
||||
}
|
||||
return { pickObj, intersect };
|
||||
}
|
||||
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 KeyWordList = [{ key: "3", msg: "靠前" }, { key: "4", msg: "靠后" }];
|
||||
let tmpPar1 = spaces[0].min.y;
|
||||
let tmpPar2 = spaces[1].min.y;
|
||||
|
||||
if (spaces[0].min.y === spaces[1].min.y)
|
||||
{
|
||||
KeyWordList = [{ key: "3", msg: "靠左" }, { key: "4", msg: "靠右" }];
|
||||
tmpPar1 = spaces[0].min.x;
|
||||
tmpPar2 = spaces[1].min.x;
|
||||
}
|
||||
let keyWord = await app.m_Editor.GetKeyWords({
|
||||
Msg: "输入位置:",
|
||||
KeyWordList
|
||||
});
|
||||
if (keyWord.StringResult == "3")
|
||||
{
|
||||
tmpPar1 < tmpPar2 ? spaces.pop() : spaces.shift();
|
||||
}
|
||||
else if (keyWord.StringResult == "4")
|
||||
{
|
||||
tmpPar1 > tmpPar2 ? 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];
|
||||
}
|
||||
//构建板件
|
||||
protected buildBoard(box: Box3Ext, opt: BoardOption, ro: Matrix4)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,475 +1,20 @@
|
||||
import { Matrix4, Mesh, Object3D, Ray, Raycaster, Vector2, Vector3 } from 'three';
|
||||
import { Vector3 } from 'three';
|
||||
|
||||
import { app } from '../../ApplicationServices/Application';
|
||||
import { arrayRemoveIf } from '../../Common/ArrayExt';
|
||||
import { Vec3DTo2D } from '../../Common/CurveUtils';
|
||||
import { Board, BoardType } from '../../DatabaseServices/Board';
|
||||
import { Command } from '../../Editor/CommandMachine';
|
||||
import { PromptStatus } from '../../Editor/PromptResult';
|
||||
import { SelectLine } from '../../Editor/SelectBox';
|
||||
import { Box3Ext } from '../../Geometry/Box';
|
||||
import { equaln } from '../../Geometry/GeUtils';
|
||||
import { GeneralSpaceParse, GeneralSpaceParse2 } from '../../Geometry/SpaceParse/GeneralSpaceParse';
|
||||
import { Viewer } from '../../GraphicsSystem/Viewer';
|
||||
import { MoveMatrix } from '../../Geometry/GeUtils';
|
||||
import { BoardModalType } from '../../UI/Components/Board/BoardModal';
|
||||
import { BehindBoardStore, LayerBoardStore, VerticalBoardStore, BoardStore } from '../../UI/Store/BoardStore';
|
||||
import { ModalState, BoardOption } from '../../UI/Store/BoardInterface';
|
||||
import { SideBoardStore, SingleBoardStore } from '../../UI/Store/BoardStore';
|
||||
import { ModalState } from '../../UI/Store/BoardInterface';
|
||||
|
||||
|
||||
export abstract class DrawSingleBoard implements Command
|
||||
export class DrawSingleBoard implements Command
|
||||
{
|
||||
//画板件类型,默认画层板
|
||||
protected drawType = BoardType.Layer;
|
||||
async exec()
|
||||
{
|
||||
//原来禁用捕捉开启状态
|
||||
let oldSnapState = app.m_Editor.m_GetpointServices.snapServices.m_Disabled;
|
||||
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = true;
|
||||
|
||||
let store: LayerBoardStore | VerticalBoardStore | BehindBoardStore;
|
||||
let modalType: BoardModalType;
|
||||
switch (this.drawType)
|
||||
{
|
||||
case BoardType.Layer:
|
||||
store = LayerBoardStore.Store();
|
||||
modalType = BoardModalType.Ly;
|
||||
break;
|
||||
case BoardType.Vertical:
|
||||
store = VerticalBoardStore.Store();
|
||||
modalType = BoardModalType.Ve;
|
||||
break;
|
||||
case BoardType.Behind:
|
||||
store = BehindBoardStore.Store();
|
||||
modalType = BoardModalType.Be;
|
||||
|
||||
}
|
||||
app.m_Editor.m_ModalManage.RenderBoardModal(store, modalType);
|
||||
|
||||
let state = await store.GetBoardOption();
|
||||
|
||||
if (state !== ModalState.Ok)
|
||||
return;
|
||||
|
||||
await this.SelectPoint(store, modalType)
|
||||
|
||||
//恢复原先状态
|
||||
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = oldSnapState;
|
||||
}
|
||||
private async SelectPoint(store: BoardStore, type: BoardModalType)
|
||||
{
|
||||
// 板件数据
|
||||
let opt = store.m_BoardOption;
|
||||
|
||||
let view = app.m_Viewer;
|
||||
|
||||
while (true)
|
||||
{
|
||||
let ptRes = await app.m_Editor.GetPoint({
|
||||
Msg: "点选画板区域",
|
||||
KeyWordList: [{ msg: "框选", key: "S" }, { msg: "全选", key: "A" }, { msg: "放弃", key: "U" }]
|
||||
});
|
||||
|
||||
if (ptRes.Status === PromptStatus.OK)
|
||||
{
|
||||
let brs: Board[] = [];
|
||||
|
||||
let mousePt = ptRes.Value.clone();
|
||||
|
||||
view.WorldToScreen(mousePt);
|
||||
|
||||
//是否选到背板
|
||||
let en = this.pointPick(mousePt, view);
|
||||
//选中面法向量
|
||||
let normal: Vector3;
|
||||
//鼠标在面上的交点
|
||||
let origin: Vector3;
|
||||
if (en.pickObj && (<Board>en.pickObj.userData).BoardType === BoardType.Behind)
|
||||
{
|
||||
brs.push(en.pickObj.userData);
|
||||
let res = this.getPtSurroundBoardsByPick(en, view, brs);
|
||||
normal = res.normal;
|
||||
origin = res.origin;
|
||||
}
|
||||
else
|
||||
{
|
||||
//选择上下左右的板
|
||||
this.getPtSurroundBoardsByMouse(mousePt, view, brs);
|
||||
}
|
||||
//分析点周围的空间
|
||||
if (brs.length > 1)
|
||||
{
|
||||
let spaceParse = new GeneralSpaceParse(brs);
|
||||
await spaceParse.SpaceParse();
|
||||
|
||||
if (spaceParse.Spaces.length === 0)
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("生成b板件失败,没分析出有效空间");
|
||||
continue;
|
||||
}
|
||||
|
||||
//柜子旋转矩阵
|
||||
let ro = new Matrix4().extractRotation(spaceParse.OCS);
|
||||
|
||||
//存在的空间
|
||||
let spaces = spaceParse.Spaces;
|
||||
|
||||
if (spaces.length > 1)
|
||||
{
|
||||
let ray: Ray;
|
||||
//构造射线,取和射线相交的空间
|
||||
if (normal)
|
||||
{
|
||||
ray = new Ray(origin, normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
let raycaster = new Raycaster();
|
||||
raycaster.setFromCamera({
|
||||
x: (mousePt.x / view.Width) * 2 - 1,
|
||||
y: - (mousePt.y / view.Height) * 2 + 1
|
||||
}, view.Camera);
|
||||
ray = raycaster.ray;
|
||||
ray.origin.sub(raycaster.ray.direction.clone().multiplyScalar(1e3));
|
||||
}
|
||||
arrayRemoveIf(spaces, box =>
|
||||
{
|
||||
let b = box.clone().applyMatrix4(ro);
|
||||
return !Boolean(ray.intersectBox(b, new Vector3()))
|
||||
});
|
||||
}
|
||||
if (spaces.length > 0)
|
||||
{
|
||||
let box = spaces[0];
|
||||
this.buildBoard(box, opt, ro);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("请选择有效的板件,或者周围没有效板件");
|
||||
}
|
||||
|
||||
}
|
||||
else if (ptRes.Status === PromptStatus.Keyword)
|
||||
{
|
||||
if (ptRes.StringResult === "S")
|
||||
{
|
||||
await this.SelectBoxes(opt);
|
||||
break;
|
||||
}
|
||||
else if (ptRes.StringResult === "A")
|
||||
{
|
||||
//TODO:未完善功能
|
||||
await this.DrawInALlBoxes(opt);
|
||||
break;
|
||||
}
|
||||
else if (ptRes.StringResult === "U")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!store.isContinuous)
|
||||
{
|
||||
app.m_Editor.m_ModalManage.RenderBoardModal(store, type);
|
||||
let state = await store.GetBoardOption();
|
||||
if (state !== ModalState.Ok) break;
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*获取鼠标点周围的板
|
||||
* @private
|
||||
* @param {Vector3} mousePt
|
||||
* @param {Viewer} view
|
||||
* @param {Board[]} brs
|
||||
* @memberof DrawLayerBoard
|
||||
*/
|
||||
private getPtSurroundBoardsByMouse(mousePt: Vector3, view: Viewer, brs: Board[])
|
||||
{
|
||||
let { vMeshs, lMeshs } = this.getMeshs(view);
|
||||
//获取上下左右的板
|
||||
const getBoard = (pt: Vector2, objs: Object3D[], type: string) =>
|
||||
{
|
||||
let sl = new SelectLine(view, Vec3DTo2D(mousePt), pt);
|
||||
sl.Select(objs);
|
||||
this.selectSurroundBoard(sl.Enlity as Board[], type, brs)
|
||||
}
|
||||
|
||||
let leftPt = Vec3DTo2D(mousePt).setX(0);
|
||||
getBoard(leftPt, vMeshs, "left");
|
||||
|
||||
let rightPt = Vec3DTo2D(mousePt).setX(view.Width);
|
||||
getBoard(rightPt, vMeshs, "right");
|
||||
|
||||
let topPt = Vec3DTo2D(mousePt).setY(0);
|
||||
getBoard(topPt, lMeshs, "top");
|
||||
|
||||
let bottomPt = Vec3DTo2D(mousePt).setY(view.Height);
|
||||
getBoard(bottomPt, lMeshs, "bottom")
|
||||
|
||||
}
|
||||
private getPtSurroundBoardsByPick(en: { pickObj: Object3D, intersect: any }, view: Viewer, brs: Board[])
|
||||
{
|
||||
let { vMeshs, lMeshs } = this.getMeshs(view);
|
||||
let ro = new Matrix4().extractRotation(en.intersect.object.matrix);
|
||||
let normal = en.intersect.face.normal.clone() as Vector3;
|
||||
let leftDir = new Vector3().setX(normal.z);
|
||||
let topDir = new Vector3().setY(normal.z)
|
||||
|
||||
normal.applyMatrix4(ro);
|
||||
leftDir.applyMatrix4(ro);
|
||||
topDir.applyMatrix4(ro);
|
||||
|
||||
let origin = en.intersect.point as Vector3;
|
||||
let leftRay = new Raycaster(origin, leftDir);
|
||||
let rightRay = new Raycaster(origin, leftDir.clone().negate());
|
||||
//原点往法向量方向偏移一点,保证相交
|
||||
let fuzzVec = normal.clone().multiplyScalar(1e-3);
|
||||
let topRay = new Raycaster(origin.clone().add(fuzzVec), topDir);
|
||||
let bottomRay = new Raycaster(origin.clone().add(fuzzVec), topDir.clone().negate());
|
||||
|
||||
const getBoard = (ray, meshs) =>
|
||||
{
|
||||
let ints = ray.intersectObjects(meshs, false);
|
||||
if (ints.length > 0)
|
||||
{
|
||||
brs.push(ints[0].object.userData)
|
||||
}
|
||||
}
|
||||
getBoard(leftRay, vMeshs);
|
||||
getBoard(rightRay, vMeshs);
|
||||
getBoard(topRay, lMeshs);
|
||||
getBoard(bottomRay, lMeshs);
|
||||
|
||||
return { normal, origin };
|
||||
}
|
||||
private getMeshs(view: Viewer)
|
||||
{
|
||||
let meshs = view.Scene.children.filter(o => o instanceof Mesh && o.userData && o.userData instanceof Board);
|
||||
let vMeshs = meshs.filter(o => (<Board>o.userData).BoardType === BoardType.Vertical);
|
||||
let lMeshs = meshs.filter(o => (<Board>o.userData).BoardType === BoardType.Layer);
|
||||
return { vMeshs, lMeshs }
|
||||
}
|
||||
private selectSurroundBoard(ens: Board[], dir: string, brs: Board[])
|
||||
{
|
||||
if (ens.length === 0) return;
|
||||
|
||||
let boxMap: Map<Board, Vector3> = new Map();
|
||||
ens.forEach(b =>
|
||||
{
|
||||
let pt = b.MinPoint;
|
||||
app.m_Viewer.WorldToScreen(pt);
|
||||
boxMap.set(b, pt);
|
||||
})
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case "left":
|
||||
ens.sort((a, b) => boxMap.get(b).x - boxMap.get(a).x);
|
||||
break;
|
||||
case "right":
|
||||
ens.sort((a, b) => boxMap.get(a).x - boxMap.get(b).x);
|
||||
break;
|
||||
case "top":
|
||||
ens.sort((a, b) => boxMap.get(b).y - boxMap.get(a).y);
|
||||
break;
|
||||
case "bottom":
|
||||
ens.sort((a, b) => boxMap.get(a).y - boxMap.get(b).y);
|
||||
break;
|
||||
}
|
||||
|
||||
let en = ens[0];
|
||||
if (en && !brs.includes(en))
|
||||
{
|
||||
brs.push(en)
|
||||
}
|
||||
}
|
||||
private async SelectBoxes(opt: BoardOption)
|
||||
{
|
||||
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[];
|
||||
|
||||
if (boardCus.length > 0)
|
||||
{
|
||||
let spaceParse = new GeneralSpaceParse(boardCus);
|
||||
await spaceParse.SpaceParse();
|
||||
|
||||
if (spaceParse.Spaces.length === 0)
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("生成层板失败");
|
||||
return;
|
||||
}
|
||||
let ro = new Matrix4().extractRotation(spaceParse.OCS);
|
||||
|
||||
let spaces = spaceParse.Spaces;
|
||||
let box = await this.selectBox(spaces);
|
||||
|
||||
this.buildBoard(box, opt, ro);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("请选择板件")
|
||||
}
|
||||
}
|
||||
private async DrawInALlBoxes(opt: BoardOption)
|
||||
{
|
||||
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[];
|
||||
|
||||
if (boardCus.length > 0)
|
||||
{
|
||||
let spaceParse = new GeneralSpaceParse2(boardCus);
|
||||
spaceParse.SpaceParse();
|
||||
|
||||
if (spaceParse.Spaces.length === 0)
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("生成层板失败");
|
||||
return;
|
||||
}
|
||||
let ro = new Matrix4().extractRotation(spaceParse.OCS);
|
||||
|
||||
let spaces = spaceParse.Spaces;
|
||||
for (let box of spaces)
|
||||
{
|
||||
this.buildBoard(box, opt, ro);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("请选择板件")
|
||||
}
|
||||
}
|
||||
|
||||
private pointPick(ptVcs: Vector3, view: Viewer)
|
||||
{
|
||||
let selectObjects = view.Scene.children;
|
||||
|
||||
selectObjects = selectObjects.filter(o => o instanceof Mesh && o.userData && o.userData instanceof Board);
|
||||
|
||||
let raycaster = new Raycaster();
|
||||
raycaster.setFromCamera({
|
||||
x: (ptVcs.x / view.Width) * 2 - 1,
|
||||
y: - (ptVcs.y / view.Height) * 2 + 1
|
||||
}, view.Camera);
|
||||
raycaster.ray.origin.sub(raycaster.ray.direction.clone().multiplyScalar(1e3));
|
||||
|
||||
let pickObj: Object3D;
|
||||
let minDis: number;
|
||||
let intersect;
|
||||
for (let obj of selectObjects)
|
||||
{
|
||||
let intersects = [];
|
||||
if (!obj.visible) continue;
|
||||
obj.raycast(raycaster, intersects)
|
||||
if (intersects.length > 0)
|
||||
if (!minDis || minDis > intersects[0].distance)
|
||||
{
|
||||
pickObj = obj;
|
||||
minDis = intersects[0].distance
|
||||
intersect = intersects[0];
|
||||
}
|
||||
}
|
||||
return { pickObj, intersect };
|
||||
}
|
||||
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 KeyWordList = [{ key: "3", msg: "靠前" }, { key: "4", msg: "靠后" }];
|
||||
let tmpPar1 = spaces[0].min.y;
|
||||
let tmpPar2 = spaces[1].min.y;
|
||||
|
||||
if (spaces[0].min.y === spaces[1].min.y)
|
||||
{
|
||||
KeyWordList = [{ key: "3", msg: "靠左" }, { key: "4", msg: "靠右" }];
|
||||
tmpPar1 = spaces[0].min.x;
|
||||
tmpPar2 = spaces[1].min.x;
|
||||
}
|
||||
let keyWord = await app.m_Editor.GetKeyWords({
|
||||
Msg: "输入位置:",
|
||||
KeyWordList
|
||||
});
|
||||
if (keyWord.StringResult == "3")
|
||||
{
|
||||
tmpPar1 < tmpPar2 ? spaces.pop() : spaces.shift();
|
||||
}
|
||||
else if (keyWord.StringResult == "4")
|
||||
{
|
||||
tmpPar1 > tmpPar2 ? 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];
|
||||
}
|
||||
//构建板件
|
||||
protected buildBoard(box: Box3Ext, opt: BoardOption, ro: Matrix4)
|
||||
{
|
||||
|
||||
let store = SingleBoardStore.Store();
|
||||
app.m_Editor.m_ModalManage.RenderBoardModal(store, BoardModalType.Sg);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
import { observer } from "../../../../node_modules/mobx-react";
|
||||
import * as React from 'react';
|
||||
import { SingleBoardStore } from "../../Store/BoardStore";
|
||||
|
||||
export const SingleBoardModal =
|
||||
(observer((props: { store?: SingleBoardStore }) =>
|
||||
{
|
||||
let pars = new Map([["height", "柜高"], ["width", "柜深"], ["thickness", "板厚"], ["spaceSize", "总宽"]]);
|
||||
return (
|
||||
<div>
|
||||
<label className="bp3-label bp3-inline .modifier">
|
||||
<span>纹路</span>
|
||||
<div className="bp3-select bp3-inline .modifier">
|
||||
<select>
|
||||
<option value="0">正纹</option>
|
||||
<option value="1">反纹</option>
|
||||
<option value="1">可翻转</option>
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
}));
|
Loading…
Reference in new issue