!1453 优化:造型应用和合并的性能

pull/1453/MERGE
ChenX 4 years ago
parent a62b0309fb
commit 07a4c740b2

@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`造型里面有重复的圆造型 1`] = `2782`;
exports[`造型里面有重复的圆造型 2`] = `0`;

@ -0,0 +1,15 @@
import { Board } from "../../src/DatabaseServices/Entity/Board";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
test('造型里面有重复的圆造型', () =>
{
let d = require("./br.json").file;
let br = LoadEntityFromFileData(d)[0] as Board;
let split = [];
br.GrooveCheckAll(split);
expect(br.Grooves.length).toMatchSnapshot();
expect(split.length).toMatchSnapshot();
});

File diff suppressed because one or more lines are too long

@ -1,10 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`EdgeGeometry生成 1`] = `216`;
exports[`EdgeGeometry生成 1`] = `164`;
exports[`EdgeGeometry生成 2`] = `410`;
exports[`EdgeGeometry生成 3`] = `60`;
exports[`EdgeGeometry生成 3`] = `68`;
exports[`EdgeGeometry生成2 1`] = `66`;

@ -26,6 +26,7 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@types/flatbush": "^3.3.0",
"@rollup/plugin-typescript": "^6.0.0",
"@types/html-webpack-plugin": "^3.2.3",
"@types/jest": "^26.0.19",
@ -95,6 +96,7 @@
"@types/react-window": "^1.8.2",
"detect-browser": "^5.1.1",
"dxf-parser": "git+https://ZoeLeee@github.com/ZoeLeee/dxf-parser.git",
"flatbush": "^3.3.0",
"golden-layout": "^1.5.9",
"js-angusj-clipper": "^1.1.0",
"mobx": "^5.15.6",

@ -38,7 +38,8 @@ export async function selectOutlinePosition(cus: Curve[] | Curve)
if (ptRes.Status === PromptStatus.OK)
{
moveCus.forEach(cu => app.Database.ModelSpace.Append(cu));
for (let cu of moveCus)
app.Database.ModelSpace.Append(cu);
return true;
}
return false;

