!1804 重构:新的板件交集算法,影响:板件干涉,板件切割(非平行垂直时)

pull/1805/MERGE
ChenX 3 years ago
parent 9485fa687c
commit 60d3738cc7

@ -152,6 +152,19 @@ test('布尔运算导致的切割错误', () =>
{
let d =
{ "file": [2, "Board", 8, 2, 101, false, 1, 11, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 145.70588235294053, 55.24369747899152, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 145.70588235294053, 55.24369747899152, 0, 1], 0, 3, 2000, 600, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [600, 0], 0, [600, 2000], 0, [0, 2000], 0, true, 2, 3, 2000, 9, 5, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [9, 0], 0, [9, 2000], 0, [0, 2000], 0, true, 0, 3, 6, 1, 1, 0, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 158.70588235294053, 628.2436974789915, 0, 1], 3, 18, 588.3901659112175, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [588.3901659112175, 0], 0, [588.3901659112175, 18], 0, [0, 18], 0, true, 0, 3, 0, 0, 0, 0, 0, [0, 0.9659258262890683, -0.25881904510252074, 0, 0, 0.25881904510252074, 0.9659258262890683, 0, 1, 0, 0, 0, 145.7058823529403, 55.24369747899152, 990.9999999999998, 1], 3, 0, 0, 0, 0, 0, 10, 1, "左侧板", "主卧", "下柜", "", "", "", 0, 0, "测试", 2, 0, "1", "1", "1", "1", "", "", "", 4, "测试", "测试", "测试", "测试", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, 0, 0, "Board", 8, 2, 100, false, 1, 2, 0, [0, 0.9659258262890683, -0.25881904510252074, 0, -1, 0, 0, 0, 0, 0.25881904510252074, 0.9659258262890683, 0, 1327.7058823529405, 55.24369747899152, 990.9999999999998, 1], 0, 0, true, [1, 0, 0, 0, 0, 0.9659258262890683, -0.25881904510252074, 0, 0, 0.25881904510252074, 0.9659258262890683, 0, 163.70588235294053, -201.24597621760648, 33.76750614753291, 1], 0, 3, 1364, 588.3901659112173, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [588.3901659112173, 0], 0, [588.3901659112173, 1364], 0, [0, 1364], 0, true, 0, 3, 0, 0, 0, 0, 0, 10, 0, "层板", "主卧", "下柜", "", "", "", 0, 1, "测试", 2, 0, "1", "1", "1", "1", "", "", "", 4, "测试", "测试", "测试", "测试", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, 0, 0], "basePt": { "x": -36.294117647059466, "y": 55.24369747899152, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] };
let [br0, br1] = LoadBoardsFromFileData(d) as Board[];
let splitBrs = CuttingBoard(br0, [br1]);
splitBrs.push(br0);
for (let b of splitBrs)
{
expect(b.Volume).toMatchNumberSnapshot();
}
});
test('板件切割因为csg计算错误导致的切割错误', () =>
{
let d =
{ "file": [2, "Board", 8, 2, 103, false, 1, 2, 0, [0, 0.9999999999999999, 0, 0, -0.8860509631594647, 0, -0.4635878457036862, 0, -0.46358784570377454, 0, 0.8860509631594184, 0, 1762.4153704413025, 0, 1040.0002246857875, 1], 0, 0, true, [0.8860509631594647, 0, 0.4635878457036862, 0, 0, 0.9999999999999999, 0, 0, -0.46358784570377454, 0, 0.8860509631594184, 0, 1762.4153704413025, -18, 1040.0002246857875, 1], 0, 3, 1979.65, 882.0000000000001, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -18, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -18, 0, 0, 1], 0, 2, 4, [18, 0], 0, [900.0000000000001, 0], 0, [900.0000000000001, 1979.65], 0, [18, 1979.65], 0, true, 0, 3, 0, 0, 0, 0, 0, 10, 0, "层板", "", "", "", "", "", 0, 1, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, 0, 0, "Board", 8, 2, 102, false, 1, 11, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1166.6250332856093, 2, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1166.6250332856093, -18, 0, 1], 0, 3, 738.2, 880, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -20, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -20, 0, 0, 1], 0, 2, 4, [20, 0], 0, [900, 0], 0, [900, 738.2], 0, [20, 738.2], 0, true, 2, 3, 7, 738.2, 5.250000000116415, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -5.25, 0, 0, 1], 0, 0, true, [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 881.5, 0, 1], 0, 2, 4, [743.4499999999998, 7], 0, [5.25, 7], 0, [5.25, 0], 0, [743.45, 0], 0, true, 0, 3, 6, 1, 0.15, 0, 0, [0, 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 1179.375033285493, 863.5, 0, 1], 3, 7, 737.7971530380617, 5.2500000000001705, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -5.250000000059116, 0, 0, 1], 0, 0, true, [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 8.881784197001252e-16, 881.5, 0, 1], 0, 2, 4, [5.250000000059116, 0], 0, [743.0471530381208, 0], 0, [743.0471530381208, 7], 0, [5.250000000059117, 7], 0, true, 0, 3, 6, 1, 0.15, 0, 0, [0, 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 1166.6250332856093, 863.5, 0, 1], 3, 0, 0, 0, 0, 0, 10, 1, "立板", "", "", "", "", "", 0, 1, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, 0, 0], "basePt": { "x": 0, "y": 0, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] };
let [br0, br1] = LoadBoardsFromFileData(d) as Board[];
let splitBrs = CuttingBoard(br0, [br1]);

