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

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

@ -152,6 +152,19 @@ test('布尔运算导致的切割错误', () =>
{ {
let d = 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] }; { "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 [br0, br1] = LoadBoardsFromFileData(d) as Board[];
let splitBrs = CuttingBoard(br0, [br1]); let splitBrs = CuttingBoard(br0, [br1]);

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

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

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

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

@ -1,11 +1,8 @@
import { Vector3 } from "three";
import { TestDraw } from "./TestUtil";
import { app } from "../../ApplicationServices/Application"; import { app } from "../../ApplicationServices/Application";
import { Board } from "../../DatabaseServices/Entity/Board"; import { Board } from "../../DatabaseServices/Entity/Board";
import { PromptStatus } from "../../Editor/PromptResult"; import { PromptStatus } from "../../Editor/PromptResult";
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";
import { HotCMD } from "../../Hot/HotCommand"; import { HotCMD } from "../../Hot/HotCommand";
import { MoveMatrix } from "../../Geometry/GeUtils";
import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeEdgeGeometry2";
@HotCMD @HotCMD
export class Command_TestTape 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 { Box3, Material, Mesh } from "three";
import { CSG } from "../csg/core/CSG"; import { FuzzyFactory } from "../csg/core/FuzzyFactory";
import { FuzzyCSGFactory } from "../csg/core/FuzzyFactory3d"; import { CSG2Geometry2, Geometry2CSG2 } from "../csg/core/Geometry2CSG";
import { CSG2Geometry, Geometry2CSG } from "../csg/core/Geometry2CSG";
import { Plane } from "../csg/core/math/Plane";
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole"; import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid"; import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid";
import { Board } from "../DatabaseServices/Entity/Board"; import { Board } from "../DatabaseServices/Entity/Board";
@ -13,8 +12,10 @@ import { ObjectId } from "../DatabaseServices/ObjectId";
import { ProcessingGroupRecord } from "../DatabaseServices/ProcessingGroup/ProcessingGroupRecord"; import { ProcessingGroupRecord } from "../DatabaseServices/ProcessingGroup/ProcessingGroupRecord";
import { TemplateLatticeRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateLatticeRecord"; import { TemplateLatticeRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateLatticeRecord";
import { TemplateWineRackRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateWineRackRecord"; import { TemplateWineRackRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateWineRackRecord";
import { BoxIsSolid } from "../Geometry/Box";
import { OBB } from "../Geometry/OBB/obb"; import { OBB } from "../Geometry/OBB/obb";
import { ColorMaterial } from "./ColorPalette"; import { ColorMaterial } from "./ColorPalette";
import { CSGIntersect } from "./CSGIntersect";
import { Log } from "./Log"; import { Log } from "./Log";
import { Sleep } from "./Sleep"; import { Sleep } from "./Sleep";
@ -162,16 +163,20 @@ export class CheckInterfereTool
continue; continue;
} }
let interCsg = csg1.intersect(csg2.transform1(e1.OCSInv.multiply(e2.OCSNoClone))); let interCsg = CSGIntersect(csg1, csg2, e1.OCSInv.multiply(e2.OCSNoClone));
let planeSet = new Set<number[]>();
let planeSet = new Set<Plane>(); let f = new FuzzyFactory;
let f = new FuzzyCSGFactory;
for (let polygon of interCsg.polygons) 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个面围成一个三维实体 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); let mesh = new Mesh(geo, this._MeshMaterial);
objMap.push([mesh, [e1, e2]]); objMap.push([mesh, [e1, e2]]);
} }
@ -189,10 +194,10 @@ export class CheckInterfereTool
this.objMap.length = 0; this.objMap.length = 0;
} }
csgCache: Map<Entity, CSG> = new Map(); csgCache: Map<Entity, Geom3> = new Map();
private GetCSG(en: Solid3D) private GetCSG(en: Solid3D)
{ {
let csg: CSG = this.csgCache.get(en); let csg: Geom3 = this.csgCache.get(en);
if (csg) return csg; if (csg) return csg;
if (en instanceof ExtrudeSolid) if (en instanceof ExtrudeSolid)
@ -202,7 +207,7 @@ export class CheckInterfereTool
csg = en.CSG; csg = en.CSG;
} }
else else
csg = Geometry2CSG(en.MeshGeometry); csg = Geometry2CSG2(en.MeshGeometry);
this.csgCache.set(en, csg); this.csgCache.set(en, csg);
return csg; return csg;

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

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

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

