mirror of https://gitee.com/cf-fz/WebCAD.git
!1081 优化:干涉检查忽略格子抽和酒格,增加单元测试
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);
|
||||||
|
});
|
||||||
|
});
|
@ -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…
Reference in new issue