@ -32,6 +32,8 @@ exports[`板件与板件切割_分裂成多个 4`] = `"5558571.43374"`;
exports[`板件分裂后槽需要在正确的位置 1`] = `"6248188.54979"`;
exports[`板件切割因为csg计算错误导致的切割错误 1`] = `"31269963.76655"`;
exports[`板件切割测试2 1`] = `"1081121.00089"`;
exports[`板件切割测试2 2`] = `"1707974.98308"`;

@ -1,7 +1,7 @@
import { Line } from "three";
import { ExtrudeGeometryBuilder } from "../../src/Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";
import { RenderType } from "../../src/GraphicsSystem/RenderType";
import { LoadBoardsFromFileData } from "../Utils/LoadEntity.util";
import { ExtrudeGeometryBuilder } from "../../src/Geometry/ExtrudeEdgeGeometry2";
test('EdgeGeometry生成', () =>
{

@ -95,6 +95,7 @@
"@blueprintjs/core": "^3.52.0",
"@blueprintjs/popover2": "^0.12.9",
"@blueprintjs/table": "^3.9.13",
"@jscad/modeling": "^2.7.1",
"@types/react-virtualized-auto-sizer": "^1.0.1",
"@types/react-window": "^1.8.5",
"blueimp-md5": "^2.19.0",
@ -107,9 +108,9 @@
"mobx": "^5.15.7",
"mobx-react": "^6.3.1",
"monotone-convex-hull-2d": "^1.0.1",
"polylabel": "^1.1.0",
"p-queue": "^6.6.2",
"pako": "^1.0.11",
"polylabel": "^1.1.0",
"react": "^17.0.2",
"react-color": "^2.19.3",
"react-dom": "^17.0.2",

@ -174,7 +174,10 @@ export function Entitys2Data(ents: Iterable<Entity>): Data
{
let index = d.Entitys.length;
if (e instanceof Board)
if (e.SplitExtrudes)
arrayPushArray(d.Entitys, e.SplitExtrudes.map(e => ConvertBoard2Data(e)));
else
d.Entitys.push(ConvertBoard2Data(e));
else if (e instanceof SweepSolid)
d.Entitys.push(ConverSweep2Data(e));
else if (e instanceof Region)

@ -1,11 +1,8 @@
import { Vector3 } from "three";
import { TestDraw } from "./TestUtil";
import { app } from "../../ApplicationServices/Application";
import { Board } from "../../DatabaseServices/Entity/Board";
import { PromptStatus } from "../../Editor/PromptResult";
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";
import { HotCMD } from "../../Hot/HotCommand";
import { MoveMatrix } from "../../Geometry/GeUtils";
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeEdgeGeometry2";
@HotCMD
export class Command_TestTape
{

@ -0,0 +1,33 @@
import { Geom3 } from "@jscad/modeling/src/geometries/types";
import { Mat4 } from "@jscad/modeling/src/maths/mat4";
import { Vec3 } from "@jscad/modeling/src/maths/vec3";
import { intersect } from "@jscad/modeling/src/operations/booleans";
import { Matrix4 } from "three";
export interface Geom3Res
{
polygons: Array<{
vertices: Array<Vec3>,
plane: [number, number, number, number];
}>;
}
export function CSGIntersect(csg1: Geom3, csg2: Geom3, csg2tranfrom: Matrix4): Geom3Res
{
let bak1 = csg1.polygons;
let bak2 = csg2.polygons;
let bakMtx = csg2.transforms;
csg2.transforms = csg2tranfrom.elements as Mat4;
csg1.polygons = bak1.concat();
csg2.polygons = bak2.concat();
let res = intersect(csg1, csg2) as unknown as Geom3Res;
csg1.polygons = bak1;
csg2.polygons = bak2;
csg2.transforms = bakMtx;
return res;
}

@ -1,8 +1,7 @@
import { Geom3 } from "@jscad/modeling/src/geometries/types";
import { Box3, Material, Mesh } from "three";
import { CSG } from "../csg/core/CSG";
import { FuzzyCSGFactory } from "../csg/core/FuzzyFactory3d";
import { CSG2Geometry, Geometry2CSG } from "../csg/core/Geometry2CSG";
import { Plane } from "../csg/core/math/Plane";
import { FuzzyFactory } from "../csg/core/FuzzyFactory";
import { CSG2Geometry2, Geometry2CSG2 } from "../csg/core/Geometry2CSG";
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid";
import { Board } from "../DatabaseServices/Entity/Board";
@ -13,8 +12,10 @@ import { ObjectId } from "../DatabaseServices/ObjectId";
import { ProcessingGroupRecord } from "../DatabaseServices/ProcessingGroup/ProcessingGroupRecord";
import { TemplateLatticeRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateLatticeRecord";
import { TemplateWineRackRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateWineRackRecord";
import { BoxIsSolid } from "../Geometry/Box";
import { OBB } from "../Geometry/OBB/obb";
import { ColorMaterial } from "./ColorPalette";
import { CSGIntersect } from "./CSGIntersect";
import { Log } from "./Log";
import { Sleep } from "./Sleep";
@ -162,16 +163,20 @@ export class CheckInterfereTool
continue;
}
let interCsg = csg1.intersect(csg2.transform1(e1.OCSInv.multiply(e2.OCSNoClone)));
let planeSet = new Set<Plane>();
let f = new FuzzyCSGFactory;
let interCsg = CSGIntersect(csg1, csg2, e1.OCSInv.multiply(e2.OCSNoClone));
let planeSet = new Set<number[]>();
let f = new FuzzyFactory;
for (let polygon of interCsg.polygons)
planeSet.add(f.getPlane(polygon.plane));
planeSet.add(f.lookupOrCreate(polygon.plane, polygon.plane));
if (planeSet.size >= 4)//最少4个面围成一个三维实体
{
let geo = CSG2Geometry(interCsg).applyMatrix4(e1.OCSNoClone);
let geo = CSG2Geometry2(interCsg);
geo.computeBoundingBox();
if (!BoxIsSolid(geo.boundingBox, 0.1))
continue;
geo.applyMatrix4(e1.OCSNoClone);
let mesh = new Mesh(geo, this._MeshMaterial);
objMap.push([mesh, [e1, e2]]);
}
@ -189,10 +194,10 @@ export class CheckInterfereTool
this.objMap.length = 0;
}
csgCache: Map<Entity, CSG> = new Map();
csgCache: Map<Entity, Geom3> = new Map();
private GetCSG(en: Solid3D)
{
let csg: CSG = this.csgCache.get(en);
let csg: Geom3 = this.csgCache.get(en);
if (csg) return csg;
if (en instanceof ExtrudeSolid)
@ -202,7 +207,7 @@ export class CheckInterfereTool
csg = en.CSG;
}
else
csg = Geometry2CSG(en.MeshGeometry);
csg = Geometry2CSG2(en.MeshGeometry);
this.csgCache.set(en, csg);
return csg;

@ -8,8 +8,8 @@ import { Vector2ApplyMatrix4 } from "../../Common/Matrix4Utils";
import { ObjectSnapMode } from "../../Editor/ObjectSnapMode";
import { Box3Ext } from "../../Geometry/Box";
import { FastWireframe2 } from "../../Geometry/CreateWireframe";
import { GenerateExtrudeEdgeGeometry } from "../../Geometry/ExtrudeEdgeGeometry";
import { AsVector3, equaln, equalv2, equalv3, ZeroVec } from "../../Geometry/GeUtils";
import { GenerateExtrudeEdgeGeometry } from "../../Geometry/SimpleExtrudeEdgeGeometry";
import { ScaleUV } from "../../Geometry/UVUtils";
import { RenderType } from "../../GraphicsSystem/RenderType";
import { AutoRecord } from "../AutoRecord";

@ -69,7 +69,7 @@ export class CompositeEntity extends Entity
{
let cloneE = e.Clone();
cloneE.Material = e.Material;
return cloneE.ApplyMatrix(this.OCS);
return cloneE.ApplyMatrix(this.OCSNoClone);
});
}
Traverse(callback: (arg0: Entity) => void)

@ -1,24 +1,25 @@
import { Geom3 } from '@jscad/modeling/src/geometries/types';
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";
import { ColorMaterial } from "../../Common/ColorPalette";
import { CSGIntersect } from '../../Common/CSGIntersect';
import { equalCurve, PolylineSpliteRect } from "../../Common/CurveUtils";
import { DisposeThreeObj, Object3DRemoveAll } from "../../Common/Dispose";
import { Log } from "../../Common/Log";
import { matrixSetVector, reviseMirrorMatrix, Vector2ApplyMatrix4 } from "../../Common/Matrix4Utils";
import { Status, UpdateDraw } from "../../Common/Status";
import { CSG } from "../../csg/core/CSG";
import { Geometry2CSG } from "../../csg/core/Geometry2CSG";
import { Geometry2CSG2 } from "../../csg/core/Geometry2CSG";
import { ObjectSnapMode } from "../../Editor/ObjectSnapMode";
import { boardUVGenerator } from "../../Geometry/BoardUVGenerator";
import { Box3Ext } from "../../Geometry/Box";
import { BSPGroupParse } from "../../Geometry/BSPGroupParse";
import { BSPGroupParse } from '../../Geometry/BSPGroupParse';
import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils";
import { FastExtrudeEdgeGeometry, FastWireframe } from "../../Geometry/CreateWireframe";
import { EdgesGeometry } from "../../Geometry/EdgeGeometry";
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeEdgeGeometry2";
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";
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";
@ -1072,13 +1073,13 @@ export class ExtrudeSolid extends Entity
/**
* Draw,bsp
*/
private csg: CSG;
get CSG()
private csg: Geom3;
get CSG(): Geom3
{
if (this.csg)
return this.csg;
if (this.csg) return this.csg;
this.csg = Geometry2CSG(this.MeshGeometry);
this.csg = Geometry2CSG2(this.MeshGeometry);
return this.csg;
}
@ -1158,8 +1159,12 @@ export class ExtrudeSolid extends Entity
let m = new Matrix4().makeBasis(xv, yv, zv).copyPosition(this.OCS);
let mi = new Matrix4().getInverse(m).multiply(this.OCS);
let interBSP = this.CSG.intersect(target.CSG.transform1(this.OCSInv.multiply(target.OCS)));
let topology = new BSPGroupParse(interBSP);
let interCSG = CSGIntersect(this.CSG, target.CSG, this.OCSInv.multiply(target.OCSNoClone));
//测试绘制
// TestDraw(new Mesh(CSG2Geometry2(interBSP), ColorMaterial.GetConceptualMaterial(1, DoubleSide)));
let topology = new BSPGroupParse(interCSG);
let grooves: ExtrudeSolid[] = [];
for (let pts of topology.Parse())
{

@ -1,9 +1,9 @@
import { CompositeEntity } from "../Entity/CompositeEntity";
import { Factory } from "../CADFactory";
import { AutoRecord } from "../AutoRecord";
import { DefaultCompositeMetalsOption } from "../../Editor/DefaultConfig";
import { ICompHardwareOption } from "../../UI/Components/RightPanel/RightPanelInterface";
import { AutoRecord } from "../AutoRecord";
import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler";
import { DefaultCompositeMetalsOption } from "../../Editor/DefaultConfig";
import { CompositeEntity } from "../Entity/CompositeEntity";
import { Entity } from "../Entity/Entity";
import { ObjectId } from "../ObjectId";
@ -13,30 +13,32 @@ export class HardwareCompositeEntity extends CompositeEntity
@AutoRecord HardwareOption: ICompHardwareOption = { ...DefaultCompositeMetalsOption };
@AutoRecord DataList: [string, string][] = [];
@AutoRecord RelevanceBoards: ObjectId[] = [];
constructor()
{
super();
}
GetAllEntity(isHole: boolean = false, filter?: (e: Entity) => boolean)
/**
*
* @param [checkIsHole=false] true: false:
* @param [checkFilter]
* @returns
*/
GetAllEntity(checkIsHole: boolean = false, checkFilter?: (e: Entity) => boolean)
{
let holes: Entity[] = [];
for (let e of this.Entitys)
{
if (e instanceof HardwareCompositeEntity)
{
if (!isHole || e.HardwareOption.isHole)
holes.push(...e.GetAllEntity(isHole, filter).map(h => h.ApplyMatrix(this.OCS)));
if (!checkIsHole || e.HardwareOption.isHole)
holes.push(...e.GetAllEntity(checkIsHole, checkFilter).map(h => h.ApplyMatrix(this.OCSNoClone)));
}
else
{
if (!filter || filter(e))
{
holes.push(e.Clone().ApplyMatrix(this.OCS));
}
if (!checkFilter || checkFilter(e))
holes.push(e.Clone().ApplyMatrix(this.OCSNoClone));
}
}
return holes;
}
protected _ReadFile(file: CADFiler)
{
super._ReadFile(file);
@ -83,6 +85,7 @@ export class HardwareCompositeEntity extends CompositeEntity
}
}
}
//对象将自身数据写入到文件.
WriteFile(file: CADFiler)
{

@ -1,4 +1,4 @@
import { BufferGeometry, Float32BufferAttribute, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Vector3, Box3 } from "three";
import { BufferGeometry, Float32BufferAttribute, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Vector3 } from "three";
import { ColorMaterial } from "../Common/ColorPalette";
import { FixedNotZero } from "../Common/Utils";
import { AutoRecord } from "../DatabaseServices/AutoRecord";
@ -7,11 +7,11 @@ 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 { Box3Ext } from "../Geometry/Box";
import { XAxis, XAxisN, YAxis, YAxisN, ZAxis, ZeroVec } from "../Geometry/GeUtils";
import { GenerateBoxEdgeGeometry } from "../Geometry/SimpleExtrudeEdgeGeometry";
import { RenderType } from "../GraphicsSystem/RenderType";
import { ObjectSnapMode } from "./ObjectSnapMode";
import { Box3Ext } from "../Geometry/Box";
const EmptyArray = [];

@ -1,8 +1,8 @@
import { Poly3 } from "@jscad/modeling/src/geometries/types";
import { Vec3 } from "@jscad/modeling/src/maths/vec3";
import { Vector3 } from "three";
import { Geom3Res } from "../Common/CSGIntersect";
import { ToFixed } from "../Common/Utils";
import { CSG } from "../csg/core/CSG";
import { Polygon } from "../csg/core/math/Polygon3";
import { Vec3 } from "./IVec3";
/**
* THREEBSP(CSG) .
@ -15,15 +15,15 @@ import { Vec3 } from "./IVec3";
*/
export class BSPGroupParse
{
constructor(bsp?: CSG, public fractionDigits = 1)
constructor(bsp?: Geom3Res, public fractionDigits = 1)
{
if (bsp)
for (let poly of bsp.polygons)
this.Add(poly);
}
Add(poly: Polygon)
Add(poly: Poly3)
{
let strs = poly.vertices.map(p => this.GenerateP(p.pos));
let strs = poly.vertices.map(p => this.GenerateP(p));
let str0 = strs[0];
let s0 = this.Get(str0);
for (let i = 1; i < strs.length; i++)
@ -51,7 +51,7 @@ export class BSPGroupParse
let pts = [...cset].map(str =>
{
let v3 = this.vecMap.get(str);
return new Vector3(v3.x, v3.y, v3.z);
return new Vector3().fromArray(v3);
});
res.push(pts);
}
@ -81,10 +81,10 @@ export class BSPGroupParse
}
}
}
private vecMap = new Map();
private vecMap: Map<string, Vec3> = new Map();
private GenerateP(v: Vec3)
{
let str = [v.x, v.y, v.z].map(n => ToFixed(n, this.fractionDigits)).join(",");
let str = v.map(n => ToFixed(n, this.fractionDigits)).join(",");
this.vecMap.set(str, v);
return str;
}