@ -1,9 +1,9 @@
import { CompositeEntity } from "../Entity/CompositeEntity"; import { DefaultCompositeMetalsOption } from "../../Editor/DefaultConfig";
import { Factory } from "../CADFactory";
import { AutoRecord } from "../AutoRecord";
import { ICompHardwareOption } from "../../UI/Components/RightPanel/RightPanelInterface"; import { ICompHardwareOption } from "../../UI/Components/RightPanel/RightPanelInterface";
import { AutoRecord } from "../AutoRecord";
import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler"; import { CADFiler } from "../CADFiler";
import { DefaultCompositeMetalsOption } from "../../Editor/DefaultConfig"; import { CompositeEntity } from "../Entity/CompositeEntity";
import { Entity } from "../Entity/Entity"; import { Entity } from "../Entity/Entity";
import { ObjectId } from "../ObjectId"; import { ObjectId } from "../ObjectId";
@ -13,30 +13,32 @@ export class HardwareCompositeEntity extends CompositeEntity
@AutoRecord HardwareOption: ICompHardwareOption = { ...DefaultCompositeMetalsOption }; @AutoRecord HardwareOption: ICompHardwareOption = { ...DefaultCompositeMetalsOption };
@AutoRecord DataList: [string, string][] = []; @AutoRecord DataList: [string, string][] = [];
@AutoRecord RelevanceBoards: ObjectId[] = []; @AutoRecord RelevanceBoards: ObjectId[] = [];
constructor()
{ /**
super(); *
} * @param [checkIsHole=false] true: false:
GetAllEntity(isHole: boolean = false, filter?: (e: Entity) => boolean) * @param [checkFilter]
* @returns
*/
GetAllEntity(checkIsHole: boolean = false, checkFilter?: (e: Entity) => boolean)
{ {
let holes: Entity[] = []; let holes: Entity[] = [];
for (let e of this.Entitys) for (let e of this.Entitys)
{ {
if (e instanceof HardwareCompositeEntity) if (e instanceof HardwareCompositeEntity)
{ {
if (!isHole || e.HardwareOption.isHole) if (!checkIsHole || e.HardwareOption.isHole)
holes.push(...e.GetAllEntity(isHole, filter).map(h => h.ApplyMatrix(this.OCS))); holes.push(...e.GetAllEntity(checkIsHole, checkFilter).map(h => h.ApplyMatrix(this.OCSNoClone)));
} }
else else
{ {
if (!filter || filter(e)) if (!checkFilter || checkFilter(e))
{ holes.push(e.Clone().ApplyMatrix(this.OCSNoClone));
holes.push(e.Clone().ApplyMatrix(this.OCS));
}
} }
} }
return holes; return holes;
} }
protected _ReadFile(file: CADFiler) protected _ReadFile(file: CADFiler)
{ {
super._ReadFile(file); super._ReadFile(file);
@ -83,6 +85,7 @@ export class HardwareCompositeEntity extends CompositeEntity
} }
} }
} }
//对象将自身数据写入到文件. //对象将自身数据写入到文件.
WriteFile(file: CADFiler) 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 { ColorMaterial } from "../Common/ColorPalette";
import { FixedNotZero } from "../Common/Utils"; import { FixedNotZero } from "../Common/Utils";
import { AutoRecord } from "../DatabaseServices/AutoRecord"; import { AutoRecord } from "../DatabaseServices/AutoRecord";
@ -7,11 +7,11 @@ import { CADFiler } from "../DatabaseServices/CADFiler";
import { Entity } from "../DatabaseServices/Entity/Entity"; import { Entity } from "../DatabaseServices/Entity/Entity";
import { TemplateRecord } from "../DatabaseServices/Template/TemplateRecord"; import { TemplateRecord } from "../DatabaseServices/Template/TemplateRecord";
import { Text, TextAligen } from "../DatabaseServices/Text/Text"; 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 { XAxis, XAxisN, YAxis, YAxisN, ZAxis, ZeroVec } from "../Geometry/GeUtils";
import { GenerateBoxEdgeGeometry } from "../Geometry/SimpleExtrudeEdgeGeometry";
import { RenderType } from "../GraphicsSystem/RenderType"; import { RenderType } from "../GraphicsSystem/RenderType";
import { ObjectSnapMode } from "./ObjectSnapMode"; import { ObjectSnapMode } from "./ObjectSnapMode";
import { Box3Ext } from "../Geometry/Box";
const EmptyArray = []; const EmptyArray = [];

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

