!1138 优化:干涉检查性能,进度条,避免卡死

pull/1138/MERGE
ChenX 4 years ago
parent d3c6972bef
commit 3dfd41b98c

@ -2,12 +2,12 @@ import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
import { Solid3D, checkInterfereTool } from "../../src/Common/InterfereUtil"; import { Solid3D, checkInterfereTool } from "../../src/Common/InterfereUtil";
import { ObjectId } from "../../src/DatabaseServices/ObjectId"; import { ObjectId } from "../../src/DatabaseServices/ObjectId";
function Check(data: any, count: number) async function Check(data: any, count: number)
{ {
let boards = LoadEntityFromFileData(data) as Solid3D[]; let boards = LoadEntityFromFileData(data) as Solid3D[];
for (let i = 0; i < boards.length; i++) for (let i = 0; i < boards.length; i++)
boards[i].objectId = new ObjectId(i); boards[i].objectId = new ObjectId(i);
checkInterfereTool.Check(boards as any[]); await checkInterfereTool.Check(boards as any[]);
expect(checkInterfereTool.objMap.size).toBe(count); expect(checkInterfereTool.objMap.size).toBe(count);
} }

@ -2,17 +2,17 @@
import { Intent } from '@blueprintjs/core'; import { Intent } from '@blueprintjs/core';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { DisposeThreeObj } from '../Common/Dispose'; import { DisposeThreeObj } from '../Common/Dispose';
import { checkInterfereTool, Solid3D } from '../Common/InterfereUtil'; import { checkInterfereTool } from '../Common/InterfereUtil';
import { ExtrudeSolid } from '../DatabaseServices/Entity/Extrude'; import { ExtrudeSolid } from '../DatabaseServices/Entity/Extrude';
import { HardwareCompositeEntity } from '../DatabaseServices/Hardware/HardwareCompositeEntity';
import { PromptStatus } from '../Editor/PromptResult'; import { PromptStatus } from '../Editor/PromptResult';
import { userConfig } from '../Editor/UserConfig'; import { userConfig } from '../Editor/UserConfig';
import { RenderType } from '../GraphicsSystem/RenderType'; import { RenderType } from '../GraphicsSystem/RenderType';
import { InterfereModal } from '../UI/Components/Modal/InterfereModal'; import { InterfereModal } from '../UI/Components/Modal/InterfereModal';
import { DownPanelStore } from '../UI/Store/DownPanelStore';
import { SweepSolid } from './../DatabaseServices/3DSolid/SweepSolid'; import { SweepSolid } from './../DatabaseServices/3DSolid/SweepSolid';
import { Command } from './../Editor/CommandMachine'; import { Command } from './../Editor/CommandMachine';
import { AppToaster } from './../UI/Components/Toaster'; import { AppToaster } from './../UI/Components/Toaster';
import { HardwareCompositeEntity } from '../DatabaseServices/Hardware/HardwareCompositeEntity';
import { ExtrudeHole } from '../DatabaseServices/3DSolid/ExtrudeHole';
export class Interfere implements Command export class Interfere implements Command
{ {
@ -31,7 +31,29 @@ export class Interfere implements Command
let selectEnts = enRes.SelectSet.SelectEntityList as (HardwareCompositeEntity | ExtrudeSolid | SweepSolid)[]; let selectEnts = enRes.SelectSet.SelectEntityList as (HardwareCompositeEntity | ExtrudeSolid | SweepSolid)[];
checkInterfereTool.Check(selectEnts); //进度条
let down = DownPanelStore.GetInstance() as DownPanelStore;
down.progress = 0.1;
AppToaster.show({
message: "正在计算干涉检查...",
timeout: 0
}, 'interfere');
await checkInterfereTool.Check(selectEnts, (i, all) =>
{
let a = i / all;
if (a - down.progress > 0.1)
down.progress = a;
});
AppToaster.show({
message: "计算完成!",
timeout: 100
}, 'interfere');
down.progress = 1;
let objMap = checkInterfereTool.objMap; let objMap = checkInterfereTool.objMap;
if (objMap.size === 0) if (objMap.size === 0)

@ -1,18 +1,22 @@
import { Mesh, Vector3, Geometry, Face3 } from "three"; import { Box3, Face3, Geometry, Mesh, Vector3 } 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 { CSG } from "../csg/core/CSG";
import { Geometry2CSG, Vector3DToVector3 } from "../csg/core/Geometry2CSG"; import { Geometry2CSG, Vector3DToVector3 } from "../csg/core/Geometry2CSG";
import { equalv3 } from "../Geometry/GeUtils"; import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
import { FixedNotZero } from "./Utils"; import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid";
import { Box3Ext } from "../Geometry/Box";
import { ColorMaterial } from "./ColorPalette";
import { TemplateWineRackRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateWineRackRecord";
import { TemplateLatticeRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateLatticeRecord";
import { Board } from "../DatabaseServices/Entity/Board"; import { Board } from "../DatabaseServices/Entity/Board";
import { Entity } from "../DatabaseServices/Entity/Entity";
import { ExtrudeSolid } from "../DatabaseServices/Entity/Extrude";
import { HardwareCompositeEntity } from "../DatabaseServices/Hardware/HardwareCompositeEntity"; import { HardwareCompositeEntity } from "../DatabaseServices/Hardware/HardwareCompositeEntity";
import { ObjectId } from "../DatabaseServices/ObjectId";
import { TemplateLatticeRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateLatticeRecord";
import { TemplateWineRackRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateWineRackRecord";
import { Box3Ext } from "../Geometry/Box";
import { equalv3 } from "../Geometry/GeUtils";
import { OBB } from "../Geometry/OBB/obb";
import { ColorMaterial } from "./ColorPalette";
import { Log } from "./Log";
import { Sleep } from "./Sleep";
import { FixedNotZero } from "./Utils";
export type Solid3D = ExtrudeSolid | SweepSolid | ExtrudeHole; export type Solid3D = ExtrudeSolid | SweepSolid | ExtrudeHole;
@ -36,7 +40,8 @@ export class CheckInterfereTool
} }
return ens; return ens;
} }
Check(selectEnts: (HardwareCompositeEntity | ExtrudeSolid | SweepSolid)[])
async Check(selectEnts: (HardwareCompositeEntity | ExtrudeSolid | SweepSolid)[], progressCallBack?: (index: number, all: number) => void)
{ {
let ens = this.GetEntitys(selectEnts); let ens = this.GetEntitys(selectEnts);
let entitySet = this.entitySet; let entitySet = this.entitySet;
@ -44,59 +49,73 @@ export class CheckInterfereTool
entitySet.clear(); entitySet.clear();
objMap.clear(); objMap.clear();
const csgCache: WeakMap<Entity, CSG> = new WeakMap();
for (let i = 0; i < ens.length; i++) for (let i = 0; i < ens.length; i++)
{ {
let e1 = ens[i]; let e1 = ens[i];
if (e1.Template && (e1.Template.Object instanceof TemplateWineRackRecord || e1.Template.Object instanceof TemplateLatticeRecord)) if (e1.Template && (e1.Template.Object instanceof TemplateWineRackRecord || e1.Template.Object instanceof TemplateLatticeRecord))
continue; continue;
let c1: CSG;
if (csgCache.has(e1))
c1 = csgCache.get(e1);
else
c1 = this.GetCSG(e1);
let obb1 = e1.OBB; if (i % 50 === 0)
for (let j = i + 1; j < ens.length; j++)
{ {
let e2 = ens[j]; await Sleep(0);
if (progressCallBack)
progressCallBack(i, ens.length);
}
if (e2.TempData && e2.TempData.Id === e1.TempData?.Id) continue; let obb1 = this.GetOBB(e1);
let box1 = this.GetBox(e1);
let RelevanceMeats: Set<ObjectId>;
let RelevanceKnifs: Set<ObjectId>;
let RelativeHardware: Set<ObjectId>;
if (e1 instanceof Board) if (e1 instanceof Board)
{ {
let id = e2.Id ?? e2.TempData.Id; RelevanceMeats = new Set(e1.RelevanceMeats);
if (e1.RelevanceMeats.includes(id) || e1.RelevanceKnifs.includes(id) || e1.RelativeHardware.includes(id)) continue; RelevanceKnifs = new Set(e1.RelevanceKnifs);
RelativeHardware = new Set(e1.RelativeHardware);
} }
let RelevanceBoards: Set<ObjectId>;
if (!e1.Id && e1.TempData?.Id) if (!e1.Id && e1.TempData?.Id)
{ {
let orgEn = e1.TempData.Id.Object; let orgEn = e1.TempData.Id.Object;
if (orgEn instanceof HardwareCompositeEntity) if (orgEn instanceof HardwareCompositeEntity)
{ RelevanceBoards = new Set(orgEn.RelevanceBoards);
if (orgEn.RelevanceBoards.includes(e2.Id)) continue;
} }
for (let j = i + 1; j < ens.length; j++)
{
let e2 = ens[j];
if (e2.TempData && e2.TempData.Id === e1.TempData?.Id) continue;
if (RelevanceMeats)
{
let id = e2.Id ?? e2.TempData.Id;
if (RelevanceMeats.has(id) || RelevanceKnifs.has(id) || RelativeHardware.has(id)) continue;
} }
if (RelevanceBoards && RelevanceBoards.has(e2.Id))
continue;
if (e2.Template && (e2.Template.Object instanceof TemplateWineRackRecord || e2.Template.Object instanceof TemplateLatticeRecord)) if (e2.Template && (e2.Template.Object instanceof TemplateWineRackRecord || e2.Template.Object instanceof TemplateLatticeRecord))
continue; continue;
if (!obb1.intersectsOBB(e2.OBB))
if (!box1.intersectsBox(this.GetBox(e2)))
continue; continue;
let c2: CSG; if (!obb1.intersectsOBB(this.GetOBB(e2)))
if (csgCache.has(e2)) continue;
c2 = csgCache.get(e2);
else let csg1 = this.GetCSG(e1);
let csg2 = this.GetCSG(e2);
if (!csg1 || !csg2)
{ {
c2 = this.GetCSG(e2); Log("构造CSG错误!");
csgCache.set(e2, c2); continue;
} }
if (!c2) let c = csg1.intersect(csg2.transform1(e1.OCSInv.multiply(e2.OCS)));
console.error("实体CSG出错");
let c = c1.intersect(c2.transform1(e1.OCSInv.multiply(e2.OCS)));
if (c.polygons.length > 0) if (c.polygons.length > 0)
{ {
@ -178,20 +197,49 @@ export class CheckInterfereTool
} }
} }
} }
this.csgCache.clear();
this.boxCache.clear();
this.obbCache.clear();
return objMap; return objMap;
} }
csgCache: Map<Entity, CSG> = new Map();
private GetCSG(en: Solid3D) private GetCSG(en: Solid3D)
{ {
let csg: CSG = this.csgCache.get(en);
if (csg) return csg;
if (en instanceof ExtrudeSolid) if (en instanceof ExtrudeSolid)
{ {
if (!en.Id) if (!en.Id)
en.CheckContourCurve(); en.CheckContourCurve();
return en.CSG; csg = en.CSG;
} }
else else
csg = Geometry2CSG(en.MeshGeometry);
this.csgCache.set(en, csg);
return csg;
}
obbCache = new Map<Entity, OBB>();
private GetOBB(e: Solid3D)
{ {
return Geometry2CSG(en.MeshGeometry); let obb = this.obbCache.get(e);
if (obb) return obb;
obb = e.OBB;
this.obbCache.set(e, obb);
return obb;
} }
boxCache = new Map<Entity, Box3>();
private GetBox(e: Solid3D)
{
let box = this.boxCache.get(e);
if (box) return box;
box = e.BoundingBox;
this.boxCache.set(e, box);
return box;
} }
} }

Loading…
Cancel
Save