@ -25,7 +25,7 @@ export class Box3Ext extends Box3
//每个轴的大小必须大于最小的size
isSolid(minSize = 1)
{
return this.getSize(new Vector3()).toArray().every(x => x > minSize);
return BoxIsSolid(this, minSize);
}
substract(b: Box3Ext, spaceType: SplitType)
{
@ -72,3 +72,10 @@ export function IntersectBox2(box1: Box3, box2: Box3, fuzz = 1e-3)
return box2.max.x < box1.min.x - fuzz || box2.min.x > box1.max.x + fuzz ||
box2.max.y < box1.min.y - fuzz || box2.min.y > box1.max.y + fuzz ? false : true;
}
let size = new Vector3;
export function BoxIsSolid(box: Box3, minSize = 1)
{
box.getSize(size);
return size.x > minSize && size.y > minSize && size.z > minSize;
}

@ -0,0 +1,25 @@
import { geom2 } from "@jscad/modeling/src/geometries";
import { Geom3 } from "@jscad/modeling/src/geometries/geom3/";
import { Mat4 } from "@jscad/modeling/src/maths/mat4";
import { subtract } from "@jscad/modeling/src/operations/booleans";
import { extrudeLinear } from "@jscad/modeling/src/operations/extrusions";
import { ExtrudeSolid } from "../../DatabaseServices/Entity/Extrude";
import { SplitCurveParams } from "./SplitCurveParams";
//使用这个算法会有性能问题 用webworker会好一点,不到必要时刻不使用(例如切斜边 和 二维刀路造型)
export function ExtBuildCSG(ext: ExtrudeSolid): Geom3
{
let c = ext.ContourCurve;
let pts = SplitCurveParams(c).map(p => c.GetPointAtParam(p));
let geo2 = geom2.fromPoints(pts.map(p => [p.x, p.y]));
let geo = extrudeLinear({ height: ext.Thickness }, geo2);
let grooveGeo: Geom3[] = ext.Grooves.map(ExtBuildCSG);
geo.transforms = ext.OCSNoClone.elements as Mat4;
if (grooveGeo.length)
return subtract(geo, grooveGeo);
else
return geo;
}

