增加点选画层板功能

pull/93/head
Zoe 6 years ago
parent 007611db7b
commit c5c46139ce

@ -1,4 +1,4 @@
import { Vector3, Matrix4, Raycaster } from 'three';
import { Vector3, Matrix4, Raycaster, Vector2, Mesh } from 'three';
import { app } from '../../ApplicationServices/Application';
import { Board, BoardType } from '../../DatabaseServices/Board';
import { Command } from '../../Editor/CommandMachine';
@ -8,38 +8,20 @@ import { GeneralSpaceParse } from '../../Geometry/SpaceParse/GeneralSpaceParse';
import { LayerBoardStore, ModalState, LayerPosType, LayerBoardOption } from '../../UI/Store/BoardStore';
import { BoardModalType } from '../../UI/Components/Board/BoardModal';
import { Box3Ext } from '../../Geometry/Box';
import { SelectSet } from '../../Editor/SelectSet';
import { SelectLine } from '../../Editor/SelectBox';
import { Vec3DTo2D } from '../../Common/CurveUtils';
import { SortEntityByBox } from '../../Geometry/SortEntityByBox';
import { PointPick } from '../../Editor/PointPick';
export class DrawLayerBoard implements Command
{
async exec()
{
this.SelectBoards();
// await this.SelectBoxes();
await this.SelectPoint();
}
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)
@ -119,27 +101,133 @@ export class DrawLayerBoard implements Command
}
return spaces[0];
}
async PointSelect()
async SelectPoint()
{
let ptRes = await app.m_Editor.GetPoint({ Msg: "点选画板区域" });
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = true;
let store = LayerBoardStore.Store();
app.m_Editor.m_ModalManage.RenderBoardModal(store, BoardModalType.Ly);
let state = await store.GetBoardOption();
if (state !== ModalState.Ok)
return;
let view = app.m_Viewer;
if (ptRes.Status !== PromptStatus.Cancel)
while (true)
{
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));
let ptRes = await app.m_Editor.GetPoint({ Msg: "点选画板区域" });
let meshs = view.Scene.children.filter(o => o instanceof Mesh);
if (ptRes.Status !== PromptStatus.Cancel)
{
let brs: Board[] = [];
let br: Board;
let startPt = ptRes.Value.clone();
view.WorldToScreen(startPt);
//是否选到背板
let en = PointPick(startPt, view).map(o =>
{
if (o.userData && o.userData instanceof Board && o.userData.BoardType === BoardType.Behind)
return o.userData
});
if (en && en.length > 0)
{
brs.push(en[0])
}
//选择上下左右的板
let leftPt = Vec3DTo2D(startPt).setX(0);
let sl = new SelectLine(view, Vec3DTo2D(startPt), leftPt);
sl.Select(meshs);
br = this.selectFitBoard(sl.Enlity.filter(b => b instanceof Board && b.BoardType === BoardType.Vertical) as Board[], "left")
br && brs.push(br);
let rightPt = Vec3DTo2D(startPt).setX(view.Width);
sl = new SelectLine(view, Vec3DTo2D(startPt), rightPt);
sl.Select(meshs);
br = this.selectFitBoard(sl.Enlity.filter(b => b instanceof Board && b.BoardType === BoardType.Vertical) as Board[], "right")
br && brs.push(br);
let topPt = Vec3DTo2D(startPt).setY(0);
sl = new SelectLine(view, Vec3DTo2D(startPt), topPt);
sl.Select(meshs);
br = this.selectFitBoard(sl.Enlity.filter(b => b instanceof Board && b.BoardType === BoardType.Layer) as Board[], "top")
br && brs.push(br);
let bottomPt = Vec3DTo2D(startPt).setY(view.Height);
sl = new SelectLine(view, Vec3DTo2D(startPt), bottomPt);
sl.Select(meshs);
br = this.selectFitBoard(sl.Enlity.filter(b => b instanceof Board && b.BoardType === BoardType.Layer) as Board[], "bottom")
br && brs.push(br);
//分析点周围的空间
if (brs.length > 0)
{
let spaceParse = new GeneralSpaceParse(brs);
spaceParse.SpaceParse();
if (spaceParse.Spaces.length === 0)
{
app.m_Editor.m_CommandStore.Prompt("生成层板失败");
continue;
}
let opt = store.layerBoardOption;
let ro = new Matrix4().extractRotation(spaceParse.OCS);
let spaces = spaceParse.Spaces;
if (spaces.length > 1)
{
spaces.sort((b1, b2) =>
{
return b1.min.y - b2.min.y;
});
}
let box = spaces[0];
this.buildBoard(box, opt, ro);
}
else
{
app.m_Editor.m_CommandStore.Prompt("请选择板件");
}
} else break;
}
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = false;
}
selectFitBoard(brs: Board[], dir: string)
{
if (brs.length === 0) return;
async SelectBoards()
let boxMap: Map<Board, Vector3> = new Map();
brs.forEach(b =>
{
let pt = b.MinPoint;
app.m_Viewer.WorldToScreen(pt);
boxMap.set(b, pt);
})
switch (dir)
{
case "left":
brs.sort((a, b) => boxMap.get(b).x - boxMap.get(a).x);
return brs[0];
case "right":
brs.sort((a, b) => boxMap.get(a).x - boxMap.get(b).x);
return brs[0];
case "top":
brs.sort((a, b) => boxMap.get(b).y - boxMap.get(a).y);
return brs[0];
case "bottom":
brs.sort((a, b) => boxMap.get(a).y - boxMap.get(b).y);
return brs[0];
}
}
async SelectBoxes()
{
let exSsRes = await app.m_Editor.GetSelection({ Msg: "请选择对象<全部选择>:", UseSelect: true });
if (exSsRes.Status === PromptStatus.Cancel)
@ -183,4 +271,28 @@ export class DrawLayerBoard implements Command
app.m_Editor.m_CommandStore.Prompt("请选择板件")
}
}
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);
}
}
}

