!1081 优化:干涉检查忽略格子抽和酒格,增加单元测试

pull/1081/MERGE
ZoeLeeFZ 4 years ago committed by ChenX
parent 77f8d7eeaf
commit c98bef1396

@ -0,0 +1,27 @@
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
import { Solid3D, checkInterfereTool } from "../../src/Common/InterfereUtil";
function Check(data: any[], count: number)
{
let boards = LoadEntityFromFileData(data) as Solid3D[];
checkInterfereTool.Check(boards);
expect(checkInterfereTool.objMap.size).toBe(count);
}
describe("干涉测试", () =>
{
test("切割板件", () =>
{
let data =
[2, "Board", 8, 2, 100, false, 1, 11, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -2231.9185171823483, -4422.281844206504, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -2231.9185171823483, -4422.281844206504, 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, 4, 3, 18, 600, 9, 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, 18], 0, [0, 18], 0, true, 0, 3, 0, 0, 0, 0, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -2222.9185171823483, -4422.281844206504, 486.5, 1], 3, 18, 600, 6, 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, 18], 0, [0, 18], 0, true, 0, 3, 0, 0, 0, 0, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -2219.9185171823483, -4422.281844206504, 991, 1], 3, 1780.0698549677409, 18.000000000000455, 10, true, "Polyline", 8, 2, 0, false, 0, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -500.6580645161275, -219.93014503225913, 0, 1], 0, 0, true, [-1.8369701987210297e-16, -1, 0, 0, 1, -1.8369701987210297e-16, 0, 0, 0, 0, 1, 0, 2789.204261929938, 4347.811790451612, 0, 1], 0, 2, 4, [500.658064516128, 2000], 0, [500.6580645161275, 219.93014503225913], 0, [518.6580645161275, 219.93014503225913], 0, [518.658064516128, 2000], 0, true, 0, 3, 0, 0, 0, 0, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -2223.9185171823483, -3921.623779690376, 219.93014503225913, 1], 3, 18, 600, 9, 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, 18], 0, [0, 18], 0, true, 0, 3, 0, 0, 0, 0, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -2222.9185171823483, -4422.281844206504, 50, 1], 3, 0, 0, 0, 0, 0, 9, 1, "左侧板", "主卧", "下柜", "", "", "", 0, 0, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, "Board", 8, 2, 103, false, 1, 2, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, -1049.9185171823483, -4422.281844206504, 486.5, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1049.9185171823483, -4422.281844206504, 486.5, 1], 0, 3, 1173, 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, 1173], 0, [0, 1173], 0, true, 0, 3, 0, 0, 0, 0, 0, 9, 0, "层板", "主卧", "下柜", "", "", "", 0, 1, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 1, 101, 2, 3, 112, 113, 114, 3, 115, 116, 117, 0, 0, 0, 0, 0, 0, true];
Check(data, 0);
data = [2, "Board", 8, 2, 101, false, 1, 11, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1049.9185171823483, -4422.281844206504, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1049.9185171823483, -4422.281844206504, 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, 1, 3, 1780.0698549677409, 18.000000000000455, 10, true, "Polyline", 8, 2, 0, false, 0, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -500.6580645161275, -219.93014503225913, 0, 1], 0, 0, true, [-1.8369701987210297e-16, -1, 0, 0, 1, -1.8369701987210297e-16, 0, 0, 0, 0, 1, 0, 2789.2042619299355, 4347.811790451612, 0, 1], 0, 2, 4, [500.658064516128, 2000], 0, [500.6580645161275, 219.93014503225913], 0, [518.6580645161275, 219.93014503225913], 0, [518.658064516128, 2000], 0, true, 0, 3, 0, 0, 0, 0, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1041.9185171823483, -3921.623779690376, 219.93014503225913, 1], 3, 0, 0, 0, 0, 0, 9, 1, "右侧板", "主卧", "下柜", "", "", "", 0, 0, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 2, 102, 2, 3, 104, 105, 106, 3, 107, 108, 109, 103, 2, 3, 112, 113, 114, 3, 115, 116, 117, 0, 0, 0, 0, 0, 0, true, "Board", 8, 2, 103, false, 1, 2, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, -606.3306739002, -4422.281844206504, 486.5, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1049.9185171823483, -4422.281844206504, 486.5, 1], 0, 3, 1616.5878432821482, 600, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 443.58784328214824, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 443.58784328214824, 0, 1], 0, 2, 4, [0, -443.58784328214824], 0, [600, -443.58784328214824], 0, [600, 1173], 0, [0, 1173], 0, true, 0, 3, 0, 0, 0, 0, 0, 9, 0, "层板", "主卧", "下柜", "", "", "", 0, 1, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 1, 101, 2, 3, 112, 113, 114, 3, 115, 116, 117, 0, 0, 0, 0, 0, 0, true];
Check(data, 1);
data = [2, "Board", 8, 2, 15731, false, 1, 12, 0, [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -17103.964135848066, 173.0236442641158, 3142.826736584199, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -17103.964135848066, -20, 3142.826736584199, 1], 0, 3, 1182, 136.9763557358842, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -193.0236442641158, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -193.0236442641158, 0, 0, 1], 0, 2, 4, [193.0236442641158, 0], 0, [330, 0], 0, [330, 1182], 0, [193.0236442641158, 1182], 0, true, 0, 3, 0, 0, 0, 0, 0, 9, 1, "右侧板", "鞋柜", "鞋柜左柜", "", "", "", 0, 1, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, "Board", 8, 2, 15732, false, 1, 5, 0, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, -17256.775064763995, 283, 3142.119629803012, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -18267.25702906688, 274.6553453088989, 3142.119629803012, 1], 0, 3, 59.99999365700023, 153.5180356971141, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1010.4819643028859, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1010.4819643028859, 0, 0, 1], 0, 2, 4, [1010.4819643028859, 0], 0, [1164, 0], 0, [1164, 59.99999365700023], 0, [1010.4819643028859, 59.99999365700023], 0, true, 0, 3, 0, 0, 0, 0, 0, 9, 2, "地脚线", "鞋柜", "鞋柜左柜", "", "", "", 1, 0, "地脚线三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "地脚线三合一", "地脚线三合一", "地脚线三合一", "地脚线三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true];
Check(data, 1);
});
});