@ -1,23 +1,23 @@
import Flatbush from 'flatbush';
import { Box3, BufferGeometry, Float32BufferAttribute, MathUtils, Matrix4, Shape as TShape, ShapeUtils, Vector3 } from "three";
import { arrayPushArray, arrayRemoveDuplicateBySort, arraySortByNumber } from "../Common/ArrayExt";
import { curveLinkGroup } from "../Common/CurveUtils";
import { clamp, FixIndex } from "../Common/Utils";
import { Contour } from "../DatabaseServices/Contour";
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, MaxDrawGrooveCount } from "../DatabaseServices/Entity/Extrude";
import { Line } from "../DatabaseServices/Entity/Line";
import { Polyline, PolylineProps } from "../DatabaseServices/Entity/Polyline";
import { IntersectOption, IntersectResult } from "../GraphicsSystem/IntersectWith";
import { LinesType } from "../UI/Store/BoardInterface";
import { IntersectsBox } from "./Box";
import { CreateContour2 } from "./CreateContour2";
import { FastOffset } from "./FastOffset";
import { AsVector2, equaln, equalv2, equalv3, IdentityMtx4 } from "./GeUtils";
import { RegionParse } from "./RegionParse";
import { arrayPushArray, arrayRemoveDuplicateBySort, arraySortByNumber } from "../../Common/ArrayExt";
import { curveLinkGroup } from "../../Common/CurveUtils";
import { FixIndex } from "../../Common/Utils";
import { Contour } from "../../DatabaseServices/Contour";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Curve } from "../../DatabaseServices/Entity/Curve";
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";
import { LinesType } from "../../UI/Store/BoardInterface";
import { IntersectsBox } from "../Box";
import { CreateContour2 } from "../CreateContour2";
import { FastOffset } from "../FastOffset";
import { AsVector2, equaln, equalv2, equalv3, IdentityMtx4 } from "../GeUtils";
import { RegionParse } from "../RegionParse";
import { SplitCurveParams } from './SplitCurveParams';
export enum DepthType
{
@ -557,52 +557,6 @@ export class CurveTapeShape
}
}
const SplitLength = 4;
const MinSplitCount = 12;
const MaxSplitCount = 360;
function SplitCurveParams(cu: ExtureContourCurve): number[]
{
let xparams: number[] = [];
if (cu instanceof Circle)
{
let splitCount = cu.Radius / SplitLength;
splitCount = clamp(Math.floor(splitCount), MinSplitCount, MaxSplitCount);
for (let i = 0; i < splitCount; i++)
xparams.push(i / splitCount);
}
else
//分段1
for (let i = 0; i < cu.EndParam; i++)
{
xparams.push(i);
if (cu.GetBuilgeAt(i) !== 0)
{
let arc = cu.GetCurveAtIndex(i) as Arc;
let splitCount = arc.Radius / SplitLength;
splitCount = clamp(Math.floor(splitCount), MinSplitCount, MaxSplitCount);
if (splitCount === 0) continue;
let a = Math.PI * 2 / splitCount;
let params: number[] = [];
for (let j = 0; j < splitCount; j++)
{
let param = arc.GetParamAtAngle(a * j);
if (arc.ParamOnCurve(param))
params.push(param);
}
arraySortByNumber(params);
if (params.length === 0) continue;
for (let p of params)
{
if (p > 1e-5 && p < 9.99999)
xparams.push(p + i);
}
}
}
xparams.push(cu.EndParam);
return xparams;
}
/**
* 线()
@ -968,14 +922,14 @@ interface CurveSegs
reverse: Curve[];//反向
}
function binarySearch(ar: number[], el: number): number
function binarySearch(arr: number[], el: number): number
{
let m = 0;
let n = ar.length - 1;
let n = arr.length - 1;
while (m <= n)
{
let k = (n + m) >> 1;
let cmp = (el - ar[k]);
let cmp = (el - arr[k]);
if (cmp > 1e8)
m = k + 1;
else if (cmp < -1e8)

@ -0,0 +1,61 @@
import { arraySortByNumber } from "../../Common/ArrayExt";
import { clamp } from "../../Common/Utils";
import { Arc } from "../../DatabaseServices/Entity/Arc";
import { Circle } from "../../DatabaseServices/Entity/Circle";
import { ExtureContourCurve } from "../../DatabaseServices/Entity/Extrude";
const ARC_SplitLength = 4;//圆的分段长度
const Arc_MinSplitCount = 12;//圆的最小分段个数
const ARC_MaxSplitCount = 360;//圆的最大分段个数
/**
*
* @param cu
* @returns
*/
export function SplitCurveParams(cu: ExtureContourCurve): number[]
{
let xparams: number[] = [];
if (cu instanceof Circle)
{
let splitCount = cu.Radius / ARC_SplitLength;
splitCount = clamp(Math.floor(splitCount), Arc_MinSplitCount, ARC_MaxSplitCount);
for (let i = 0; i < splitCount; i++)
xparams.push(i / splitCount);
}
else
//分段1
for (let i = 0; i < cu.EndParam; i++)
{
xparams.push(i);
if (cu.GetBuilgeAt(i) !== 0)
{
let arc = cu.GetCurveAtIndex(i) as Arc;
let splitCount = arc.Radius / ARC_SplitLength;
splitCount = clamp(Math.floor(splitCount), Arc_MinSplitCount, ARC_MaxSplitCount);
if (splitCount === 0)
continue;
let a = Math.PI * 2 / splitCount;
let params: number[] = [];
for (let j = 0; j < splitCount; j++)
{
let param = arc.GetParamAtAngle(a * j);
if (arc.ParamOnCurve(param))
params.push(param);
}
arraySortByNumber(params);
if (params.length === 0)
continue;
for (let p of params)
{
if (p > 1e-5 && p < 9.99999)
xparams.push(p + i);
}
}
}
xparams.push(cu.EndParam);
return xparams;
}