@ -1,24 +0,0 @@
import { Command } from "../Editor/CommandMachine";
import { app } from "../ApplicationServices/Application";
import { PromptStatus } from "../Editor/PromptResult";
import { Line } from "../DatabaseServices/Line";
export class Command_TestBox implements Command
{
async exec()
{
let ss = await app.m_Editor.GetSelection();
if (ss.Status != PromptStatus.OK)
return;
for (let en of ss.SelectSet.SelectEntityList)
{
let box = en.BoundingBox;
let line = new Line(box.min, box.max);
app.m_Database.ModelSpace.Append(line);
}
}
}

@ -0,0 +1,50 @@
import { Command } from "../../Editor/CommandMachine";
import { app } from "../../ApplicationServices/Application";
import { PromptStatus } from "../../Editor/PromptResult";
import { Line } from "../../DatabaseServices/Line";
import { SelectLine, SelectBox } from "../../Editor/SelectBox";
import { Vec3DTo2D } from "../../Common/CurveUtils";
import { SelectSet } from "../../Editor/SelectSet";
export class Command_TestBox implements Command
{
async exec()
{
// let ss = await app.m_Editor.GetSelection();
// if (ss.Status != PromptStatus.OK)
// return;
// for (let en of ss.SelectSet.SelectEntityList)
// {
// let box = en.BoundingBox;
// let line = new Line(box.min, box.max);
// app.m_Database.ModelSpace.Append(line);
// }
let ptRes = await app.m_Editor.GetPoint({ Msg: "选择点" })
if (ptRes.Status !== PromptStatus.OK)
return;
let pt1 = ptRes.Value.clone();
app.m_Viewer.WorldToScreen(pt1);
ptRes = await app.m_Editor.GetPoint({
Msg: "选择其他点",
BasePoint: ptRes.Value,
AllowDrawRubberBand: true,
Callback: (v) =>
{
let sss = new SelectSet();
let pt = v.clone();
app.m_Viewer.WorldToScreen(pt);
let sl = new SelectLine(app.m_Viewer, Vec3DTo2D(pt1), Vec3DTo2D(pt.clone()))
sl.Select();
sss.AddSelect(sl);
console.log(sss.SelectEntityList);
}
})
}
}

@ -1,6 +1,6 @@
import { app } from "../ApplicationServices/Application";
import { Board } from "../DatabaseServices/Board";
import { Command } from "../Editor/CommandMachine";
import { app } from "../../ApplicationServices/Application";
import { Board } from "../../DatabaseServices/Board";
import { Command } from "../../Editor/CommandMachine";
export class Command_DrawBoard2 implements Command