@ -5,7 +5,7 @@ import { Status } from "../Common/Status";
import { FixIndex } from "../Common/Utils";
import { IntersectBox2 } from "../Geometry/Box";
import { Route } from "../Geometry/CurveMap";
import { equaln, equalv3 } from "../Geometry/GeUtils";
import { equaln, equalv2, equalv3 } from "../Geometry/GeUtils";
import { RegionParse } from "../Geometry/RegionParse";
import { isTargetCurInOrOnSourceCur } from "../GraphicsSystem/BoolOperateUtils";
import { IntersectOption } from "../GraphicsSystem/IntersectWith";
@ -213,6 +213,15 @@ export class Contour
*/
GetIntersetAndUnionList(target: Contour): { intersectionList: Curve[], unionList: Curve[]; }
{
//同心圆
if (this._Curve instanceof Circle && target._Curve instanceof Circle && equalv2(this._Curve.Center, target._Curve.Center, 1e-3))
{
if (this._Curve.Radius > target._Curve.Radius)
return { intersectionList: [this._Curve], unionList: [target._Curve] };
else
return { intersectionList: [target._Curve], unionList: [this._Curve] };
}
let intersectionList: Curve[] = [];
let unionList: Curve[] = [];

@ -343,6 +343,7 @@ export class Board extends ExtrudeSolid
for (let g of this.grooves)
{
let cu = g.ContourCurve.Clone().ApplyMatrix(this.OCSInv.multiply(g.OCS));
cu.Erase(false);//当内部造型超过100个时,不校验时,这个曲线就是erase的状态,所以设置这个状态,避免无法绘制出来
if (cu instanceof Circle)//这里保证这个圆是正常坐标系 I3BUSY#note_4525213
cu.OCS = new Matrix4().setPosition(cu.Position);

@ -1,4 +1,5 @@
import { BoxGeometry, BufferGeometry, ExtrudeGeometry, ExtrudeGeometryOptions, Geometry, InstancedInterleavedBuffer, InterleavedBufferAttribute, Line as TLine, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Path, UVGenerator, Vector3 } from "three";
import Flatbush from 'flatbush';
import { Box3, BoxGeometry, BufferGeometry, ExtrudeGeometry, ExtrudeGeometryOptions, Float32BufferAttribute, Geometry, InstancedInterleavedBuffer, InterleavedBufferAttribute, Line as TLine, LineSegments, Matrix3, Matrix4, Mesh, Object3D, UVGenerator, Vector3 } from "three";
import { Line2 } from "three/examples/jsm/lines/Line2";
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";
import { arrayClone, arrayLast, arrayPushArray, arrayRemoveIf, arrayRemoveOnce, arraySortByNumber, arraySum } from "../../Common/ArrayExt";
@ -15,11 +16,10 @@ import { boardUVGenerator } from "../../Geometry/BoardUVGenerator";
import { Box3Ext } from "../../Geometry/Box";
import { BSPGroupParse } from "../../Geometry/BSPGroupParse";
import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils";
import { FastWireframe } from "../../Geometry/CreateWireframe";
import { FastExtrudeEdgeGeometry, FastWireframe } from "../../Geometry/CreateWireframe";
import { EdgesGeometry } from "../../Geometry/EdgeGeometry";
import { GenerateExtrudeEdgeGeometry } from "../../Geometry/ExtrudeEdgeGeometry";
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeEdgeGeometry2";
import { AsVector2, AsVector3, equaln, equalv2, equalv3, IdentityMtx4, isIntersect, isParallelTo, isPerpendicularityTo, MoveMatrix, XAxis, YAxis, ZAxis, ZeroVec } from "../../Geometry/GeUtils";
import { AsVector2, equaln, equalv2, equalv3, IdentityMtx4, isIntersect, isParallelTo, isPerpendicularityTo, MoveMatrix, XAxis, YAxis, ZAxis, ZeroVec } from "../../Geometry/GeUtils";
import { OBB } from "../../Geometry/OBB/obb";
import { ScaleUV, ScaleUV2 } from "../../Geometry/UVUtils";
import { RenderType } from "../../GraphicsSystem/RenderType";
@ -45,6 +45,8 @@ import { Region } from "./Region";
export type ExtureContourCurve = Polyline | Circle;
export type ExtureContour = Polyline | Circle | ExtrudeSolid | Region;
export const MaxDrawGrooveCount = 1000;//最大的绘制槽个数(但是还是会绘制线)
@Factory
export class ExtrudeSolid extends Entity
{
@ -770,7 +772,7 @@ export class ExtrudeSolid extends Entity
case ObjectSnapMode.Tan:
{
let contour = this.ContourCurve.Clone();
contour.ApplyMatrix(this.OCS);
contour.ApplyMatrix(this.OCSNoClone);
let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform);
contour.Position = contour.Position.add(this.Normal.multiplyScalar(this.thickness));
@ -781,13 +783,15 @@ export class ExtrudeSolid extends Entity
for (let p of ps)
{
let l = new Line(p, p.clone().setZ(this.thickness));
l.ApplyMatrix(this.OCS);
l.ApplyMatrix(this.OCSNoClone);
pts.push(
...l.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform)
);
}
for (let g of this.grooves)
pts.push(...g.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform));
if (this.grooves.length < 100)
for (let g of this.grooves)
pts.push(...g.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform));
return pts;
}
@ -819,7 +823,7 @@ export class ExtrudeSolid extends Entity
let pts = isGrip ? this.ContourCurve.GetGripPoints() : this.ContourCurve.GetStretchPoints();
let v = new Vector3(0, 0, this.thickness);
pts.push(...pts.map(p => p.clone().add(v)));
pts.forEach(p => { p.applyMatrix4(this.OCS); });
pts.forEach(p => { p.applyMatrix4(this.OCSNoClone); });
for (let g of this.grooves)
{
@ -1243,30 +1247,71 @@ export class ExtrudeSolid extends Entity
*/
GrooveCheckMerge()
{
let gs: ExtrudeSolid[] = [];
while (this.grooves.length > 0)
if (this.grooves.length < 2) return;
//生命周期:初始化->used->undefined
type ExtData = {
index: number;
used: boolean;
box: Box3;
};
//构建二维空间索引
let ocsInv = this.OCSInv;
let mtx = new Matrix4;
let fb = new Flatbush(this.grooves.length);
for (let i = 0; i < this.grooves.length; i++)
{
let g = this.grooves[i];
mtx.multiplyMatrices(ocsInv, g.OCSNoClone);
let cu = g.ContourCurve.Clone().ApplyMatrix(mtx);
let box = cu.BoundingBox;
g.TempData = { index: i, used: false, box };
fb.add(box.min.x, box.min.y, box.max.x, box.max.y);
}
fb.finish();
let retGs: ExtrudeSolid[] = [];//新的槽列表
for (let i = 0; i < this.grooves.length; i++)
{
let g = this.grooves.pop();
while (this.grooves.length > 0)
let startG = this.grooves[i];
if (startG.TempData === undefined)//已经被使用
continue;
retGs.push(startG);
let stack = [startG];
for (let j = 0; j < stack.length; j++)
{
//剩余的 无法合并的板件
let remGs = this.grooves.filter(gn =>
let g = stack[j];
let gd = g.TempData as ExtData;//能入栈的都是未被使用的
let ids = fb.search(gd.box.min.x, gd.box.min.y, gd.box.max.x, gd.box.max.y, (id =>
{
if (equaln(g.knifeRadius, gn.knifeRadius))
return g.Join(gn) === Status.False;
else
return true;
});
if (remGs.length === this.grooves.length)
break;
this.grooves = remGs;
if (id <= i) return false;//(id比它小(如果能合并 早就合并了))
let gd = this.grooves[id].TempData as ExtData;
return gd && !gd.used;//判断被使用
}));
for (let id of ids)
{
let ng = this.grooves[id];
if (equaln(startG.knifeRadius, ng.knifeRadius, 1e-3) && startG.Join(ng) === Status.True)
{
(ng.TempData as ExtData).used = true;
stack.push(ng);
}
}
g.TempData = undefined;//总是保证被使用的造型这个数据为空
}
gs.push(g);
}
if (gs.length !== this.grooves.length)
if (retGs.length !== this.grooves.length)
{
this.grooves = gs;
this.grooves = retGs;
for (let g of this.grooves)
g.CheckContourCurve();
}
@ -1770,13 +1815,14 @@ export class ExtrudeSolid extends Entity
let ocsInv = this.OCSInv;
let alMatrix4 = new Matrix4();
for (let g of grooves)
{
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
let gContour = g.ContourCurve.Clone();
gContour.ApplyMatrix(alMatrix4);
holes.push(Contour.CreateContour(gContour));
}
if (grooves.length < 1000)
for (let g of grooves)
{
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
let gContour = g.ContourCurve.Clone();
gContour.ApplyMatrix(alMatrix4);
holes.push(Contour.CreateContour(gContour));
}
let shape = new Shape(Contour.CreateContour(contour), holes);
@ -1798,7 +1844,8 @@ export class ExtrudeSolid extends Entity
let builder = new ExtrudeGeometryBuilder(this);
this._MeshGeometry = builder.MeshGeometry;
this._EdgeGeometry = builder.EdgeGeometry;
if (grooves.length < MaxDrawGrooveCount)
this._EdgeGeometry = builder.EdgeGeometry;
this.UpdateUV(null, null);
return this._MeshGeometry;
@ -1812,36 +1859,18 @@ export class ExtrudeSolid extends Entity
if (!ExtrudeConfig.DisableRefCut)
this.CalcRelevanceGroove();
if (this._EdgeGeometry)
return this._EdgeGeometry;
if (this.grooves.every(g => equaln(g.thickness, this.thickness)) || this.grooves.length === 0)
//这里我们超过100就用这个,为了性能 和MaxDrawGrooveCount不一致
if (this.grooves.length > 100 || this.grooves.every(g => equaln(g.thickness, this.thickness)) || this.grooves.length === 0)
{
let pts = [this.ContourCurve.Shape.getPoints(6).map(AsVector3)];
let ocsInv = this.OCSInv;
let alMatrix4 = new Matrix4();
for (let g of this.grooves)
{
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
let gContour = g.ContourCurve.Clone();
gContour.ApplyMatrix(alMatrix4);
if (gContour instanceof Polyline)
gContour.UpdateMatrixTo(this.contourCurve.OCS);
if (gContour instanceof Circle)
{
let sp = new Path();
let cen = gContour.Center.applyMatrix4(this.contourCurve.OCSInv);
sp.ellipse(cen.x, cen.y, gContour.Radius, gContour.Radius, 0, 2 * Math.PI, false, 0);
pts.push(sp.getPoints(6).map(AsVector3));
}
else
pts.push(gContour.Shape.getPoints(6).map(AsVector3));
}
let geo = GenerateExtrudeEdgeGeometry(pts, this.thickness).applyMatrix4(this.contourCurve.OCSNoClone);
this._EdgeGeometry = geo;
return geo;
let coords = FastExtrudeEdgeGeometry(this, this.ColorIndex, 6, true);
let edgeGeo = new BufferGeometry();
edgeGeo.setAttribute('position', new Float32BufferAttribute(coords, 3));
this._EdgeGeometry = edgeGeo;
return this._EdgeGeometry;
}
if (this._MeshGeometry)

@ -1,23 +1,44 @@
import { EllipseCurve, Shape, Vector2 } from "three";
import { clamp } from "../Common/Utils";
import { equalv2 } from "../Geometry/GeUtils";
import { Arc } from "./Entity/Arc";
let tempArc: Arc;
export class Shape2 extends Shape
{
getPoints(divisions: number = 12)
getPoints(divisions: number = 12, optimizeArc = true)
{
divisions = divisions || 12;
let points = [], last: Vector2;
for (let i = 0, curves = this.curves; i < curves.length; i++)
{
let curve = curves[i];
let curve = curves[i] as EllipseCurve;
let resolution = divisions;
//@ts-ignore
let resolution = (curve && curve.isEllipseCurve) ? clamp(curve.getLength() / 20, divisions * 2, 60)
if (curve && curve.isEllipseCurve)
{
if (optimizeArc)
{
if (!tempArc) tempArc = new Arc;
tempArc.IsClockWise = curve.aClockwise;
tempArc.StartAngle = curve.aStartAngle;
tempArc.EndAngle = curve.aEndAngle;
tempArc.Radius = curve.xRadius;
resolution = clamp(tempArc.Length / 20, divisions * 2, 60);
}
else
resolution = divisions * 2;
}
else
{
//@ts-ignore
: (curve && (curve.isLineCurve || curve.isLineCurve3)) ? 1
resolution = (curve && (curve.isLineCurve || curve.isLineCurve3)) ? 1
//@ts-ignore
: (curve && curve.isSplineCurve) ? divisions * curve.points.length
: divisions;
}
let pts = curve.getPoints(resolution);

@ -2,7 +2,7 @@ import { end } from 'xaop';
import { InputState } from '../Common/InputState';
import { KeyCode } from '../Common/KeyEnum';
import { Editor } from './Editor';
import { GetSelectionPrompt } from "./PromptOptions";
import { GetEntityPrompt, GetSelectionPrompt } from "./PromptOptions";
import { PromptSsgetResult, PromptStatus } from './PromptResult';
import { SelectType } from './SelectBox';
import { SelectPick } from './SelectPick';
@ -48,12 +48,14 @@ export class SsgetServiecs
while (true)
{
let enRes = await this._Editor.GetEntity({
let gep: GetEntityPrompt = {
Msg: prompt.Msg,
IsSelect: true,
KeyWordList: prompt.KeyWordList,
Filter: prompt.Filter,
Callback: (res) =>
Filter: prompt.Filter
};
if (prompt.Callback)
gep.Callback = (res) =>
{
if (prompt.Callback)
{
@ -64,8 +66,9 @@ export class SsgetServiecs
set.AddSelect(ssEnt);
prompt.Callback({ Status: PromptStatus.OK, SelectSet: set });
}
}
});
};
let enRes = await this._Editor.GetEntity(gep);
switch (enRes.Status)
{

@ -2,13 +2,11 @@ import { BufferGeometry, Line, Matrix3, Matrix4, Object3D, PerspectiveCamera, Ve
import { app } from '../ApplicationServices/Application';
import { ColorMaterial } from '../Common/ColorPalette';
import { GetEntity } from '../Common/Utils';
import { SweepSolid } from '../DatabaseServices/3DSolid/SweepSolid';
import { Arc } from '../DatabaseServices/Entity/Arc';
import { Circle } from '../DatabaseServices/Entity/Circle';
import { Curve } from '../DatabaseServices/Entity/Curve';
import { Entity } from '../DatabaseServices/Entity/Entity';
import { EntityRef } from '../DatabaseServices/Entity/EntityRef';
import { ExtrudeSolid } from '../DatabaseServices/Entity/Extrude';
import { Line as DbLine } from "../DatabaseServices/Entity/Line";
import { Polyline } from '../DatabaseServices/Entity/Polyline';
import { BufferGeometryUtils } from '../Geometry/BufferGeometryUtils';
@ -17,7 +15,6 @@ import { equaln, equalv3, midPoint, SnapPoint, XAxis, YAxis, ZAxis } from '../Ge
import { PointShapeUtils } from '../Geometry/PointShapeUtils';
import { IntersectOption } from '../GraphicsSystem/IntersectWith';
import { DrawMode } from '../GraphicsSystem/PreViewer';
import { RenderType } from '../GraphicsSystem/RenderType';
import { DynamicInputManage } from '../UI/DynamicPrompt/DynamicInputManage';
import { PromptBlock } from '../UI/DynamicPrompt/PromptBlock';
import { ObjectSnapMode } from './ObjectSnapMode';
@ -247,24 +244,35 @@ export class SnapServices
}
}
let sel = new SelectPick(app.Viewer, vcsP, this.SnapSize);
let sel = new SelectPick(app.Viewer, vcsP, this.SnapSize);//直接用这个,不需要用box,射线追踪没有性能损耗
let selectEns: Entity[] = [];
// 由于绘制的实体可能有多个分裂,所以代码会重复的去选择,当前注释的代码已经避免这种情况,不过性能并不会提高.所以取消这个代码
// console.time("all");
// let cacheSet = new Set<Entity>();
sel.Select(app.Viewer.VisibleObjects, {
filterErase: true,
filterFunction: (obj, ent) =>
{
// if (cacheSet.has(ent)) return false;
if (ent instanceof EntityRef)
return false;
else if (ent instanceof ExtrudeSolid || ent instanceof SweepSolid)
{
//黑魔法,提高性能,否则如果是概念视觉央视下,还要选一遍网格体,亏死
if (sel.CheckSelectTraverse(ent.GetDrawObjectFromRenderType(RenderType.Wireframe)))
selectEns.push(ent);
return false;
}
// else if (ent instanceof ExtrudeSolid || ent instanceof SweepSolid)
// {
// cacheSet.add(ent);
// console.time();
// //黑魔法,提高性能,否则如果是概念视觉央视下,还要选一遍网格体,亏死
// if (sel.CheckSelectTraverse(ent.GetDrawObjectFromRenderType(RenderType.Wireframe)))
// selectEns.push(ent);
// console.timeEnd();
// return false;
// }
return true;
}
});
// console.timeEnd("all");
selectEns.push(...sel.SelectEntityList);

@ -1,14 +1,14 @@
import { BufferGeometry, Float32BufferAttribute, Geometry, Line, LineBasicMaterial, LineSegments, Object3D, Shape as TShape, Vector3 } from "three";
import { BufferGeometry, Float32BufferAttribute, Geometry, Line, LineBasicMaterial, LineSegments, Matrix4, Object3D, Vector3 } from "three";
import { ColorMaterial } from "../Common/ColorPalette";
import { FixIndex } from "../Common/Utils";
import { Board } from "../DatabaseServices/Entity/Board";
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
import { Contour } from "../DatabaseServices/Contour";
import { Board } from "../DatabaseServices/Entity/Board";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { ExtrudeSolid } from "../DatabaseServices/Entity/Extrude";
import { Shape } from "../DatabaseServices/Shape";
import { FaceDirection } from "../UI/Store/BoardInterface";
import { MoveMatrix } from "./GeUtils";
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
import { MatrixIsIdentityCS, MoveMatrix } from "./GeUtils";
//FIXME: #IWBPB 性能缺陷和BUG. 等待废弃或者改进
export function CreateWireframe(en3D: Board | ExtrudeSolid)
@ -93,7 +93,8 @@ function appendLines(cu: Curve, thick: number, lines: Object3D[], mat: LineBasic
}
}
export function FastWireframe(br: ExtrudeSolid, color = 0)
//使用lineseg来生成拉伸的边框,避免生成过多的实体导致的drawcall次数增多
export function FastWireframe(br: ExtrudeSolid, color = 0, divCount = 6, optArc = true): Line<BufferGeometry, LineBasicMaterial>[]
{
color = color || br.ColorIndex;
let material = ColorMaterial.GetLineMaterial(color);
@ -101,7 +102,7 @@ export function FastWireframe(br: ExtrudeSolid, color = 0)
let thickness = br.Thickness;
let cu = br.ContourCurve;
let pts = cu.Shape.getPoints(6);
let pts = cu.Shape.getPoints(divCount, optArc);
let geo = new BufferGeometry();
let coords: number[] = [];
@ -121,27 +122,84 @@ export function FastWireframe(br: ExtrudeSolid, color = 0)
geo.setAttribute('position', new Float32BufferAttribute(coords, 3));
let line = new Line(geo, material);
line.applyMatrix4(cu.OCS);
line.applyMatrix4(cu.OCSNoClone);
let edge = new LineSegments(edgeGeo, material);
edge.applyMatrix4(cu.OCS);
edge.applyMatrix4(cu.OCSNoClone);
let result = [line, edge];
let ocsInv = br.OCSInv;
for (let g of br.Grooves)
if (br.Grooves.length < 100)
for (let g of br.Grooves)
{
let m = ocsInv.clone().multiply(g.OCSNoClone);
let lines = FastWireframe(g, color, 3, false);
for (let l of lines)
{
l.applyMatrix4(m);
result.push(l);
}
}
return result;
}
let tempP = new Vector3;
export function FastExtrudeEdgeGeometry(ext: ExtrudeSolid, color = 0, divCount = 6, optArc = true, coords: number[] = [], inv: Matrix4 = undefined)
{
color = color || ext.ColorIndex;
let thickness = ext.Thickness;
let cu = ext.ContourCurve;
let pts = cu.Shape.getPoints(divCount, optArc);
let startIndex = coords.length / 3;
for (let i = 0; i < pts.length; i++)
{
let m = ocsInv.clone().multiply(g.OCS);
let lines = FastWireframe(g, color);
for (let l of lines)
let p = pts[i];
let nextp = pts[FixIndex(i + 1, pts)];
//底面
coords.push(p.x, p.y, 0, nextp.x, nextp.y, 0);
//顶面
coords.push(p.x, p.y, thickness, nextp.x, nextp.y, thickness);
if (p["_mask_"])//侧面
coords.push(p.x, p.y, 0, p.x, p.y, thickness);
}
let m = inv ? (ext.Grooves.length ? inv.clone() : inv).multiply(cu.OCSNoClone) : cu.OCSNoClone;
if (!MatrixIsIdentityCS(m))
{
let count = coords.length / 3;
for (let i = startIndex; i < count; i++)
{
l.applyMatrix4(m);
result.push(l);
let a = i * 3;
let b = a + 1;
let c = a + 2;
tempP.set(coords[a], coords[b], coords[c]);
tempP.applyMatrix4(m);
coords[a] = tempP.x;
coords[b] = tempP.y;
coords[c] = tempP.z;
}
}
return result;
let ocsInv = inv ? (inv.multiply(ext.OCSInv)) : ext.OCSInv;
optArc = ext.Grooves.length < 100;
for (let g of ext.Grooves)
{
FastExtrudeEdgeGeometry(g, color, divCount, optArc, coords, ocsInv.clone().multiply(g.OCSNoClone));
}
return coords;
}
export function FastWireframe2(dr: ExtrudeHole, color = 0)
{
color = color || dr.ColorIndex;

@ -1,4 +1,5 @@
import { BufferGeometry, Float32BufferAttribute, MathUtils, Matrix4, Shape as TShape, ShapeUtils, Vector3 } from "three";
import Flatbush from 'flatbush';
import { Box3, BufferGeometry, Float32BufferAttribute, MathUtils, Matrix4, Shape as TShape, ShapeUtils, Vector3 } from "three";
import { arrayRemoveDuplicateBySort, arraySortByNumber } from "../Common/ArrayExt";
import { curveLinkGroup } from "../Common/CurveUtils";
import { clamp, FixIndex } from "../Common/Utils";
@ -7,7 +8,7 @@ import { Arc } from "../DatabaseServices/Entity/Arc";
import { Board } from "../DatabaseServices/Entity/Board";
import { Circle } from "../DatabaseServices/Entity/Circle";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { ExtrudeSolid, ExtureContourCurve } from "../DatabaseServices/Entity/Extrude";
import { ExtrudeSolid, ExtureContourCurve, MaxDrawGrooveCount } from "../DatabaseServices/Entity/Extrude";
import { Line } from "../DatabaseServices/Entity/Line";
import { Polyline, PolylineProps } from "../DatabaseServices/Entity/Polyline";
import { IntersectOption, IntersectResult } from "../GraphicsSystem/IntersectWith";
@ -150,10 +151,15 @@ enum DirectionType
export class ContourTreeNode
{
parent: ContourTreeNode;//当存在Parent时,表示它是一个洞(如果有多层时,使用IsHole判断)
box: Box3;
area: number;
constructor(public contour: Contour, public children: ContourTreeNode[] = []) { }
SetParent(node: ContourTreeNode)
{
if (this.parent)
throw "ContourTreeNode重复设置父对象";
this.parent = node;
node.children.push(this);
}
@ -166,6 +172,9 @@ export class ContourTreeNode
{
depth++;
parent = parent.parent;
if (depth > 10)
throw "ContourTreeNode嵌套超过10层";
}
return depth;
}
@ -276,16 +285,32 @@ export class ContourTreeNode
static ParseContourTree(contourNodes: ContourTreeNode[]): void
{
contourNodes.sort((c1, c2) => c1.contour.Curve.Area - c2.contour.Curve.Area);
if (contourNodes.length < 2) return;
let fb = new Flatbush(contourNodes.length);
for (let node of contourNodes)
{
node.box = node.contour.BoundingBox;
node.area = node.contour.Area;
fb.add(node.box.min.x, node.box.min.y, node.box.max.x, node.box.max.y);
}
fb.finish();
for (let i = 0; i < contourNodes.length; i++)
{
const node1 = contourNodes[i];
let p = node1.contour.Curve.StartPoint;
for (let j = i + 1; j < contourNodes.length; j++)
let ids = fb.search(node1.box.min.x, node1.box.min.y, node1.box.max.x, node1.box.max.y);
ids.sort((i1, i2) => contourNodes[i1].area - contourNodes[i2].area);
for (let id of ids)
{
const node2 = contourNodes[j];
if (node2.contour.BoundingBox.intersectsBox(node1.contour.BoundingBox)
&& node2.contour.Curve.PtInCurve(p))
if (id === i) continue;
let node2 = contourNodes[id];
if (node2.parent === node1 || node2.area < node1.area) continue;//避免自己的儿子成为自己的父亲
if (node2.contour.Curve.PtInCurve(p))
{
node1.SetParent(node2);
break;
@ -1244,19 +1269,20 @@ export class ExtrudeGeometryBuilder
//计算墙(创建轮廓取出,为了得到正确的轮廓曲线(逆时针之类的))
let outerWall = new ExtudeWall(Contour.CreateContour(br.ContourCurve.Clone()).Curve, DepthType.All, br.Thickness, br.Thickness, DirectionType.Outer);
let grooves = this.ParseGrooves();
for (let i = 0; i < grooves.length; i++)
{
let s1 = grooves[i];
outerWall.ClipTo(s1, false);
s1.contourWall.ClipReverse(outerWall);
for (let j = i + 1; j < grooves.length; j++)
if (grooves.length < MaxDrawGrooveCount)//只能绘制1000个以下的造型
for (let i = 0; i < grooves.length; i++)
{
let s2 = grooves[j];
s1.ClipTo(s2, true);
}
let s1 = grooves[i];
outerWall.ClipTo(s1, false);
s1.contourWall.ClipReverse(outerWall);
for (let j = i + 1; j < grooves.length; j++)
{
let s2 = grooves[j];
s1.ClipTo(s2, true);
}
s1.Draw(this.verticesArray, this.uvArray, this.edgeAndLidBuilder, rotateUv);
}
s1.Draw(this.verticesArray, this.uvArray, this.edgeAndLidBuilder, rotateUv);
}
outerWall.Draw(this.verticesArray, this.uvArray, this.edgeAndLidBuilder);
//这里构建盖子

@ -167,12 +167,12 @@ export class BoardConfigModal extends React.Component<BoardConfigProps, {}>{
);
}
/**
*
*/
*
*/
private PickUpModelingOutline = async () =>
{
await app.Editor.ModalManage.EndExecingCmd();
CommandWrap(async () =>
await CommandWrap(async () =>
{
app.Editor.SelectCtrl.Cancel();
app.Editor.ModalManage.ToggleShow();
@ -382,6 +382,7 @@ export class BoardConfigModal extends React.Component<BoardConfigProps, {}>{
if (!contour) return;
let br = this.props.br;
br.AutoUpdate = false;
let applyMatrix = ExtrudeApplyContour(br, contour);
if (contour instanceof Region)
@ -420,6 +421,7 @@ export class BoardConfigModal extends React.Component<BoardConfigProps, {}>{
if (selectBox.CheckSelectTraverse(c.GetDrawObjectFromRenderType()))
{
//在创建内部造型时,如果存在封闭的轮廓或者圆,那么自动分裂将失效(需要用户自己裂开)
let contours = CreateContours(g);
if (!contourMap.has(c.ColorIndex))
@ -440,6 +442,9 @@ export class BoardConfigModal extends React.Component<BoardConfigProps, {}>{
}
this.AddModeling(contourMap, applyMatrix);
}
br.AutoUpdate = true;
br.DeferUpdate();
};
await exec();
@ -543,6 +548,7 @@ export class BoardConfigModal extends React.Component<BoardConfigProps, {}>{
{
let br = this.props.br;
const rightStore = RightPanelStore.GetInstance() as RightPanelStore;
for (let [color, contours] of contourMap)
{
for (let con of contours)
@ -562,7 +568,7 @@ export class BoardConfigModal extends React.Component<BoardConfigProps, {}>{
if (contourNode.IsHole) continue;
let groove = new ExtrudeSolid();
groove.Thickness = cd.height;
groove.Thickness = Math.min(cd.height, br.Thickness);
groove.ContourCurve = contourNode.contour.Curve;
groove.KnifeRadius = cd.knifeRad;
groove.GroovesAddLength = cd.addLen;
@ -584,7 +590,6 @@ export class BoardConfigModal extends React.Component<BoardConfigProps, {}>{
}
br.GrooveCheckAllAutoSplit();
br.Update();
}
};
private AddModeling2 = (contourMap: Map<number, Polyline[]>, applyMatrix: Matrix4) =>

@ -1,7 +1,7 @@
import { Vector3 } from "three";
import { DynamicInputManage } from "./DynamicInputManage";
import { PromptBlock } from "./PromptBlock";
import { RealDynamicInput } from "./RealDynamicInput";
import { DynamicInputManage } from "./DynamicInputManage";
import { Vector3, Box3 } from "three";
/**
*

Loading…
Cancel
Save