@ -3,6 +3,7 @@ import { arrayLast, arrayPushArray } from "../Common/ArrayExt";
import { FixIndex } from "../Common/Utils";
import { equalv3 } from "./GeUtils";
//使用轮廓点表快速拉伸
export function GenerateExtrudeEdgeGeometry(contourPoints: Vector3[][], height: number): BufferGeometry
{
let pts: Vector3[] = [];
@ -12,6 +13,7 @@ export function GenerateExtrudeEdgeGeometry(contourPoints: Vector3[][], height:
return geo;
}
//拉伸点表成为Geom
function GenerateExtrudeEdgeGeometryPoints(contourPoints: Vector3[], height: number): Vector3[]
{
if (contourPoints.length < 3) return [];
@ -27,6 +29,7 @@ function GenerateExtrudeEdgeGeometryPoints(contourPoints: Vector3[], height: num
return pts;
}
//创建一个盒子几何体
export function GenerateBoxEdgeGeometry(length: number, width: number, height: number): BufferGeometry
{
let pts = [new Vector3(), new Vector3(length), new Vector3(length, width), new Vector3(0, width)];

@ -23,7 +23,7 @@ import { JigUtils } from "../../../Editor/JigUtils";
import { PromptStatus } from "../../../Editor/PromptResult";
import { SelectBox, SelectType } from "../../../Editor/SelectBox";
import { CreateContours } from "../../../Geometry/CreateContour2";
import { ContourTreeNode } from "../../../Geometry/ExtrudeEdgeGeometry2";
import { ContourTreeNode } from "../../../Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";
import { AsVector2, equaln, isParallelTo, MoveMatrix } from "../../../Geometry/GeUtils";
import { BoardConfigOption, BoardProcessOption, FaceDirection, IGrooveOption, IUiOption } from '../../Store/BoardInterface';
import { RightPanelStore } from "../../Store/RightPanelStore/RightPanelStore";

@ -10,12 +10,15 @@
// Constructor:
// numdimensions: the number of parameters for each object
// for example for a 2D rectangle this would be 2
import { EPS } from "./constants";
// tolerance: The maximum difference for each parameter allowed to be considered a match
export class FuzzyFactory
{
lookuptable: {};
multiplier: number;
constructor(numdimensions: number, tolerance: number)
constructor(numdimensions: number = 3, tolerance: number = EPS)
{
this.lookuptable = {};
this.multiplier = 1.0 / tolerance;

@ -1,4 +1,8 @@
import geom3, { Geom3 } from "@jscad/modeling/src/geometries/geom3";
import { create, Poly3 } from "@jscad/modeling/src/geometries/poly3";
import { Vec3 } from "@jscad/modeling/src/maths/vec3";
import { BufferGeometry, Face3, Geometry, Vector2, Vector3 } from "three";
import { Geom3Res } from "../../Common/CSGIntersect";
import { AsVector2, AsVector3, equalv3, ZeroVec } from "../../Geometry/GeUtils";
import { CSG } from "./CSG";
import { Polygon } from "./math/Polygon3";
@ -79,6 +83,53 @@ export function CSG2Geometry(csg: CSG): Geometry
return geo;
}
export function Geometry2CSG2(geometry: Geometry | BufferGeometry): Geom3
{
if (geometry instanceof BufferGeometry)
geometry = new Geometry().fromBufferGeometry(geometry);
let polygons: Poly3[] = [];
for (let i = 0; i < geometry.faces.length; i++)
{
let face = geometry.faces[i];
let vertices: Vec3[] = [];
if (face instanceof Face3)
{
vertices.push(geometry.vertices[face.a].toArray() as Vec3);
vertices.push(geometry.vertices[face.b].toArray() as Vec3);
vertices.push(geometry.vertices[face.c].toArray() as Vec3);
}
polygons.push(create(vertices));
}
return geom3.create(polygons);
}
export function CSG2Geometry2(csg: Geom3 | Geom3Res): Geometry
{
let geo = new Geometry;
for (let poly of csg.polygons)
{
//@ts-ignore
let normal = new Vector3().fromArray(poly.plane);
let startIndex = geo.vertices.length;
for (let v of poly.vertices)
geo.vertices.push(new Vector3().fromArray(v));
for (let i = poly.vertices.length - 3; i >= 0; i--)
{
let f = new Face3(
startIndex,
startIndex + i + 1,
startIndex + i + 2,
normal);
geo.faces.push(f);
}
}
return geo;
}
function Vector3ToVector3D(v: Vector3): Vector3D
{
return new Vector3D(v.x, v.y, v.z);

@ -2,4 +2,4 @@ export * from "./DatabaseServices/Entity/Circle";
export * from "./DatabaseServices/Entity/Extrude";
export * from "./DatabaseServices/Entity/Polyline";
export * from "./DatabaseServices/Shape2";
export * from "./Geometry/ExtrudeEdgeGeometry2";
export * from "./Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";

Loading…
Cancel
Save