@ -1,6 +1,6 @@
import { Command } from "../Editor/CommandMachine";
import { DirectionalLight } from "../DatabaseServices/DirectionalLight";
import { app } from "../ApplicationServices/Application";
import { Command } from "../../Editor/CommandMachine";
import { DirectionalLight } from "../../DatabaseServices/DirectionalLight";
import { app } from "../../ApplicationServices/Application";
/**
*

@ -1,6 +1,6 @@
import { Command } from '../Editor/CommandMachine';
import { PointLight } from '../DatabaseServices/PointLight';
import { app } from '../ApplicationServices/Application';
import { Command } from '../../Editor/CommandMachine';
import { PointLight } from '../../DatabaseServices/PointLight';
import { app } from '../../ApplicationServices/Application';
export class TestDrawPointLight implements Command

@ -1,6 +1,6 @@
import { Command } from "../Editor/CommandMachine";
import { SpotLight } from "../DatabaseServices/SpotLight";
import { app } from "../ApplicationServices/Application";
import { Command } from "../../Editor/CommandMachine";
import { SpotLight } from "../../DatabaseServices/SpotLight";
import { app } from "../../ApplicationServices/Application";
import { Matrix4 } from "three";
/**
*

@ -1,12 +1,12 @@
import { Matrix4, Vector3 } from 'three';
import { app } from '../ApplicationServices/Application';
import { matrixAlignCoordSys } from '../Common/Matrix4Utils';
import { Board } from '../DatabaseServices/Board';
import { Polyline } from '../DatabaseServices/Polyline';
import { Region } from '../DatabaseServices/Region';
import { Command } from "../Editor/CommandMachine";
import { PromptStatus } from "../Editor/PromptResult";
import { MoveMatrix } from '../Geometry/GeUtils';
import { app } from '../../ApplicationServices/Application';
import { matrixAlignCoordSys } from '../../Common/Matrix4Utils';
import { Board } from '../../DatabaseServices/Board';
import { Polyline } from '../../DatabaseServices/Polyline';
import { Region } from '../../DatabaseServices/Region';
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { MoveMatrix } from '../../Geometry/GeUtils';

@ -3,7 +3,7 @@ import { Box3, EllipseCurve, Geometry, Object3D, Vector3 } from 'three';
import { arrayLast, arrayRemoveDuplicateBySort } from '../Common/ArrayExt';
import { ColorMaterial } from '../Common/ColorPalette';
import { clamp } from '../Common/Utils';
import { Arc } from '../DatabaseServices/Arc';
import { Arc } from './Arc'
import { MoveMatrix, angle, equaln, polar } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum';
import { IntersectCircleAndArc, IntersectCircleAndCircle, IntersectLineAndCircle, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith';

@ -51,11 +51,11 @@ import { Command_SwitchPass } from '../Add-on/SwitchPass';
// import { DrawFloor } from '../Add-on/DrawFloor';
// import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
import { TestIntersect } from '../Add-on/test/testIntersect';
import { Command_TestBox } from '../Add-on/TestBox';
import { Command_DrawBoard2 } from '../Add-on/TestDrawBoard';
import { TestDrawDirectionalLight } from '../Add-on/TestDrawDirectionalLight';
import { TestDrawPointLight } from '../Add-on/TestDrawPointLight';
import { TestDrawSpotLight } from '../Add-on/TestDrawSpotLight';
import { Command_TestBox } from '../Add-on/testEntity/TestBox';
import { Command_DrawBoard2 } from '../Add-on/testEntity/TestDrawBoard';
import { TestDrawDirectionalLight } from '../Add-on/testEntity/TestDrawDirectionalLight';
import { TestDrawPointLight } from '../Add-on/testEntity/TestDrawPointLight';
import { TestDrawSpotLight } from '../Add-on/testEntity/TestDrawSpotLight';
import { TestTargeOnCurve } from '../Add-on/testEntity/TestCurve';
import { Command_Trim } from '../Add-on/Trim';
import { Redo, Undo } from '../Add-on/Undo';

@ -23,7 +23,7 @@ export class SelectBox extends SelectSetBase
private m_SelectBox: THREE.Box2 = new THREE.Box2();
private m_RectLines: Line[] = [];
private m_Frustom: THREE.Frustum = new THREE.Frustum();
private m_Frustum: THREE.Frustum = new THREE.Frustum();
private m_bIsPerCamera;
@ -58,7 +58,7 @@ export class SelectBox extends SelectSetBase
let _projScreenMatrix = new THREE.Matrix4();
_projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
this.m_Frustom.setFromMatrix(_projScreenMatrix);
this.m_Frustum.setFromMatrix(_projScreenMatrix);
camera.clearViewOffset();
}
@ -94,14 +94,14 @@ export class SelectBox extends SelectSetBase
continue;
if (obj.hasOwnProperty("geometry"))
{
if (this.m_Frustom.intersectsObject(obj) && CheckFunction(obj))
if (this.m_Frustum.intersectsObject(obj) && CheckFunction(obj))
this.m_SelectList.push(obj);
}
else if (obj instanceof THREE.Group)
{
for (let ob of obj.children)
{
if (this.m_Frustom.intersectsObject(ob) && CheckFunction(ob))
if (this.m_Frustum.intersectsObject(ob) && CheckFunction(ob))
{
this.m_SelectList.push(obj);
break;
@ -128,7 +128,7 @@ export class SelectBox extends SelectSetBase
{
if (!obj.visible) return false;
if (obj.hasOwnProperty("geometry"))
return this.m_Frustom.intersectsObject(obj);
return this.m_Frustum.intersectsObject(obj);
return true;
}
@ -142,7 +142,7 @@ export class SelectBox extends SelectSetBase
//如果是透视相机,则需要 裁剪算法. 保证线在视图内部
if (this.m_bIsPerCamera)
{
let nearPlan = this.m_Frustom.planes[5];
let nearPlan = this.m_Frustum.planes[5];
let px1 = worldPts[index1];
let px2 = worldPts[index2];
@ -241,3 +241,111 @@ export class SelectBox extends SelectSetBase
return this.m_SelectBox.containsPoint(new THREE.Vector2(ptVcs.x, ptVcs.y));
}
}
export class SelectLine extends SelectSetBase
{
private m_Line;
constructor(view: Viewer | PreViewer, p1: THREE.Vector2, p2: THREE.Vector2)
{
super(view);
this.m_Line = new Line(Vec2DTo3D(p1), Vec2DTo3D(p2));
}
get Enlity()
{
let ens: Entity[] = [];
for (let obj of this.m_SelectList)
{
if (obj.userData && obj.userData instanceof Entity)
{
ens.push(obj.userData)
}
}
return ens;
}
/**
* . ().
*
* @memberof SelectBox
*/
Select(selectList?: Object3D[])
{
selectList = selectList || this.m_Viewer.Scene.children;
let CheckFunction = (obj) => this.IntersectObject(obj);
for (let obj of selectList)
{
if (!obj.visible || obj instanceof GripScene || !obj.userData)
continue;
if (obj.hasOwnProperty("geometry"))
{
if (CheckFunction(obj))
this.m_SelectList.push(obj);
}
else if (obj instanceof THREE.Group)
{
for (let ob of obj.children)
{
if (CheckFunction(ob))
{
this.m_SelectList.push(obj);
break;
}
}
}
}
}
//判断直接是否和选择线相交.该算法包含了投影裁剪线算法.
IntersectLine(index1: number, index2: number, screenPts: Array<THREE.Vector3>, worldPts: Array<THREE.Vector3>)
{
let p1 = screenPts[index1];
let p2 = screenPts[index2];
let line = new Line(p1.clone(), p2.clone());
let ins = this.m_Line.IntersectWith(line, IntersectOption.OnBothOperands);
if (ins.length > 0)
return true;
return false;
}
IntersectObject(obj: THREE.Object3D): Boolean
{
let { pts, faces } = this.GetObjectVertices(obj);
//转为为屏幕点
let screenPts = new Array<THREE.Vector3>();
for (let pt of pts)
{
let p = pt.clone();
this.WorldToScreenPoint(p);
p.z = 0;
screenPts.push(p);
}
if (faces.length == 0)
{
for (let index = 0; index < pts.length - 1; index++)
{
if (this.IntersectLine(index, index + 1, screenPts, pts))
return true;
}
}
else
{
for (let face of faces)
{
if (
this.IntersectLine(face.a, face.b, screenPts, pts) ||
this.IntersectLine(face.b, face.c, screenPts, pts) ||
this.IntersectLine(face.c, face.a, screenPts, pts))
{
return true;
}
}
}
for (let c of obj.children)
if (this.IntersectObject(c))
return true;
return false;
}
}

