!728 实现可视化空间布局

pull/728/MERGE
ChenX 5 years ago
parent 613c40d091
commit efa7d71f94

@ -8,15 +8,25 @@
" ReadFile(file: CADFiler)",
" {",
" let ver = file.Read();",
" super.Read(file);",
" }",
"",
" //对象从文件中读取数据,初始化自身",
" protected _ReadFile(file: CADFiler)",
" {",
" let ver = file.Read();",
" super._ReadFile(file);",
" }",
" //对象将自身数据写入到文件.",
" WriteFile(file: CADFiler)",
" {",
" file.Write(1);",
" super.Write(file);",
" }",
" //局部撤销",
" ApplyPartialUndo(undoData: CADObject)",
" {",
" super.ApplyPartialUndo(undoData);",
" }",
" //#endregion"
]

@ -21,7 +21,7 @@
"license": "ISC",
"devDependencies": {
"@types/html-webpack-plugin": "^3.2.2",
"@types/jest": "^25.1.1",
"@types/jest": "^25.1.2",
"@types/node": "^13.7.0",
"@types/pako": "^1.0.1",
"@types/react": "^16.9.19",
@ -29,7 +29,7 @@
"@types/react-dom": "^16.9.5",
"@types/stats.js": "^0.17.0",
"@types/terser-webpack-plugin": "^2.2.0",
"@types/webpack": "^4.41.4",
"@types/webpack": "^4.41.5",
"@types/webpack-dev-server": "^3.10.0",
"@types/webpack-env": "^1.15.1",
"@types/webpack-merge": "^4.1.5",
@ -60,7 +60,7 @@
"source-map-loader": "^0.2.4",
"style-loader": "^1.1.3",
"terser-webpack-plugin": "^2.3.4",
"ts-jest": "^25.1.0",
"ts-jest": "^25.2.0",
"ts-loader": "^6.2.1",
"ts-node": "^8.6.2",
"tsconfig-paths": "^3.9.0",
@ -69,7 +69,7 @@
"wallaby-webpack": "^3.9.15",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.2",
"webpack-dev-server": "^3.10.3",
"webpack-merge": "^4.2.2",
"worker-loader": "^2.0.0"
},
@ -80,7 +80,7 @@
"golden-layout": "^1.5.9",
"js-angusj-clipper": "^1.0.4",
"mobx": "^5.15.4",
"mobx-react": "^6.1.4",
"mobx-react": "^6.1.7",
"monotone-convex-hull-2d": "^1.0.1",
"p-queue": "^6.2.1",
"pako": "^1.0.11",

@ -1,8 +1,10 @@
import { Vector3 } from 'three';
import { app } from '../ApplicationServices/Application';
import { Entity } from '../DatabaseServices/Entity/Entity';
import { Line } from '../DatabaseServices/Entity/Line';
import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult';
import { VisualSpaceBox } from '../Editor/VisualSpaceBox';
import { DynamicInputManage } from '../UI/DynamicPrompt/DynamicInputManage';
import { PromptBlock } from '../UI/DynamicPrompt/PromptBlock';
@ -28,6 +30,61 @@ export class Entsel implements Command
dyn.UpdatePrompt(`模版:${res.Entity.Template.Index}`);
else
dyn.UpdatePrompt(`null`);
if (res.Entity instanceof VisualSpaceBox)
{
let vbox = res.Entity as VisualSpaceBox;
let [l, w, h] = [vbox.Length, vbox.Width, vbox.Height];
let pts = [
new Vector3(),//0
new Vector3(l),//x 1
new Vector3(l, w),// 2
new Vector3(0, w, 0),//y 3
new Vector3(0, 0, h),//z 4
new Vector3(l, 0, h),//5
new Vector3(l, w, h),//6
new Vector3(0, w, h),//7
];
let lines = [
[0, 1],
[0, 3],
[0, 4],
[3, 2],
[1, 2],
[1, 5],
[4, 5],
[4, 7],
[2, 6],
[7, 6],
[5, 6],
[3, 7],
];
let cs = vbox.OCS;
let dcs = app.Viewer.DCS;
for (let p of pts)
p.applyMatrix4(cs).applyMatrix4(dcs);
let vcs = app.Editor.MouseCtrl.m_CurMousePointVCS;
let line = new Line();
let dists = lines.map((p1p2: number[]) =>
{
let [p1, p2] = p1p2.map(i => pts[i]);
line.StartPoint = p1;
line.EndPoint = p2;
return line.GetClosestPointTo(vcs, true).distanceTo(vcs);
});
let index = dists.indexOf(Math.min(...dists)) % 3;
dyn.UpdatePrompt(`猜测鼠标在${["长", "宽", "高"][index]}轴上`);
}
}
else
dyn.Visible = false;

