|
|
@ -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 { Line2 } from "three/examples/jsm/lines/Line2";
|
|
|
|
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";
|
|
|
|
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";
|
|
|
|
import { arrayClone, arrayLast, arrayPushArray, arrayRemoveIf, arrayRemoveOnce, arraySortByNumber, arraySum } from "../../Common/ArrayExt";
|
|
|
|
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 { Box3Ext } from "../../Geometry/Box";
|
|
|
|
import { BSPGroupParse } from "../../Geometry/BSPGroupParse";
|
|
|
|
import { BSPGroupParse } from "../../Geometry/BSPGroupParse";
|
|
|
|
import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils";
|
|
|
|
import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils";
|
|
|
|
import { FastWireframe } from "../../Geometry/CreateWireframe";
|
|
|
|
import { FastExtrudeEdgeGeometry, FastWireframe } from "../../Geometry/CreateWireframe";
|
|
|
|
import { EdgesGeometry } from "../../Geometry/EdgeGeometry";
|
|
|
|
import { EdgesGeometry } from "../../Geometry/EdgeGeometry";
|
|
|
|
import { GenerateExtrudeEdgeGeometry } from "../../Geometry/ExtrudeEdgeGeometry";
|
|
|
|
|
|
|
|
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeEdgeGeometry2";
|
|
|
|
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 { OBB } from "../../Geometry/OBB/obb";
|
|
|
|
import { ScaleUV, ScaleUV2 } from "../../Geometry/UVUtils";
|
|
|
|
import { ScaleUV, ScaleUV2 } from "../../Geometry/UVUtils";
|
|
|
|
import { RenderType } from "../../GraphicsSystem/RenderType";
|
|
|
|
import { RenderType } from "../../GraphicsSystem/RenderType";
|
|
|
@ -45,6 +45,8 @@ import { Region } from "./Region";
|
|
|
|
export type ExtureContourCurve = Polyline | Circle;
|
|
|
|
export type ExtureContourCurve = Polyline | Circle;
|
|
|
|
export type ExtureContour = Polyline | Circle | ExtrudeSolid | Region;
|
|
|
|
export type ExtureContour = Polyline | Circle | ExtrudeSolid | Region;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const MaxDrawGrooveCount = 1000;//最大的绘制槽个数(但是还是会绘制线)
|
|
|
|
|
|
|
|
|
|
|
|
@Factory
|
|
|
|
@Factory
|
|
|
|
export class ExtrudeSolid extends Entity
|
|
|
|
export class ExtrudeSolid extends Entity
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -770,7 +772,7 @@ export class ExtrudeSolid extends Entity
|
|
|
|
case ObjectSnapMode.Tan:
|
|
|
|
case ObjectSnapMode.Tan:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let contour = this.ContourCurve.Clone();
|
|
|
|
let contour = this.ContourCurve.Clone();
|
|
|
|
contour.ApplyMatrix(this.OCS);
|
|
|
|
contour.ApplyMatrix(this.OCSNoClone);
|
|
|
|
let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform);
|
|
|
|
let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform);
|
|
|
|
|
|
|
|
|
|
|
|
contour.Position = contour.Position.add(this.Normal.multiplyScalar(this.thickness));
|
|
|
|
contour.Position = contour.Position.add(this.Normal.multiplyScalar(this.thickness));
|
|
|
@ -781,13 +783,15 @@ export class ExtrudeSolid extends Entity
|
|
|
|
for (let p of ps)
|
|
|
|
for (let p of ps)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let l = new Line(p, p.clone().setZ(this.thickness));
|
|
|
|
let l = new Line(p, p.clone().setZ(this.thickness));
|
|
|
|
l.ApplyMatrix(this.OCS);
|
|
|
|
l.ApplyMatrix(this.OCSNoClone);
|
|
|
|
pts.push(
|
|
|
|
pts.push(
|
|
|
|
...l.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform)
|
|
|
|
...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;
|
|
|
|
return pts;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -819,7 +823,7 @@ export class ExtrudeSolid extends Entity
|
|
|
|
let pts = isGrip ? this.ContourCurve.GetGripPoints() : this.ContourCurve.GetStretchPoints();
|
|
|
|
let pts = isGrip ? this.ContourCurve.GetGripPoints() : this.ContourCurve.GetStretchPoints();
|
|
|
|
let v = new Vector3(0, 0, this.thickness);
|
|
|
|
let v = new Vector3(0, 0, this.thickness);
|
|
|
|
pts.push(...pts.map(p => p.clone().add(v)));
|
|
|
|
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)
|
|
|
|
for (let g of this.grooves)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1243,30 +1247,71 @@ export class ExtrudeSolid extends Entity
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
GrooveCheckMerge()
|
|
|
|
GrooveCheckMerge()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let gs: ExtrudeSolid[] = [];
|
|
|
|
if (this.grooves.length < 2) return;
|
|
|
|
while (this.grooves.length > 0)
|
|
|
|
//生命周期:初始化->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();
|
|
|
|
let startG = this.grooves[i];
|
|
|
|
while (this.grooves.length > 0)
|
|
|
|
|
|
|
|
|
|
|
|
if (startG.TempData === undefined)//已经被使用
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
retGs.push(startG);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let stack = [startG];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let j = 0; j < stack.length; j++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//剩余的 无法合并的板件
|
|
|
|
let g = stack[j];
|
|
|
|
let remGs = this.grooves.filter(gn =>
|
|
|
|
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))
|
|
|
|
if (id <= i) return false;//(id比它小(如果能合并 早就合并了))
|
|
|
|
return g.Join(gn) === Status.False;
|
|
|
|
let gd = this.grooves[id].TempData as ExtData;
|
|
|
|
else
|
|
|
|
return gd && !gd.used;//判断被使用
|
|
|
|
return true;
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
if (remGs.length === this.grooves.length)
|
|
|
|
for (let id of ids)
|
|
|
|
break;
|
|
|
|
{
|
|
|
|
this.grooves = remGs;
|
|
|
|
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)
|
|
|
|
for (let g of this.grooves)
|
|
|
|
g.CheckContourCurve();
|
|
|
|
g.CheckContourCurve();
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1770,13 +1815,14 @@ export class ExtrudeSolid extends Entity
|
|
|
|
|
|
|
|
|
|
|
|
let ocsInv = this.OCSInv;
|
|
|
|
let ocsInv = this.OCSInv;
|
|
|
|
let alMatrix4 = new Matrix4();
|
|
|
|
let alMatrix4 = new Matrix4();
|
|
|
|
for (let g of grooves)
|
|
|
|
if (grooves.length < 1000)
|
|
|
|
{
|
|
|
|
for (let g of grooves)
|
|
|
|
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
|
|
|
|
{
|
|
|
|
let gContour = g.ContourCurve.Clone();
|
|
|
|
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
|
|
|
|
gContour.ApplyMatrix(alMatrix4);
|
|
|
|
let gContour = g.ContourCurve.Clone();
|
|
|
|
holes.push(Contour.CreateContour(gContour));
|
|
|
|
gContour.ApplyMatrix(alMatrix4);
|
|
|
|
}
|
|
|
|
holes.push(Contour.CreateContour(gContour));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let shape = new Shape(Contour.CreateContour(contour), holes);
|
|
|
|
let shape = new Shape(Contour.CreateContour(contour), holes);
|
|
|
|
|
|
|
|
|
|
|
@ -1798,7 +1844,8 @@ export class ExtrudeSolid extends Entity
|
|
|
|
let builder = new ExtrudeGeometryBuilder(this);
|
|
|
|
let builder = new ExtrudeGeometryBuilder(this);
|
|
|
|
|
|
|
|
|
|
|
|
this._MeshGeometry = builder.MeshGeometry;
|
|
|
|
this._MeshGeometry = builder.MeshGeometry;
|
|
|
|
this._EdgeGeometry = builder.EdgeGeometry;
|
|
|
|
if (grooves.length < MaxDrawGrooveCount)
|
|
|
|
|
|
|
|
this._EdgeGeometry = builder.EdgeGeometry;
|
|
|
|
this.UpdateUV(null, null);
|
|
|
|
this.UpdateUV(null, null);
|
|
|
|
|
|
|
|
|
|
|
|
return this._MeshGeometry;
|
|
|
|
return this._MeshGeometry;
|
|
|
@ -1812,36 +1859,18 @@ export class ExtrudeSolid extends Entity
|
|
|
|
|
|
|
|
|
|
|
|
if (!ExtrudeConfig.DisableRefCut)
|
|
|
|
if (!ExtrudeConfig.DisableRefCut)
|
|
|
|
this.CalcRelevanceGroove();
|
|
|
|
this.CalcRelevanceGroove();
|
|
|
|
|
|
|
|
|
|
|
|
if (this._EdgeGeometry)
|
|
|
|
if (this._EdgeGeometry)
|
|
|
|
return 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 coords = FastExtrudeEdgeGeometry(this, this.ColorIndex, 6, true);
|
|
|
|
let ocsInv = this.OCSInv;
|
|
|
|
let edgeGeo = new BufferGeometry();
|
|
|
|
let alMatrix4 = new Matrix4();
|
|
|
|
edgeGeo.setAttribute('position', new Float32BufferAttribute(coords, 3));
|
|
|
|
for (let g of this.grooves)
|
|
|
|
this._EdgeGeometry = edgeGeo;
|
|
|
|
{
|
|
|
|
return this._EdgeGeometry;
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this._MeshGeometry)
|
|
|
|
if (this._MeshGeometry)
|
|
|
|