@ -1,6 +1,6 @@
import * as THREE from 'three';
import { ColorMaterial } from './../../Common/ColorPalette';
import { ColorMaterial } from '../../Common/ColorPalette';
import { AxisType } from './CoorAxes';
//构造一个旋转轴 ,供旋转变换控制器,或者其他地方使用

@ -12,7 +12,7 @@ import { Editor } from '../Editor';
import { PointPick } from '../PointPick';
import { PromptStatus } from '../PromptResult';
import { MatrixToPreViewMat } from '../UCSServices';
import { EditorService } from './../Editor';
import { EditorService } from '../Editor';
import { AxisType } from './CoorAxes';
import { RotateAxes } from './RotateAxes';
import { TranslateAxex } from './TranslateAxes';

@ -44,11 +44,15 @@ export class GeneralSpaceParse extends SpaceParse
spliteBoxes.push(box);
}
}
this.SpliteBoxs(this.MergeSpaces(unionBoxes) as Box3Ext, spliteBoxes);
let spaces = this.MergeSpaces(unionBoxes) as Box3Ext;
spaces && this.SpliteBoxs(spaces, spliteBoxes);
}
private MergeSpaces(spaces: Box3Ext[])
{
if (spaces.length === 0) return undefined;
let b1 = spaces.shift();
let isInt = false;
for (let box of spaces)
@ -84,6 +88,7 @@ export class GeneralSpaceParse extends SpaceParse
let box = boxes[i];
for (let j = 0; j < spliteBoxes.length; j++)
{
if (!box) debugger;
let bs = box.substract(spliteBoxes[j]);
if (bs.length > 0)
{
@ -174,7 +179,7 @@ export class GeneralSpaceParse extends SpaceParse
let b2 = arrayLast(boards);
let box2 = boxMap.get(b2).clone();
let box = this.parseBox3(box1, box2, b1.BoardType)
let box = this.parseBox3(box1, box2, b1.BoardType);
if (!box.isEmpty())
{
uniSpaces.push(box);

@ -43,14 +43,16 @@ export class BoardModal extends React.Component<BoardModalProps, {}> {
return (
<Dialog
autoFocus={true}
iconName="inbox"
isOpen={true}
onClose={() => store.OnOk(ModalState.Cancel)}
canOutsideClickClose={false}
canEscapeKeyClose={true}
enforceFocus={false}
enforceFocus={true}
title={store.title}
>
<div
className="pt-dialog-body"
onKeyDown={e =>

@ -1,7 +1,7 @@
import { inject, observer } from 'mobx-react';
import * as React from 'react';
import { LayerBoardStore, LayerPosType } from '../../Store/BoardStore';
import { Checkbox, RadioGroup, Radio } from '../../../../node_modules/@blueprintjs/core';
import { Checkbox, RadioGroup, Radio } from '@blueprintjs/core';
@inject("store")
@observer

@ -1,6 +1,6 @@
import { inject, observer } from 'mobx-react';
import * as React from 'react';
import { Checkbox, Radio, RadioGroup } from '../../../../node_modules/@blueprintjs/core';
import { Checkbox, Radio, RadioGroup } from '@blueprintjs/core';
import { LayerPosType, VerticalBoardStore, VerticalPosType } from '../../Store/BoardStore';
@inject("store")

@ -27,14 +27,14 @@ window.onload = function ()
//-----热模块替换的代码.
async function loadFirst()
{
let cmd = (await import("./Add-on/test")).Test;
let cmd = (await import("./Add-on/testEntity/test")).Test;
commandMachine.RegisterCommand("tt", new cmd());
}
loadFirst();//必须先加载一次,否则无法触发热模块替换
if (module.hot)
{
module.hot.accept('./Add-on/test', loadFirst)
module.hot.accept('./Add-on/testEntity/test', loadFirst)
}
};

Loading…
Cancel
Save