@ -8,7 +8,6 @@ import { HotCMD } from "../Hot/HotCommand";
import { CURRENT_HOST } from "../Common/HostUrl";
import { Region } from "../DatabaseServices/Entity/Region";
@HotCMD
export class Command_ExportView implements Command
{
async exec()

@ -1,6 +1,8 @@
import { Euler, Matrix4, Vector2, Vector3 } from "three";
import { app } from "../ApplicationServices/Application";
import { arrayLast } from "../Common/ArrayExt";
import { EBoardKeyList } from "../Common/BoardKeyList";
import { safeEval } from "../Common/eval";
import { FileSystem } from "../Common/FileSystem";
import { JigMoveEntity } from "../Common/JigMove";
import { FixIndex, ToFixed } from "../Common/Utils";
@ -9,15 +11,12 @@ import { ExtrudeSolid } from "../DatabaseServices/Entity/Extrude";
import { Polyline, PolylineProps } from "../DatabaseServices/Entity/Polyline";
import { TemplateRecord } from "../DatabaseServices/Template/TemplateRecord";
import { Command, CommandWrap } from "../Editor/CommandMachine";
import { userConfig } from "../Editor/UserConfig";
import { Vec2 } from "../Geometry/CheckIntersect";
import { AsVector2, equaln, equalv2, isParallelTo, XAxis } from "../Geometry/GeUtils";
import { AsVector2, equaln, equalv2 } from "../Geometry/GeUtils";
import { Vec3 } from "../Geometry/IVec3";
import { HotCMD } from "../Hot/HotCommand";
import { FaceDirection, LinesType, IHighSealedItem } from "../UI/Store/BoardInterface";
import { ParagraphSealinglist, HandleRectBoardSealingData } from "../GraphicsSystem/CalcEdgeSealing";
import { arrayLast } from "../Common/ArrayExt";
import { userConfig } from "../Editor/UserConfig";
import { safeEval } from "../Common/eval";
import { HandleRectBoardSealingData, ParagraphSealinglist } from "../GraphicsSystem/CalcEdgeSealing";
import { FaceDirection, IHighSealedItem, LinesType } from "../UI/Store/BoardInterface";
/** 模型类型 */
enum KJL_ModelType
@ -118,7 +117,6 @@ class FuzzPoint
}
}
@HotCMD
export class Command_KJLImport implements Command
{
async exec()

@ -3,11 +3,9 @@ import { Curve } from "../DatabaseServices/Entity/Curve";
import { Polyline } from "../DatabaseServices/Entity/Polyline";
import { Command } from "../Editor/CommandMachine";
import { PromptStatus } from "../Editor/PromptResult";
import { HotCMD } from "../Hot/HotCommand";
import { TestDraw } from "./test/TestUtil";
//无限内偏移
@HotCMD
export class OffsetX implements Command
{
offsetDis: number = 1;

@ -1,7 +1,9 @@
import { Object3D, Scene, Vector3 } from "three";
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer";
import { app } from "../ApplicationServices/Application";
import { DisposeThreeObj } from "../Common/Dispose";
import { Sleep } from "../Common/Sleep";
import { Hole } from "../DatabaseServices/3DSolid/Hole";
import { CADFiler } from "../DatabaseServices/CADFiler";
import { AlignedDimension } from "../DatabaseServices/Dimension/AlignedDimension";
import { Board } from "../DatabaseServices/Entity/Board";
@ -11,12 +13,7 @@ import { PromptStatus } from "../Editor/PromptResult";
import { userConfig } from "../Editor/UserConfig";
import { isParallelTo, XAxis, YAxis } from "../Geometry/GeUtils";
import { RenderType } from "../GraphicsSystem/RenderType";
import { AAType } from "../GraphicsSystem/Viewer";
import { HotCMD } from "../Hot/HotCommand";
import { DisposeThreeObj } from "../Common/Dispose";
import { Hole } from "../DatabaseServices/3DSolid/Hole";
@HotCMD
export class Print implements Command
{
async exec()

@ -1,8 +1,6 @@
import { app } from "../ApplicationServices/Application";
import { arrayRemoveIf } from "../Common/ArrayExt";
import { HotCMD } from "../Hot/HotCommand";
@HotCMD
export class Command_Purge
{
async exec()

@ -0,0 +1,139 @@
import { Matrix4 } from "three";
import { app } from "../../ApplicationServices/Application";
import { Log } from "../../Common/Log";
import { TemplateVisualSpace } from "../../DatabaseServices/Template/ProgramTempate/TemplateVisualSpace";
import { TemplateRecord } from "../../DatabaseServices/Template/TemplateRecord";
import { SelectTempate } from "../../DatabaseServices/Template/TemplateTest";
import { PromptStatus } from "../../Editor/PromptResult";
import { CoordinateSystem } from "../../Geometry/CoordinateSystem";
import { getEulerAngle, isPerpendicularityTo } from "../../Geometry/GeUtils";
import { HotCMD } from "../../Hot/HotCommand";
import { AppToaster } from "../../UI/Components/Toaster";
@HotCMD
export class Command_RotateTemplateSpace
{
async exec()
{
let t = await SelectTempate();
if (!t) return;
if (t.Parent?.Object?.IsErase !== false)
{
Log("顶层模块使用Rotate命令直接旋转!");
return;
}
let cs = await GetSpaceCSFrom3Point();
if (!cs) return;
let isNoPos = t.PXParam.value === 0 && t.PYParam.value === 0 && t.PZParam.value === 0;
let parent = t.Parent.Object as TemplateRecord;
if (parent.Children.length === 1 && isNoPos)
{
let tcs = parent.GetTemplateSpaceCS(true);
let tcsInv = new Matrix4().getInverse(tcs);
cs.multiply(tcsInv);
let cds = new CoordinateSystem().CopyForm(cs);
let ro = getEulerAngle(cds.XAxis, cds.YAxis, cds.ZAxis);
t.RXParam.expr = ro.roX;
t.RYParam.expr = ro.roY;
t.RZParam.expr = ro.roZ;
}
else
{
let tcs = t.GetTemplateSpaceCS(true);
let tcsInv = new Matrix4().getInverse(tcs);
cs.multiply(tcsInv);
let cds = new CoordinateSystem().CopyForm(cs);
let ro = getEulerAngle(cds.XAxis, cds.YAxis, cds.ZAxis);
//判断子层空间是否被旋转过,如果是,那么直接修改子层空间
if (t.Children.length === 1)
{
let ct = t.Children[0].Object as TemplateRecord;
if (ct instanceof TemplateVisualSpace)
{
ct.LParam.expr = "_L";
ct.WParam.expr = "_W";
ct.HParam.expr = "_H";
ct.RXParam.expr = ro.roX;
ct.RYParam.expr = ro.roY;
ct.RZParam.expr = ro.roZ;
await t.UpdateTemplateTree();
return;
}
}
let nt = new TemplateVisualSpace().InitBaseParams();
nt.Name = "旋转空间";
nt.LParam.expr = "_L";
nt.WParam.expr = "_W";
nt.HParam.expr = "_H";
nt.RXParam.expr = ro.roX;
nt.RYParam.expr = ro.roY;
nt.RZParam.expr = ro.roZ;
//如果有子层空间,那么移植到下一层
nt.Children.push(...t.Children);
t.Children.length = 0;
app.Database.TemplateTable.Append(nt);
t.Children.push(nt.Id);
await t.UpdateTemplateTree();
}
}
}
//拾取一个基点2个轴方向确定空间姿态
async function GetSpaceCSFrom3Point(): Promise<Matrix4 | undefined>
{
let ptRes = await app.Editor.GetPoint({
Msg: "选择基点"
});
if (ptRes.Status !== PromptStatus.OK)
return;
let basePt = ptRes.Point;
let xRes = await app.Editor.GetPoint({
Msg: "选择长度方向终点(x轴):",
BasePoint: basePt,
AllowDrawRubberBand: true,
});
if (ptRes.Status !== PromptStatus.OK)
return;
let xVec = xRes.Point.sub(basePt).normalize();
let zRes = await app.Editor.GetPoint({
Msg: "选择高度方向终点(Z轴):",
BasePoint: basePt,
AllowDrawRubberBand: true,
});
if (ptRes.Status !== PromptStatus.OK)
return;
let zVec = zRes.Point.sub(basePt).normalize();
let yVec = zVec.clone().cross(xVec);
if (!isPerpendicularityTo(xVec, zVec))
{
AppToaster.show({
message: "x轴和z轴必须垂直!",
timeout: 2000
});
return;
}
return new Matrix4().makeBasis(xVec, yVec, zVec);
}

@ -0,0 +1,50 @@
import { app } from "../../ApplicationServices/Application";
import { TemplateVisualSpace } from "../../DatabaseServices/Template/ProgramTempate/TemplateVisualSpace";
import { SelectTempate } from "../../DatabaseServices/Template/TemplateTest";
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { HotCMD } from "../../Hot/HotCommand";
@HotCMD
export class Command_SplitTemplate implements Command
{
async exec()
{
let t = await SelectTempate();
if (t === undefined) return;
if (t.Children.length === 0)
{
let typeRes = await app.Editor.GetKeyWords({
KeyWordList: [
{ msg: "X", key: "1" },
{ msg: "Y", key: "2" },
{ msg: "Z", key: "3" },
]
});
if (typeRes.Status !== PromptStatus.Keyword) return;
let countRes = await app.Editor.GetDistance({ Msg: "个数" });
if (countRes.Status !== PromptStatus.OK || countRes.Distance < 1) return;
t.SplitType = parseInt(typeRes.StringResult) - 1;
for (let i = 0; i < countRes.Distance; i++)
{
let tc = new TemplateVisualSpace().InitBaseParams();
tc.LParam.expr = "_L";
tc.WParam.expr = "_W";
tc.HParam.expr = "_H";
tc.Params[t.SplitType].expr = "_DIV";
tc.Params[3 + t.SplitType].expr = "_POS";
app.Database.TemplateTable.Append(tc);
t.Children.push(tc.Id);
}
await t.UpdateTemplateTree();
}
}
}

@ -4,10 +4,8 @@ import { Board } from "../../DatabaseServices/Entity/Board";
import { Line } from "../../DatabaseServices/Entity/Line";
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { HotCMD } from "../../Hot/HotCommand";
import { TestDraw } from "../test/TestUtil";
@HotCMD
export class Command_TestDrawEdgeGeometry implements Command
{
async exec()

@ -6,7 +6,6 @@ import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { HotCMD } from "../../Hot/HotCommand";
@HotCMD
export class TestFillet implements Command
{
async exec()

@ -6,7 +6,6 @@ import { SelectTempate } from "../../DatabaseServices/Template/TemplateTest";
import { Command, commandMachine } from "../../Editor/CommandMachine";
import { HotCMD } from "../../Hot/HotCommand";
@HotCMD
export class Command_DeleteTemplate implements Command
{
async exec()
@ -17,7 +16,6 @@ export class Command_DeleteTemplate implements Command
}
}
@HotCMD
export class Command_Template2Tree implements Command
{
async exec()

@ -1,32 +1,51 @@
import { HotCMD } from "../../Hot/HotCommand";
import { Command } from "../../Editor/CommandMachine";
import { app } from "../../ApplicationServices/Application";
import { PromptStatus } from "../../Editor/PromptResult";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Production } from "../../Production/Product";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Matrix4 } from "three";
import { ParagraphSealinglist } from "../../GraphicsSystem/CalcEdgeSealing";
import { Curve } from "../../DatabaseServices/Entity/Curve";
import { IHighSealedItem } from "../../UI/Store/BoardInterface";
import { TemplateVisualSpace } from "../../DatabaseServices/Template/ProgramTempate/TemplateVisualSpace";
import { Command } from "../../Editor/CommandMachine";
import { HotCMD } from "../../Hot/HotCommand";
import { TemplateSplitType } from "../../DatabaseServices/Template/TemplateType";
@HotCMD
export class Test implements Command
{
async exec()
{
let enRes = await app.Editor.GetSelection({});
if (enRes.Status === PromptStatus.OK)
{
let en = enRes.SelectSet.SelectEntityList;
// let ent = new VisualSpaceBox(1000, 1000, 1000);
// TestDraw(ent);
let template = new TemplateVisualSpace();
template.InitBaseParams();
template.LParam.expr = 2000;
template.HParam.expr = 1800;
template.WParam.expr = 600;
app.Database.TemplateTable.Append(template);
for (let e of en)
if (true)
{
await template.UpdateTemplateTree();
return;
};
let t = template;
if (t.Children.length === 0)
{
t.SplitType = TemplateSplitType.X;
for (let i = 0; i < 3; i++)
{
// if (e.IsClockWise) e.ColorIndex = 1;
if (e instanceof Board)
console.log(Production.GetBoardSplitOrderData(e));
let tc = new TemplateVisualSpace().InitBaseParams();
tc.LParam.expr = "_DIV";
tc.WParam.expr = "_W";
tc.HParam.expr = "_H";
tc.PXParam.expr = "_POS";
app.Database.TemplateTable.Append(tc);
t.Children.push(tc.Id);
}
await t.UpdateTemplateTree();
}
await template.UpdateTemplateTree();
}
}

@ -326,6 +326,17 @@ export class ColorMaterial
return mat;
}
private static _BasicTransparentMaterialMap2: Map<string, MeshBasicMaterial> = new Map();
static GetBasicMaterialTransparent2(color: number, opacity: number)
{
let key = `${color},${opacity}`;
let mat = this._BasicTransparentMaterialMap2.get(key);
if (mat) return mat;
mat = new MeshBasicMaterial({ transparent: true, opacity: opacity });
this._BasicTransparentMaterialMap2.set(key, mat);
return mat;
}
static GetColor(color: number)
{
let rgb = ColorPalette[color];

@ -6,7 +6,6 @@ import { EBoardKeyList } from '../../Common/BoardKeyList';
import { UpdateDraw } from '../../Common/Status';
import { userConfig } from '../../Editor/UserConfig';
import { boardUVGenerator, boardUVGenerator2 } from '../../Geometry/BoardUVGenerator';
import { Box3Ext } from '../../Geometry/Box';
import { equaln, MoveMatrix } from '../../Geometry/GeUtils';
import { BoardProcessOption, ComposingType, FaceDirection, LinesType } from '../../UI/Store/BoardInterface';
import { Factory } from '../CADFactory';

@ -6,7 +6,7 @@ import { RenderType } from "../../GraphicsSystem/RenderType";
let boxGeo: BoxBufferGeometry;
function getBoxGeoBufferGeometry()
export function GetBoxGeoBufferGeometry()
{
if (!boxGeo)
boxGeo = new BoxBufferGeometry(1, 1, 1);
@ -24,13 +24,17 @@ export class BoxSolid extends Entity
}
set Opacity(o: number)
{
this._opacity = o;
this.Update();
if (o !== this._opacity)
{
this.WriteAllObjectRecord();
this._opacity = o;
this.Update();
}
}
InitDrawObject(renderType: RenderType = RenderType.Wireframe)
{
let box = new Object3D();
let geo = getBoxGeoBufferGeometry();
let geo = GetBoxGeoBufferGeometry();
let mat = ColorMaterial.GetBasicMaterialTransparent(7, this._opacity);
box.add(new Mesh(geo, mat));
this.UpdateDrawObject(renderType, box);

@ -3,7 +3,7 @@ import { arrayClone, arrayLast, arrayRemoveIf, arraySortByNumber, arraySum } fro
import { ColorMaterial } from "../../Common/ColorPalette";
import { equalCurve } from "../../Common/CurveUtils";
import { DisposeThreeObj } from "../../Common/Dispose";
import { Vector2ApplyMatrix4, matrixSetVector } from "../../Common/Matrix4Utils";
import { matrixSetVector, Vector2ApplyMatrix4 } from "../../Common/Matrix4Utils";
import { Status, UpdateDraw } from "../../Common/Status";
import { CSG } from "../../csg/core/CSG";
import { CSG2Geometry, Geometry2CSG } from "../../csg/core/Geometry2CSG";
@ -13,7 +13,8 @@ import { Box3Ext } from "../../Geometry/Box";
import { BSPGroupParse } from "../../Geometry/BSPGroupParse";
import { FastWireframe } from "../../Geometry/CreateWireframe";
import { EdgesGeometry } from "../../Geometry/EdgeGeometry";
import { equaln, equalv2, equalv3, isIntersect, isParallelTo, MoveMatrix, ZeroVec, IdentityMtx4 } from "../../Geometry/GeUtils";
import { GenerateExtrudeEdgeGeometry } from "../../Geometry/ExtrudeEdgeGeometry";
import { AsVector3, equaln, equalv2, equalv3, IdentityMtx4, isIntersect, isParallelTo, MoveMatrix, ZeroVec } from "../../Geometry/GeUtils";
import { OBB } from "../../Geometry/OBB/obb";
import { ScaleUV } from "../../Geometry/UVUtils";
import { RenderType } from "../../GraphicsSystem/RenderType";
@ -1144,6 +1145,9 @@ export class ExtrudeSolid extends Entity
{
if (this._EdgeGeometry)
return this._EdgeGeometry;
if (this.grooves.length === 0)
return GenerateExtrudeEdgeGeometry(this.contourCurve.Shape.getPoints(6).map(AsVector3), this.thickness).applyMatrix4(this.contourCurve.OCS);
this.MeshGeometry;
this._EdgeGeometry = new EdgesGeometry().FromCSG(this.CSG);
return this._EdgeGeometry;
@ -1338,7 +1342,7 @@ export class ExtrudeSolid extends Entity
//#endregion
}
function FastMeshGeometry(width: number, height: number, thickness: number)
export function FastMeshGeometry(width: number, height: number, thickness: number)
{
let geo = new BoxGeometry(width, height, thickness);
geo.translate(width * 0.5, height * 0.5, thickness * 0.5);

@ -0,0 +1,70 @@
import { CADFiler } from "../../CADFiler";
import { TemplateRecord } from "../TemplateRecord";
import { AutoRecord } from "../../AutoRecord";
import { VisualSpaceBox } from "../../../Editor/VisualSpaceBox";
import { app } from "../../../ApplicationServices/Application";
import { Factory } from "../../CADFactory";
@Factory
export class TemplateVisualSpace extends TemplateRecord
{
@AutoRecord IsVisible = true;
constructor()
{
super();
this.Name = "可视化模块空间";
}
protected async Update()
{
await super.Update();
if (this.Objects.length === 0 || this.Objects[0].Object === undefined)
{
this.Objects.length = 0;
let visualEntity = new VisualSpaceBox(this.LParam.value as number, this.WParam.value as number, this.HParam.value as number);
visualEntity.ApplyMatrix(this._CacheSpaceCS);
visualEntity.SpaceOCS = this._CacheSpaceCS;
app.Database.ModelSpace.Append(visualEntity);
this.Objects.push(visualEntity.Id);
}
let visualEntity = this.Objects[0].Object as VisualSpaceBox;
let IsRoot = this.Parent === undefined;
let isVisual = IsRoot || this.Children.length === 0;
visualEntity.Visible = this.IsVisible && isVisual;
visualEntity.SetSize(this.LParam.value as number, this.WParam.value as number, this.HParam.value as number);
visualEntity.IsRoot = this.Children.length !== 0;
if (!IsRoot)
{
let root = this.Root;
visualEntity.DisplayLength = this.LParam.value !== root.LParam.value;
visualEntity.DisplayWidth = this.WParam.value !== root.WParam.value;
visualEntity.DisplayHeight = this.HParam.value !== root.HParam.value;
}
}
//#region -------------------------File-------------------------
//对象从文件中读取数据,初始化自身
ReadFile(file: CADFiler)
{
let ver = file.Read();
super.ReadFile(file);
this.IsVisible = file.Read();
}
//对象将自身数据写入到文件.
WriteFile(file: CADFiler)
{
file.Write(1);
super.WriteFile(file);
file.Write(this.IsVisible);
}
// //局部撤销
// ApplyPartialUndo(undoData: CADObject)
// {
// super.ApplyPartialUndo(undoData);
// }
//#endregion
}

@ -1073,3 +1073,19 @@ export function RemoveTemplate(temp: TemplateRecord)
(id.Object as Entity).Template = null;
temp.Children.length = 0;
}
/**新模块替换旧模块 */
export function ReplaceTemplate(oldTemp: TemplateRecord, newTemp: TemplateRecord)
{
for (let i = 0; i < 9; i++)
{
newTemp.Params[i].expr = oldTemp.Params[i].expr;
}
newTemp.Positioning = oldTemp.Positioning;
if (oldTemp.Parent)
{
let t = oldTemp.Parent.Object as TemplateRecord;
let index = t.Children.indexOf(oldTemp.Id);
t.Children[index] = newTemp.Id;
}
}

@ -171,6 +171,7 @@ export class TemplateRecord extends SymbolTableRecord
*/
set Positioning(p: Positioning)
{
if (!p) return;
this.WriteAllObjectRecord();
p.parent = this;
this._Positioning = p;

@ -123,9 +123,11 @@ import { Sweep } from "../Add-on/Sweep";
import { Command_SwitchCamera } from "../Add-on/SwitchCamera";
import { CMD_Conceptual, CMD_Physical, CMD_Wireframe } from "../Add-on/SwitchVisualStyles";
import { DrawTangentLine } from "../Add-on/Tangent";
import { Command_RotateTemplateSpace } from "../Add-on/Template/RotateTemplateSpace";
import { ShowTemplate } from "../Add-on/Template/ShowTemplate";
import { ShowTemplateDesign } from "../Add-on/Template/ShowTemplateDesign";
import { ShowTopLine } from "../Add-on/Template/ShowTopline";
import { Command_SplitTemplate } from "../Add-on/Template/SplitTemplate";
import { Command_TemplateSearch } from "../Add-on/TemplateSearch";
// import { DrawFloor } from '../Add-on/DrawFloor';
// import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
@ -390,11 +392,14 @@ export function registerCommand()
//绘制复合实体
commandMachine.RegisterCommand("combine", new Command_CombineEntity());
//Template
commandMachine.RegisterCommand("template", new ShowTemplate());
commandMachine.RegisterCommand("templatedesign", new ShowTemplateDesign());
commandMachine.RegisterCommand("TemplateSearch", new Command_TemplateSearch());
commandMachine.RegisterCommand("templateDelete", new Command_DeleteTemplate());
commandMachine.RegisterCommand("templatecheck", new Command_TemplateSearch(true));
commandMachine.RegisterCommand("SplitTemplate", new Command_SplitTemplate());
commandMachine.RegisterCommand("RotateTemplateSpace", new Command_RotateTemplateSpace());
//优化算法
commandMachine.RegisterCommand("testNFP", new Command_TestNFP());

@ -0,0 +1,390 @@
import { BufferGeometry, Float32BufferAttribute, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Vector3, Box3 } from "three";
import { ColorMaterial } from "../Common/ColorPalette";
import { FixedNotZero } from "../Common/Utils";
import { AutoRecord } from "../DatabaseServices/AutoRecord";
import { Factory } from "../DatabaseServices/CADFactory";
import { CADFiler } from "../DatabaseServices/CADFiler";
import { Entity } from "../DatabaseServices/Entity/Entity";
import { TemplateRecord } from "../DatabaseServices/Template/TemplateRecord";
import { Text, TextAligen } from "../DatabaseServices/Text/Text";
import { GenerateBoxEdgeGeometry } from "../Geometry/ExtrudeEdgeGeometry";
import { XAxis, XAxisN, YAxis, YAxisN, ZAxis, ZeroVec } from "../Geometry/GeUtils";
import { RenderType } from "../GraphicsSystem/RenderType";
import { ObjectSnapMode } from "./ObjectSnapMode";
import { Box3Ext } from "../Geometry/Box";
const EmptyArray = [];
@Factory
export class VisualSpaceBox extends Entity
{
OnlyRenderType = true;
private _LText = new Text;
private _WText = new Text;
private _HText = new Text;
@AutoRecord private _IsRoot = false;
@AutoRecord private _DisplayLength = true;
@AutoRecord private _DisplayWidth = true;
@AutoRecord private _DisplayHeight = true;
constructor(
protected _Length: number = 1,
protected _Width: number = 1,
protected _Height: number = 1,
)
{
super();
this._LText.IsEmbedEntity = true;
this._WText.IsEmbedEntity = true;
this._HText.IsEmbedEntity = true;
this._LText.TextAligen = TextAligen.Down;
this._WText.TextAligen = TextAligen.Top;
this._HText.TextAligen = TextAligen.Top;
(<VisualSpaceBox><unknown>this._LText)._Matrix.makeBasis(XAxis, ZAxis, YAxis);
(<VisualSpaceBox><unknown>this._WText)._Matrix.makeBasis(YAxis, XAxisN, ZAxis);
(<VisualSpaceBox><unknown>this._HText)._Matrix.makeBasis(ZAxis, XAxisN, YAxisN);
}
get Length() { return this._Length; }
get Width() { return this._Width; }
get Height() { return this._Height; }
set IsRoot(b: boolean)
{
if (this._IsRoot !== b)
{
this._IsRoot = b;
for (let [, obj] of this._CacheDrawObject)
{
let [box, edge, lobj, wobj, hobj] = obj.children;
if (this._IsRoot)
box.visible = false;
if (this._IsRoot)
{
this._LText.TextAligen = TextAligen.Top;
this._WText.TextAligen = TextAligen.Down;
this._HText.TextAligen = TextAligen.Down;
}
else
{
this._LText.TextAligen = TextAligen.Down;
this._WText.TextAligen = TextAligen.Top;
this._HText.TextAligen = TextAligen.Top;
}
}
}
}
set DisplayWidth(b: boolean)
{
for (let [, obj] of this._CacheDrawObject)
{
let [box, edge, lobj, wobj, hobj] = obj.children;
wobj.visible = b;
}
this._DisplayWidth = b;
}
set DisplayLength(b: boolean)
{
for (let [, obj] of this._CacheDrawObject)
{
let [box, edge, lobj, wobj, hobj] = obj.children;
lobj.visible = b;
}
this._DisplayLength = b;
}
set DisplayHeight(b: boolean)
{
for (let [, obj] of this._CacheDrawObject)
{
let [box, edge, lobj, wobj, hobj] = obj.children;
hobj.visible = b;
}
this._DisplayHeight = b;
}
SetSize(l: number, w: number, h: number)
{
if (l !== this._Length || w !== this._Width || h !== this._Height)
{
this.WriteAllObjectRecord();
this._Length = l;
this._Width = w;
this._Height = h;
this.Update();
}
}
get BoundingBoxInOCS()
{
return new Box3Ext(new Vector3, new Vector3(this._Length, this._Width, this._Height));
}
//#region 捕捉
/**
*
* @param snapMode ()
* @param pickPoint const
* @param lastPoint const
* @param viewXform const
* @returns object snap points
*/
GetObjectSnapPoints(
snapMode: ObjectSnapMode,
pickPoint: Vector3,
lastPoint: Vector3,
viewXform?: Matrix3
): Vector3[]
{
switch (snapMode)
{
case ObjectSnapMode.End:
{
let pts: Vector3[] = [
new Vector3(),
new Vector3(this._Length),
new Vector3(this._Length, this._Width),
new Vector3(0, this._Width),
new Vector3(0, 0, this._Height),
new Vector3(this._Length, 0, this._Height),
new Vector3(this._Length, this._Width, this._Height),
new Vector3(0, this._Width, this._Height),
];
for (let p of pts)
p.applyMatrix4(this._Matrix);
return pts;
}
}
return EmptyArray;
}
//#endregion
//#region Draw
InitDrawObject(renderType: RenderType = RenderType.Wireframe)
{
let obj = new Object3D();
//box
let mat = ColorMaterial.GetBasicMaterialTransparent2(7, 0.5);
obj.add(new Mesh(backGeo, mat));
//edge
obj.add(new LineSegments(edgeGeo, ColorMaterial.GetLineMaterial(7)));
obj.add(this._LText.DrawObject);
obj.add(this._WText.DrawObject);
obj.add(this._HText.DrawObject);
this.UpdateDrawObject(renderType, obj);
return obj;
}
UpdateDrawObject(type: RenderType, obj: Object3D)
{
let [box, edge, lobj, wobj, hobj] = obj.children;
box.scale.set(this._Length, this._Width, this._Height);
box.updateMatrix();
edge.scale.set(this._Length, this._Width, this._Height);
edge.updateMatrix();
box.visible = !this._IsRoot;
if (this._IsRoot)
{
this._LText.TextAligen = TextAligen.Top;
this._WText.TextAligen = TextAligen.Down;
this._HText.TextAligen = TextAligen.Down;
}
else
{
this._LText.TextAligen = TextAligen.Down;
this._WText.TextAligen = TextAligen.Top;
this._HText.TextAligen = TextAligen.Top;
}
this._LText.TextString = FixedNotZero(this._Length, 2);
this._WText.TextString = FixedNotZero(this._Width, 2);
this._HText.TextString = FixedNotZero(this._Height, 2);
//实体被错误的Dispose,导致需要这样的更新
this._LText.Update();
this._WText.Update();
this._HText.Update();
lobj.visible = this._DisplayLength;
wobj.visible = this._DisplayWidth;
hobj.visible = this._DisplayHeight;
lobj.position.set(this._Length / 2, 0, 0);
lobj.updateMatrix();
wobj.position.set(0, this._Width / 2, 0);
wobj.updateMatrix();
hobj.position.set(0, 0, this._Height / 2);
hobj.updateMatrix();
}
//#endregion
//#region -------------------------File-------------------------
//对象从文件中读取数据,初始化自身
protected _ReadFile(file: CADFiler)
{
let ver = file.Read();
super._ReadFile(file);
this._Length = file.Read();
this._Width = file.Read();
this._Height = file.Read();
this._IsRoot = file.Read();
this._DisplayLength = file.Read();
this._DisplayWidth = file.Read();
this._DisplayHeight = file.Read();
}
//对象将自身数据写入到文件.
WriteFile(file: CADFiler)
{
file.Write(1);
super.WriteFile(file);
file.Write(this._Length);
file.Write(this._Width);
file.Write(this._Height);
file.Write(this._IsRoot);
file.Write(this._DisplayLength);
file.Write(this._DisplayWidth);
file.Write(this._DisplayHeight);
}
// //局部撤销
// ApplyPartialUndo(undoData: CADObject)
// {
// super.ApplyPartialUndo(undoData);
// }
//#endregion
//#region
GetGripPoints(): Array<Vector3>
{
// return EmptyArray;//因为更新模块树是异步的,没办法在拽拖夹点时顺带更新,所以移除这个特性.
let x = new Vector3;
let y = new Vector3;
let z = new Vector3;
this._Matrix.extractBasis(x, y, z);
x.multiplyScalar(this._Length);
y.multiplyScalar(this._Width);
z.multiplyScalar(this._Height);
let p = this.Position;
return [p, x.add(p), y.add(p), z.add(p)];
}
MoveGripPoints(indexList: number[], vec: Vector3)
{
let template = this.Template?.Object as TemplateRecord;
if (template && template !== template.Root)
return;
for (let i of indexList)
{
if (i === 0)
{
this.WriteAllObjectRecord();
this.Position = this.Position.add(vec);
return;
}
else
{
continue;
let ocs = this._Matrix.clone().setPosition(ZeroVec);
let ocsinv = new Matrix4().getInverse(ocs);
vec.applyMatrix4(ocsinv);
if (i === 1)
{
this._Length += vec.x;
template.LParam.expr = this._Length;
}
else if (i === 2)
{
this._Width += vec.y;
template.WParam.expr = this._Width;
}
else
{
this._Height += vec.z;
template.HParam.expr = this._Height;
}
template.UpdateTemplateTree(); //TODO:可以弹出个对话框让用户更新. 或者使用反应器?
this.Update();
}
return;
}
}
GetStretchPoints(): Array<Vector3>
{
return [];
}
/**
* ,Stretch
*
* @param {Array<number>} indexList .
* @param {Vector3} vec
* @memberof Entity
*/
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
{
}
//#endregion
}
class BackFaceBoxBufferGeometry extends BufferGeometry
{
constructor(length: number = 1, width: number = 1, height: number = 1)
{
super();
let pts: number[] = [
0, width, 0,
length, width, 0,
length, width, height,
0, width, height,
];
let uvs: number[] = [
0, 0,
1, 0,
1, 1,
0, 0,
1, 1,
0, 1,
];
let indices: number[] = [0, 1, 2, 0, 2, 3];
this.setIndex(indices);
this.addAttribute('position', new Float32BufferAttribute(pts, 3));
// this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
}
}
const backGeo = new BackFaceBoxBufferGeometry();
const edgeGeo = GenerateBoxEdgeGeometry(1, 1, 1);

@ -0,0 +1,30 @@
import { BufferGeometry, Vector3 } from "three";
import { arrayLast } from "../Common/ArrayExt";
import { equalv3 } from "./GeUtils";
import { FixIndex } from "../Common/Utils";
export function GenerateExtrudeEdgeGeometry(contourPoints: Vector3[], height: number)
{
if (equalv3(contourPoints[0], arrayLast(contourPoints)))
contourPoints.pop();
let pts: Vector3[] = [];
let hpts = contourPoints.map(p => new Vector3(p.x, p.y, height));
let count = contourPoints.length;
for (let i = 0; i < count; i++)
{
pts.push(contourPoints[i], contourPoints[FixIndex(i + 1, count)],
hpts[i], hpts[FixIndex(i + 1, count)],
contourPoints[i], hpts[i]
);
}
let geo = new BufferGeometry().setFromPoints(pts);
return geo;
}
export function GenerateBoxEdgeGeometry(length: number, width: number, height: number)
{
let pts = [new Vector3(), new Vector3(length), new Vector3(length, width), new Vector3(0, width)];
return GenerateExtrudeEdgeGeometry(pts, height);
}

@ -4,7 +4,9 @@ import { ToFixed } from '../Common/Utils';
export const IdentityMtx4 = new Matrix4();
export const ZeroVec = new Vector3();
export const XAxis = new Vector3(1, 0, 0);
export const XAxisN = new Vector3(-1, 0, 0);
export const YAxis = new Vector3(0, 1, 0);
export const YAxisN = new Vector3(0, -1, 0);
export const ZAxis = new Vector3(0, 0, 1);
export function AsVector2(p: { x: number, y: number; })

@ -3,6 +3,7 @@ import { arrayRemoveDuplicateBySort2 } from "../../Common/ArrayExt";
import { Board, BoardType } from "../../DatabaseServices/Entity/Board";
import { Box3Ext, SplitType } from "../Box";
import { equaln, isParallelTo, XAxis, YAxis, ZAxis } from "../GeUtils";
import { VisualSpaceBox } from './../../Editor/VisualSpaceBox';
export class ISpaceParse
{
@ -39,6 +40,8 @@ export class ISpaceParse
* ,
*/
IsDynamic: Boolean = false;
/**选到的虚拟空间 */
VisualSpaceBox: VisualSpaceBox;
/**
* # Parse().

@ -23,7 +23,7 @@ export class Point3SpaceParse extends ISpaceParse
let basePt = ptRes.Point;
let xRes = await app.Editor.GetPoint({
Msg: "选择x方向终点",
Msg: "选择长度方向终点(x轴):",
BasePoint: basePt,
AllowDrawRubberBand: true,
});
@ -33,7 +33,7 @@ export class Point3SpaceParse extends ISpaceParse
let xVec = xRes.Point.sub(basePt).normalize();
let zRes = await app.Editor.GetPoint({
Msg: "选择z方向终点",
Msg: "选择高度方向终点(Z轴):",
BasePoint: basePt,
AllowDrawRubberBand: true,
});
@ -47,7 +47,7 @@ export class Point3SpaceParse extends ISpaceParse
if (!isPerpendicularityTo(xVec, zVec))
{
AppToaster.show({
message: "x轴和z轴必须垂直",
message: "x轴和z轴必须垂直!",
timeout: 2000
});
return;

@ -1,12 +1,17 @@
import { Vector3 } from "three";
import { app } from "../../ApplicationServices/Application";
import { KeyWord } from "../../Common/InputState";
import { GetEntity } from "../../Common/Utils";
import { Board } from "../../DatabaseServices/Entity/Board";
import { BoxSolid } from "../../DatabaseServices/Entity/BoxSolid";
import { Entity } from "../../DatabaseServices/Entity/Entity";
import { TemplateRecord } from "../../DatabaseServices/Template/TemplateRecord";
import { JigUtils } from "../../Editor/JigUtils";
import { PointPick } from "../../Editor/PointPick";
import { PromptPointResult, PromptStatus } from "../../Editor/PromptResult";
import { VisualSpaceBox } from './../../Editor/VisualSpaceBox';
import { ISpaceParse } from "./ISpaceParse";
import { PointSelectBoards } from "./PointSelectBoards";
import { BoxSolid } from "../../DatabaseServices/Entity/BoxSolid";
export enum EnableSelectType
{
@ -82,9 +87,25 @@ export class PointSelectSpace
{
if (this.GetPointRes.StringResult === "S")
{
let ssRes = await app.Editor.GetSelection({ UseSelect: true, Filter: { filterTypes: [Board] } });
let ssRes = await app.Editor.GetSelection({
UseSelect: true,
Filter: {
filterFunction: (o, e) =>
{
return e instanceof Board || FilterVisualSpaceBox(e);
}
}
});
if (ssRes.Status === PromptStatus.OK)
{
let visiBox = ssRes.SelectSet.SelectEntityList.find(e => e instanceof VisualSpaceBox) as VisualSpaceBox;
if (visiBox)
{
this.PointParseVisualSpace(visiBox);
return;
}
await this.ParseBySelect(ssRes.SelectSet.SelectEntityList as Board[]);
}
}
else if (this.GetPointRes.StringResult === "2")
{
@ -135,6 +156,14 @@ export class PointSelectSpace
{
let view = app.Viewer;
let vcs = app.Editor.MouseCtrl.m_CurMousePointVCS;
let visualBoxPick = PointPick(vcs, view, { filterFunction: (o, e) => FilterVisualSpaceBox(e) });
if (visualBoxPick.length > 0)
{
this.PointParseVisualSpace(GetEntity(visualBoxPick[0]) as VisualSpaceBox);
return;
}
let ptSelect = new PointSelectBoards(vcs, view, view.VisibleObjects);
if (ptSelect.SelectBoards.length === 0 && !isDynamic)
@ -142,6 +171,13 @@ export class PointSelectSpace
else
await this.ParseByPointSelect(ptSelect, isDynamic);
}
private PointParseVisualSpace(spaceBox: VisualSpaceBox)
{
this.SpaceParse = new ISpaceParse([], spaceBox.SpaceOCS);
this.SpaceParse.VisualSpaceBox = spaceBox;
this.SpaceParse.SpaceBox = spaceBox.BoundingBoxInOCS;
this.SpaceParse.ParseOK = true;
}
private ShowSpaceBox()
{
if (this.ParseOK)
@ -170,3 +206,8 @@ export class PointSelectSpace
}
}
}
function FilterVisualSpaceBox(e: Entity)
{
return (e instanceof VisualSpaceBox && (e?.Template?.Object as TemplateRecord)?.Children.length === 0);
}

@ -5,7 +5,6 @@ import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { PromptStatus } from "../../Editor/PromptResult";
import { FileSystem } from "../../Common/FileSystem";
@HotCMD
export class Command_NFPData implements Command
{
async exec()

@ -5,7 +5,7 @@ import { ConvexHull2D } from "../ConvexHull2D";
import { Path2Polyline } from "../Converter/Path2Polyline";
import { HotCMD } from "../../Hot/HotCommand";
@HotCMD
export class Command_TestHull
{
async exec()

@ -12,7 +12,6 @@ import { InitClipperCpp } from "../ClipperCpp";
const TesetPerformance = true;
@HotCMD
export class Command_TestNFP implements Command
{
async exec()

@ -2,14 +2,12 @@ import { EndType as ET, JoinType as JT } from "js-angusj-clipper/web";
import { app } from "../../ApplicationServices/Application";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { PromptStatus } from "../../Editor/PromptResult";
import { HotCMD } from "../../Hot/HotCommand";
import { clipperCpp } from "../ClipperCpp";
/**
* 19-20使c++
*/
@HotCMD
export class Command_TestOffset
{
async exec()

@ -13,7 +13,6 @@ import { Part } from "../Part";
import { PathGeneratorSingle } from "../PathGenerator";
import { InitClipperCpp } from "../ClipperCpp";
@HotCMD
export class Command_TestPlace implements Command
{
async exec()

@ -9,7 +9,6 @@ import { Circle } from "../../DatabaseServices/Entity/Circle";
import { SimplifyDouglasPeucker } from "../Converter/Simplify2";
import { Polylin2Points } from "../Converter/ConverBoard2Part";
@HotCMD
export class Command_TestSimply implements Command
{
async exec()

@ -22,7 +22,6 @@ import { OptimizeMachine } from "../OptimizeMachine";
import { PathGeneratorSingle } from "../PathGenerator";
import { NestVariant } from "./TestVariant";
@HotCMD
export class Command_TestYH2 implements Command
{
async exec()

@ -24,7 +24,6 @@ import Worker from "../OptimizeWorker.worker";
import { PathGeneratorSingle } from "../PathGenerator";
import { NestVariant } from "./TestVariant";
@HotCMD
export class Command_TestYHWorker implements Command
{
async exec()

@ -12,7 +12,7 @@ import { StoreageKeys } from '../../../Common/StoreageKeys';
import { Board } from '../../../DatabaseServices/Entity/Board';
import { Entity } from '../../../DatabaseServices/Entity/Entity';
import { PositioningClampSpace } from '../../../DatabaseServices/Template/Positioning/PositioningClampSpace';
import { GetDeepestTemplate, GetOnlineTemplate, UploadTemplate, EditorOnlineTemplate } from '../../../DatabaseServices/Template/TempateUtils';
import { GetDeepestTemplate, GetOnlineTemplate, UploadTemplate, EditorOnlineTemplate, ReplaceTemplate } from '../../../DatabaseServices/Template/TempateUtils';
import { TemplateRecord } from '../../../DatabaseServices/Template/TemplateRecord';
import { commandMachine, CommandWrap } from '../../../Editor/CommandMachine';
import { JigUtils } from '../../../Editor/JigUtils';
@ -26,6 +26,8 @@ import { HandleDirComponent } from '../SourceManage/HandleDirComponent';
import { AppToaster } from '../Toaster';
import { GetRoomCabName, IGetRoomInfo } from './GetRoomCabName';
import { TemplateList } from './TemplateList';
import { TemplateVisualSpace } from './../../../DatabaseServices/Template/ProgramTempate/TemplateVisualSpace';
import { DeleteTempate } from './../../../DatabaseServices/Template/TempateUtils';
export interface INeedUpdateParams
{
@ -268,7 +270,7 @@ export class TemplateManage extends React.Component<{ store?: TempalteEditorStor
return;
template = app.Database.WblockCloneObejcts([template], app.Database.TemplateTable, new Map(), DuplicateRecordCloning.Ignore)[0] as TemplateRecord;
let nents = template.Root.AllEntitys;
let nents = template.AllEntitys;
let seleteBrs = parse.Boards.filter(b => b.Template !== undefined);
@ -308,9 +310,18 @@ export class TemplateManage extends React.Component<{ store?: TempalteEditorStor
}
else
{
template.LParam.expr = parse.Size.x;
template.WParam.expr = parse.Size.y;
template.HParam.expr = parse.Size.z;
if (parse.VisualSpaceBox)
{
let vstemp = parse.VisualSpaceBox.Template.Object as TemplateVisualSpace;
ReplaceTemplate(vstemp, template);
DeleteTempate(vstemp);
}
else
{
template.LParam.expr = parse.Size.x;
template.WParam.expr = parse.Size.y;
template.HParam.expr = parse.Size.z;
}
let ens = template.Objects.map(obj => obj.Object as Board).filter(br => !br.IsErase);

Loading…
Cancel
Save