@ -25,7 +25,7 @@ export class Box3Ext extends Box3
//每个轴的大小必须大于最小的size //每个轴的大小必须大于最小的size
isSolid(minSize = 1) isSolid(minSize = 1)
{ {
return this.getSize(new Vector3()).toArray().every(x => x > minSize); return BoxIsSolid(this, minSize);
} }
substract(b: Box3Ext, spaceType: SplitType) 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 || 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; 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 Flatbush from 'flatbush';
import { Box3, BufferGeometry, Float32BufferAttribute, MathUtils, Matrix4, Shape as TShape, ShapeUtils, Vector3 } from "three"; import { Box3, BufferGeometry, Float32BufferAttribute, MathUtils, Matrix4, Shape as TShape, ShapeUtils, Vector3 } from "three";
import { arrayPushArray, arrayRemoveDuplicateBySort, arraySortByNumber } from "../Common/ArrayExt"; import { arrayPushArray, arrayRemoveDuplicateBySort, arraySortByNumber } from "../../Common/ArrayExt";
import { curveLinkGroup } from "../Common/CurveUtils"; import { curveLinkGroup } from "../../Common/CurveUtils";
import { clamp, FixIndex } from "../Common/Utils"; import { FixIndex } from "../../Common/Utils";
import { Contour } from "../DatabaseServices/Contour"; import { Contour } from "../../DatabaseServices/Contour";
import { Arc } from "../DatabaseServices/Entity/Arc"; import { Board } from "../../DatabaseServices/Entity/Board";
import { Board } from "../DatabaseServices/Entity/Board"; import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Circle } from "../DatabaseServices/Entity/Circle"; import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Curve } from "../DatabaseServices/Entity/Curve"; import { ExtrudeSolid, ExtureContourCurve, MaxDrawGrooveCount } from "../../DatabaseServices/Entity/Extrude";
import { ExtrudeSolid, ExtureContourCurve, MaxDrawGrooveCount } from "../DatabaseServices/Entity/Extrude"; import { Line } from "../../DatabaseServices/Entity/Line";
import { Line } from "../DatabaseServices/Entity/Line"; import { Polyline, PolylineProps } from "../../DatabaseServices/Entity/Polyline";
import { Polyline, PolylineProps } from "../DatabaseServices/Entity/Polyline"; import { IntersectOption, IntersectResult } from "../../GraphicsSystem/IntersectWith";
import { IntersectOption, IntersectResult } from "../GraphicsSystem/IntersectWith"; import { LinesType } from "../../UI/Store/BoardInterface";
import { LinesType } from "../UI/Store/BoardInterface"; import { IntersectsBox } from "../Box";
import { IntersectsBox } from "./Box"; import { CreateContour2 } from "../CreateContour2";
import { CreateContour2 } from "./CreateContour2"; import { FastOffset } from "../FastOffset";
import { FastOffset } from "./FastOffset"; import { AsVector2, equaln, equalv2, equalv3, IdentityMtx4 } from "../GeUtils";
import { AsVector2, equaln, equalv2, equalv3, IdentityMtx4 } from "./GeUtils"; import { RegionParse } from "../RegionParse";
import { RegionParse } from "./RegionParse"; import { SplitCurveParams } from './SplitCurveParams';
export enum DepthType 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[];//反向 reverse: Curve[];//反向
} }
function binarySearch(ar: number[], el: number): number function binarySearch(arr: number[], el: number): number
{ {
let m = 0; let m = 0;
let n = ar.length - 1; let n = arr.length - 1;
while (m <= n) while (m <= n)
{ {
let k = (n + m) >> 1; let k = (n + m) >> 1;
let cmp = (el - ar[k]); let cmp = (el - arr[k]);
if (cmp > 1e8) if (cmp > 1e8)
m = k + 1; m = k + 1;
else if (cmp < -1e8) 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;
}

@ -1,34 +1,37 @@
import { BufferGeometry, Vector3 } from "three"; import { BufferGeometry, Vector3 } from "three";
import { arrayLast, arrayPushArray } from "../Common/ArrayExt"; import { arrayLast, arrayPushArray } from "../Common/ArrayExt";
import { FixIndex } from "../Common/Utils"; import { FixIndex } from "../Common/Utils";
import { equalv3 } from "./GeUtils"; import { equalv3 } from "./GeUtils";
export function GenerateExtrudeEdgeGeometry(contourPoints: Vector3[][], height: number): BufferGeometry //使用轮廓点表快速拉伸
{ export function GenerateExtrudeEdgeGeometry(contourPoints: Vector3[][], height: number): BufferGeometry
let pts: Vector3[] = []; {
for (let cs of contourPoints) let pts: Vector3[] = [];
arrayPushArray(pts, GenerateExtrudeEdgeGeometryPoints(cs, height)); for (let cs of contourPoints)
let geo = new BufferGeometry().setFromPoints(pts); arrayPushArray(pts, GenerateExtrudeEdgeGeometryPoints(cs, height));
return geo; let geo = new BufferGeometry().setFromPoints(pts);
} return geo;
}
function GenerateExtrudeEdgeGeometryPoints(contourPoints: Vector3[], height: number): Vector3[]
{ //拉伸点表成为Geom
if (contourPoints.length < 3) return []; function GenerateExtrudeEdgeGeometryPoints(contourPoints: Vector3[], height: number): Vector3[]
if (equalv3(contourPoints[0], arrayLast(contourPoints))) {
contourPoints.pop(); if (contourPoints.length < 3) return [];
let pts: Vector3[] = []; if (equalv3(contourPoints[0], arrayLast(contourPoints)))
let hpts = contourPoints.map(p => new Vector3(p.x, p.y, height)); contourPoints.pop();
let count = contourPoints.length; let pts: Vector3[] = [];
for (let i = 0; i < count; i++) let hpts = contourPoints.map(p => new Vector3(p.x, p.y, height));
{ let count = contourPoints.length;
pts.push(contourPoints[i], contourPoints[FixIndex(i + 1, count)], hpts[i], hpts[FixIndex(i + 1, count)], contourPoints[i], hpts[i]); for (let i = 0; i < count; i++)
} {
return pts; pts.push(contourPoints[i], contourPoints[FixIndex(i + 1, count)], hpts[i], hpts[FixIndex(i + 1, count)], contourPoints[i], hpts[i]);
} }
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)]; //创建一个盒子几何体
return GenerateExtrudeEdgeGeometry([pts], height); 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)];
return GenerateExtrudeEdgeGeometry([pts], height);
}

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