@ -1,27 +1,19 @@
import { Intent } from '@blueprintjs/core';
import { Face3, Geometry, Mesh, Vector3 } from 'three';
import { app } from '../ApplicationServices/Application';
import { DisposeThreeObj } from '../Common/Dispose';
import { FixedNotZero } from '../Common/Utils';
import { Entity } from '../DatabaseServices/Entity/Entity';
import { ExtrudeSolid } from '../DatabaseServices/Entity/Extrude';
import { PromptStatus } from '../Editor/PromptResult';
import { userConfig } from '../Editor/UserConfig';
import { Box3Ext } from '../Geometry/Box';
import { equalv3 } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/RenderType';
import { InterfereModal } from '../UI/Components/Modal/InterfereModal';
import { ColorMaterial } from './../Common/ColorPalette';
import { CSG } from './../csg/core/CSG';
import { Geometry2CSG, Vector3DToVector3 } from './../csg/core/Geometry2CSG';
import { ExtrudeHole } from './../DatabaseServices/3DSolid/ExtrudeHole';
import { SweepSolid } from './../DatabaseServices/3DSolid/SweepSolid';
import { Command } from './../Editor/CommandMachine';
import { AppToaster } from './../UI/Components/Toaster';
import { checkInterfereTool, Solid3D } from '../Common/InterfereUtil';
import { RenderType } from '../GraphicsSystem/RenderType';
//| CylinderHole | ExtrudeHole
export type Solid3D = ExtrudeSolid | SweepSolid | ExtrudeHole;
export class Interfere implements Command
{
@ -39,122 +31,9 @@ export class Interfere implements Command
if (enRes.Status === PromptStatus.Cancel) return;
let ens = enRes.SelectSet.SelectEntityList as Solid3D[];
let set1 = new Set();
let objMap: Map<Mesh, [Solid3D, Solid3D]> = new Map();
const csgCache: WeakMap<Entity, CSG> = new WeakMap();
for (let i = 0; i < ens.length; i++)
{
let e1 = ens[i];
let c1: CSG;
if (csgCache.has(e1))
c1 = csgCache.get(e1);
else
c1 = this.GetCSG(e1);
let obb1 = e1.OBB;
for (let j = i + 1; j < ens.length; j++)
{
let e2 = ens[j];
if (!obb1.intersectsOBB(e2.OBB))
continue;
let c2: CSG;
if (csgCache.has(e2))
c2 = csgCache.get(e2);
else
{
c2 = this.GetCSG(e2);
csgCache.set(e2, c2);
}
if (!c2)
console.error("实体CSG出错");
let c = c1.intersect(c2.transform1(e1.OCSInv.multiply(e2.OCS)));
if (c.polygons.length > 0)
{
set1.add(e1);
set1.add(e2);
let ptsMap = new Map<string, Vector3[]>();
let geo = new Geometry;
for (let poly of c.polygons)
{
let normal = Vector3DToVector3(poly.plane.normal);
if (equalv3(normal, new Vector3())) continue;
let p0 = Vector3DToVector3(poly.vertices[0].pos);
if (poly.vertices.some((v, i) =>
{
if (i === 0)
return false;
let p1 = Vector3DToVector3(v.pos);
return equalv3(p0, p1, 1e-2);
}))
continue;
checkInterfereTool.Check(ens);
let objMap = checkInterfereTool.objMap;
let k = `${FixedNotZero(normal.x, 2)},${FixedNotZero(normal.y, 2)},${FixedNotZero(normal.z, 2)}`;
let k2 = `${FixedNotZero(-normal.x, 2)},${FixedNotZero(-normal.y, 2)},${FixedNotZero(-normal.z, 2)}`;
let pts = ptsMap.get(k);
if (!pts)
pts = ptsMap.get(k2);
if (!pts)
{
pts = [];
ptsMap.set(k, pts);
}
pts.push(...poly.vertices.map(v => Vector3DToVector3(v.pos)));
for (let v of poly.vertices)
{
v.tag = geo.vertices.length;
geo.vertices.push(Vector3DToVector3(v.pos));
}
let firstVertex = poly.vertices[0];
for (let i = poly.vertices.length - 3; i >= 0; i--)
{
let [a, b, c] = [
firstVertex.tag,
poly.vertices[i + 1].tag,
poly.vertices[i + 2].tag
];
let f = new Face3(a, b, c, normal);
geo.faces.push(f);
}
}
let hasSolid = false;
let count = 0;
for (let [k, pts] of ptsMap)
{
let box = new Box3Ext().setFromPoints(pts);
if (box.isSolid(1e-3))
{
count++;
hasSolid = true;
ptsMap.delete(k);
}
}
if (hasSolid)
{
//围不出一个实体的情况
if (ptsMap.size === 1) continue;
if (ptsMap.size === 0 && count <= 2) continue;
geo.applyMatrix4(e1.OCS);
let m = new Mesh(geo, ColorMaterial.GetBasicMaterial(1).clone());
objMap.set(m, [e1, e2]);
}
}
}
}
if (objMap.size === 0)
{
AppToaster.show({
@ -172,7 +51,7 @@ export class Interfere implements Command
let oldType = userConfig.RenderType;
userConfig.RenderType = RenderType.Wireframe;
app.Editor.ModalManage.RenderModeless(InterfereModal, { count: set1.size, data: objMap }, { canMinimize: false });
app.Editor.ModalManage.RenderModeless(InterfereModal, { count: checkInterfereTool.entitySet.size, data: objMap }, { canMinimize: false });
await app.Editor.ModalManage.Wait();
@ -184,15 +63,4 @@ export class Interfere implements Command
userConfig.RenderType = oldType;
}
private GetCSG(en: Solid3D)
{
if (en instanceof ExtrudeSolid)
{
return en.CSG;
}
else
{
return Geometry2CSG(en.MeshGeometry);
}
}
}

@ -0,0 +1,160 @@
import { Mesh, Vector3, Geometry, Face3 } from "three";
import { ExtrudeSolid } from "../DatabaseServices/Entity/Extrude";
import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid";
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
import { Entity } from "../DatabaseServices/Entity/Entity";
import { CSG } from "../csg/core/CSG";
import { Geometry2CSG, Vector3DToVector3 } from "../csg/core/Geometry2CSG";
import { equalv3 } from "../Geometry/GeUtils";
import { FixedNotZero } from "./Utils";
import { Box3Ext } from "../Geometry/Box";
import { ColorMaterial } from "./ColorPalette";
import { TemplateWineRackRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateWineRackRecord";
import { TemplateLatticeRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateLatticeRecord";
export type Solid3D = ExtrudeSolid | SweepSolid | ExtrudeHole;
export class CheckInterfereTool
{
entitySet: Set<Solid3D> = new Set();
objMap: Map<Mesh, [Solid3D, Solid3D]> = new Map();
Check(ens: Solid3D[])
{
let entitySet = this.entitySet;
let objMap = this.objMap;
entitySet.clear();
objMap.clear();
const csgCache: WeakMap<Entity, CSG> = new WeakMap();
for (let i = 0; i < ens.length; i++)
{
let e1 = ens[i];
if (e1.Template && (e1.Template.Object instanceof TemplateWineRackRecord || e1.Template.Object instanceof TemplateLatticeRecord))
continue;
let c1: CSG;
if (csgCache.has(e1))
c1 = csgCache.get(e1);
else
c1 = this.GetCSG(e1);
let obb1 = e1.OBB;
for (let j = i + 1; j < ens.length; j++)
{
let e2 = ens[j];
if (e2.Template && (e2.Template.Object instanceof TemplateWineRackRecord || e2.Template.Object instanceof TemplateLatticeRecord))
continue;
if (!obb1.intersectsOBB(e2.OBB))
continue;
let c2: CSG;
if (csgCache.has(e2))
c2 = csgCache.get(e2);
else
{
c2 = this.GetCSG(e2);
csgCache.set(e2, c2);
}
if (!c2)
console.error("实体CSG出错");
let c = c1.intersect(c2.transform1(e1.OCSInv.multiply(e2.OCS)));
if (c.polygons.length > 0)
{
entitySet.add(e1);
entitySet.add(e2);
let ptsMap = new Map<string, Vector3[]>();
let geo = new Geometry;
for (let poly of c.polygons)
{
let normal = Vector3DToVector3(poly.plane.normal);
if (equalv3(normal, new Vector3())) continue;
let p0 = Vector3DToVector3(poly.vertices[0].pos);
if (poly.vertices.some((v, i) =>
{
if (i === 0)
return false;
let p1 = Vector3DToVector3(v.pos);
return equalv3(p0, p1, 1e-2);
}))
continue;
let k = `${FixedNotZero(normal.x, 2)},${FixedNotZero(normal.y, 2)},${FixedNotZero(normal.z, 2)}`;
let k2 = `${FixedNotZero(-normal.x, 2)},${FixedNotZero(-normal.y, 2)},${FixedNotZero(-normal.z, 2)}`;
let pts = ptsMap.get(k);
if (!pts)
pts = ptsMap.get(k2);
if (!pts)
{
pts = [];
ptsMap.set(k, pts);
}
pts.push(...poly.vertices.map(v => Vector3DToVector3(v.pos)));
for (let v of poly.vertices)
{
v.tag = geo.vertices.length;
geo.vertices.push(Vector3DToVector3(v.pos));
}
let firstVertex = poly.vertices[0];
for (let i = poly.vertices.length - 3; i >= 0; i--)
{
let [a, b, c] = [
firstVertex.tag,
poly.vertices[i + 1].tag,
poly.vertices[i + 2].tag
];
let f = new Face3(a, b, c, normal);
geo.faces.push(f);
}
}
let hasSolid = false;
let count = 0;
for (let [k, pts] of ptsMap)
{
let box = new Box3Ext().setFromPoints(pts);
if (box.isSolid(1e-3))
{
count++;
hasSolid = true;
ptsMap.delete(k);
}
}
if (hasSolid)
{
//围不出一个实体的情况
if (ptsMap.size === 1) continue;
if (ptsMap.size === 0 && count <= 2) continue;
geo.applyMatrix4(e1.OCS);
let m = new Mesh(geo, ColorMaterial.GetBasicMaterial(1).clone());
objMap.set(m, [e1, e2]);
}
}
}
}
return objMap;
}
private GetCSG(en: Solid3D)
{
if (en instanceof ExtrudeSolid)
{
return en.CSG;
}
else
{
return Geometry2CSG(en.MeshGeometry);
}
}
}
export const checkInterfereTool = new CheckInterfereTool();
Loading…
Cancel
Save