@ -10,12 +10,15 @@
// Constructor: // Constructor:
// numdimensions: the number of parameters for each object // numdimensions: the number of parameters for each object
// for example for a 2D rectangle this would be 2 // 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 // tolerance: The maximum difference for each parameter allowed to be considered a match
export class FuzzyFactory export class FuzzyFactory
{ {
lookuptable: {}; lookuptable: {};
multiplier: number; multiplier: number;
constructor(numdimensions: number, tolerance: number) constructor(numdimensions: number = 3, tolerance: number = EPS)
{ {
this.lookuptable = {}; this.lookuptable = {};
this.multiplier = 1.0 / tolerance; 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 { BufferGeometry, Face3, Geometry, Vector2, Vector3 } from "three";
import { Geom3Res } from "../../Common/CSGIntersect";
import { AsVector2, AsVector3, equalv3, ZeroVec } from "../../Geometry/GeUtils"; import { AsVector2, AsVector3, equalv3, ZeroVec } from "../../Geometry/GeUtils";
import { CSG } from "./CSG"; import { CSG } from "./CSG";
import { Polygon } from "./math/Polygon3"; import { Polygon } from "./math/Polygon3";
@ -79,6 +83,53 @@ export function CSG2Geometry(csg: CSG): Geometry
return geo; 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 function Vector3ToVector3D(v: Vector3): Vector3D
{ {
return new Vector3D(v.x, v.y, v.z); 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/Extrude";
export * from "./DatabaseServices/Entity/Polyline"; export * from "./DatabaseServices/Entity/Polyline";
export * from "./DatabaseServices/Shape2"; export * from "./DatabaseServices/Shape2";
export * from "./Geometry/ExtrudeEdgeGeometry2"; export * from "./Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";

Loading…
Cancel
Save