!1459 优化:干涉检查

pull/1459/MERGE
ChenX 4 years ago
parent 995c78bc31
commit a62b0309fb

@ -18,7 +18,7 @@ exports[`双圆多段线倒角 8`] = `1200.793332200017`;
exports[`多段线闭合标志首尾有弧 1`] = `1357.0494514094473`;
exports[`多段线闭合标志首尾有弧 2`] = `1357.0494514094473`;
exports[`多段线闭合标志首尾有弧 2`] = `1357.049451409447`;
exports[`多段线闭合标志首尾有弧 3`] = `1357.049451409447`;

@ -91,7 +91,7 @@ exports[`圆弧合并 4`] = `0`;
exports[`最近点 1`] = `
Vector3 {
"x": 0,
"y": 0,
"y": 6.123233995736766e-16,
"z": 0,
}
`;

@ -131,7 +131,7 @@ Vector3 {
exports[`最近点 1`] = `
Vector3 {
"x": 0,
"y": 0,
"y": 6.123233995736766e-16,
"z": 0,
}
`;

File diff suppressed because one or more lines are too long

@ -14,7 +14,7 @@ exports[`多段线 存在大圆弧的多段线面积 1`] = `-24.019436375469752`
exports[`多段线 最近点精度 1`] = `
Vector3 {
"x": 1.987500976448074,
"x": 1.9875009764480738,
"y": 3.9999218841540816,
"z": 0,
}

@ -1,6 +1,6 @@
import { Intent } from "@blueprintjs/core";
import { app } from "../../ApplicationServices/Application";
import { checkInterfereTool } from "../../Common/InterfereUtil";
import { CheckInterfereTool } from "../../Common/InterfereUtil";
import { StoreageKeys } from "../../Common/StoreageKeys";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Entity } from "../../DatabaseServices/Entity/Entity";
@ -149,7 +149,7 @@ async function ExecChaiDan(chaiDanRoute: ErpRoutes)
let originEns = new Set<Board>();
for (let b of selction.boardList)
originEns.add(b.__OriginalEnt__ ?? b);
checkInterfereTool.Check([...originEns, ...selction.metalsList]).then(objMap =>
CheckInterfereTool.GetInstance().Check([...originEns, ...selction.metalsList]).then(objMap =>
{
if (objMap.size > 0)
{
@ -159,6 +159,8 @@ async function ExecChaiDan(chaiDanRoute: ErpRoutes)
intent: Intent.DANGER,
});
}
CheckInterfereTool.GetInstance().Clear();
});
}

@ -1,8 +1,9 @@
import { Intent } from '@blueprintjs/core';
import { app } from '../ApplicationServices/Application';
import { ColorMaterial } from '../Common/ColorPalette';
import { DisposeThreeObj } from '../Common/Dispose';
import { checkInterfereTool } from '../Common/InterfereUtil';
import { CheckInterfereTool } from '../Common/InterfereUtil';
import { ExtrudeSolid } from '../DatabaseServices/Entity/Extrude';
import { HardwareCompositeEntity } from '../DatabaseServices/Hardware/HardwareCompositeEntity';
import { PromptStatus } from '../Editor/PromptResult';
@ -16,8 +17,12 @@ import { AppToaster } from './../UI/Components/Toaster';
export class Interfere implements Command
{
checkInterfereTool: CheckInterfereTool;
async exec()
{
if (!this.checkInterfereTool)
this.checkInterfereTool = new CheckInterfereTool(ColorMaterial.GetConceptualMaterial(1));
const Filter = {
filterTypes: [HardwareCompositeEntity, ExtrudeSolid, SweepSolid]
};
@ -40,7 +45,7 @@ export class Interfere implements Command
timeout: 0
}, 'interfere');
await checkInterfereTool.Check(selectEnts, (i, all) =>
await this.checkInterfereTool.Check(selectEnts, (i, all) =>
{
let a = i / all;
if (a - down.progress > 0.1)
@ -54,7 +59,7 @@ export class Interfere implements Command
down.progress = 1;
let objMap = checkInterfereTool.objMap;
let objMap = this.checkInterfereTool.objMap;
if (objMap.size === 0)
{
@ -66,14 +71,16 @@ export class Interfere implements Command
return;
}
for (let [o,] of objMap)
{
app.Viewer.Scene.add(o);
}
for (let [mesh,] of objMap)
app.Viewer.Scene.add(mesh);
let oldType = userConfig.RenderType;
userConfig.RenderType = RenderType.Wireframe;
app.Editor.ModalManage.RenderModeless(InterfereModal, { count: checkInterfereTool.entitySet.size, data: objMap }, { canMinimize: false });
app.Editor.ModalManage.RenderModeless(InterfereModal, { count: this.checkInterfereTool.entitySet.size, data: objMap }, { canMinimize: false });
//等待界面呼出的时候 画布并不会刷新,所以强制刷新
app.Editor.UpdateScreen();
await app.Editor.ModalManage.Wait();
@ -84,5 +91,7 @@ export class Interfere implements Command
}
userConfig.RenderType = oldType;
this.checkInterfereTool.Clear();//回收内存
}
}

@ -1,6 +1,8 @@
import { Box3, Face3, Geometry, Mesh, Vector3 } from "three";
import { Box3, Material, Mesh } from "three";
import { CSG } from "../csg/core/CSG";
import { Geometry2CSG, Vector3DToVector3 } from "../csg/core/Geometry2CSG";
import { FuzzyCSGFactory } from "../csg/core/FuzzyFactory3d";
import { CSG2Geometry, Geometry2CSG } from "../csg/core/Geometry2CSG";
import { Plane } from "../csg/core/math/Plane";
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid";
import { Board } from "../DatabaseServices/Entity/Board";
@ -11,19 +13,27 @@ 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 { CanDrawHoleFuzz } from "../Geometry/DrillParse/BoardGetFace";
import { equaln, equalv3 } from "../Geometry/GeUtils";
import { OBB } from "../Geometry/OBB/obb";
import { PlaneExt } from "../Geometry/Plane";
import { ColorMaterial } from "./ColorPalette";
import { Log } from "./Log";
import { Sleep } from "./Sleep";
import { FixedNotZero } from "./Utils";
export type Solid3D = ExtrudeSolid | SweepSolid | ExtrudeHole;
export class CheckInterfereTool
{
constructor(public _MeshMaterial: Material = ColorMaterial.GetBasicMaterial(1))
{
}
static _SingleInstance: CheckInterfereTool;
static GetInstance(): CheckInterfereTool
{
if (this._SingleInstance) return this._SingleInstance;
this._SingleInstance = new CheckInterfereTool;
return this._SingleInstance;
}
entitySet: Set<Solid3D> = new Set();
objMap: Map<Mesh, [Solid3D, Solid3D]> = new Map();
GetEntitys(selectEnts: (HardwareCompositeEntity | ExtrudeSolid | SweepSolid)[])
@ -65,7 +75,7 @@ export class CheckInterfereTool
let e1 = ens[i];
let IsSkipEntity = this.IsSkipEntity(e1);
if (i % 50 === 0)
if (i !== 0 && i % 50 === 0)
{
await Sleep(0);
if (progressCallBack)
@ -118,11 +128,26 @@ export class CheckInterfereTool
if (!obb1.intersectsOBB(this.GetOBB(e2)))
continue;
function EntityTypeCode(ext: Entity): 0 | 1 | 2
{
if (ext instanceof ExtrudeSolid)
return 1;
else if (ext instanceof ExtrudeHole)
return 2;
else
return 0;
}
let t1 = EntityTypeCode(e1);
let t2 = EntityTypeCode(e2);
//#I2DXNO
if (e1 instanceof Board && e2 instanceof Board)
if (t1 > 0 && t2 > 0)
{
let [b1, b2] = [e1.Clone(), e2.Clone()];
if (!b1.Subtract([e2], [b1]) && !b1.IsErase && !b2.Subtract([e1], [b2]) && !b2.IsErase)
let [b1, b2] = [t1 === 1 ? <ExtrudeSolid>e1.Clone() : (<ExtrudeHole>e1).Convert2ExtrudeSolid(),
t2 === 1 ? <ExtrudeSolid>e2.Clone() : (<ExtrudeHole>e2).Convert2ExtrudeSolid()];
if (!b1.Subtract([b2]) && !b1.IsErase
&& !b2.Subtract([b1]) && !b2.IsErase)
continue;
}
@ -134,97 +159,18 @@ export class CheckInterfereTool
continue;
}
let c = csg1.intersect(csg2.transform1(e1.OCSInv.multiply(e2.OCS)));
if (c.polygons.length > 0)
{
let interCsg = csg1.intersect(csg2.transform1(e1.OCSInv.multiply(e2.OCSNoClone)));
let ptsMap = new Map<string, Vector3[]>();
let geo = new Geometry;
let planeSet = new Set<Plane>();
let f = new FuzzyCSGFactory;
for (let polygon of interCsg.polygons)
planeSet.add(f.getPlane(polygon.plane));
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;
let plane = new PlaneExt();
for (let [k, pts] of ptsMap)
{
let nor = new Vector3().fromArray(k.split(",").map(s => parseFloat(s)));
plane.setFromNormalAndCoplanarPoint(nor, pts[0]);
//超过3点不在一个面上,一般可以围城实体
let outCount = 0;
for (let p of pts)
{
let dist = plane.distanceToPoint(p);
if (!equaln(dist, 0, CanDrawHoleFuzz))
{
outCount++;
if (outCount >= 3)
{
count++;
hasSolid = true;
ptsMap.delete(k);
break;
}
}
}
}
if (hasSolid)
{
//围不出一个实体的情况
if (ptsMap.size === 1) continue;
if (ptsMap.size === 0 && count <= 2) continue;
entitySet.add(e1);
entitySet.add(e2);
geo.applyMatrix4(e1.OCS);
let m = new Mesh(geo, ColorMaterial.GetBasicMaterial(1).clone());
objMap.set(m, [e1, e2]);
}
if (planeSet.size >= 4)//最少4个面围成一个三维实体
{
let geo = CSG2Geometry(interCsg).applyMatrix4(e1.OCSNoClone);
let mesh = new Mesh(geo, this._MeshMaterial);
objMap.set(mesh, [e1, e2]);
}
}
}
@ -234,6 +180,12 @@ export class CheckInterfereTool
return objMap;
}
Clear()
{
this.entitySet.clear();
this.objMap.clear();
}
csgCache: Map<Entity, CSG> = new Map();
private GetCSG(en: Solid3D)
{
@ -273,5 +225,3 @@ export class CheckInterfereTool
return box;
}
}
export const checkInterfereTool = new CheckInterfereTool();

@ -191,7 +191,7 @@ export class ExtrudeHole extends Hole
private GeneralMeshGeometry()
{
let extrudeSettings: ExtrudeGeometryOptions = {
curveSegments: 12,
curveSegments: 6,
steps: 1,
bevelEnabled: false,
depth: this.Height,

@ -1,7 +1,7 @@
import { BoxGeometry, BufferGeometry, ExtrudeGeometry, ExtrudeGeometryOptions, Geometry, InstancedInterleavedBuffer, InterleavedBufferAttribute, Line as TLine, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Path, UVGenerator, Vector3 } from "three";
import { Line2 } from "three/examples/jsm/lines/Line2";
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";
import { arrayClone, arrayLast, arrayRemoveIf, arrayRemoveOnce, arraySortByNumber, arraySum } from "../../Common/ArrayExt";
import { arrayClone, arrayLast, arrayPushArray, arrayRemoveIf, arrayRemoveOnce, arraySortByNumber, arraySum } from "../../Common/ArrayExt";
import { ColorMaterial } from "../../Common/ColorPalette";
import { equalCurve, PolylineSpliteRect } from "../../Common/CurveUtils";
import { DisposeThreeObj, Object3DRemoveAll } from "../../Common/Dispose";
@ -514,8 +514,8 @@ export class ExtrudeSolid extends Entity
for (let g of this.grooves)
{
if (equaln(g.thickness, this.thickness))
holes.push(Contour.CreateContour(g.ContourCurve.Clone().ApplyMatrix(this.OCSInv.multiply(g.OCS)), false));
if (equaln(g.thickness, this.thickness, 1e-3))
holes.push(Contour.CreateContour(g.ContourCurve.Clone().ApplyMatrix(this.OCSInv.multiply(g.OCSNoClone)), false));
}
return new Shape(contour, holes);
}
@ -666,8 +666,9 @@ export class ExtrudeSolid extends Entity
for (let br of extrudes)
{
let gs = this.ConverToLocalGroove(br);
grooves.push(...gs);
arrayPushArray(grooves, gs);
}
if (grooves.length === 0) return false;
let area1 = this.ContourCurve.Area;
let sum1 = this.Volume;

@ -1,5 +1,6 @@
import { Box3, BufferGeometry, Geometry, Line, Matrix4, Mesh, Object3D, Vector, Vector2, Vector3 } from 'three';
import { ToFixed } from '../Common/Utils';
import { Vec3 } from './IVec3';
export const IdentityMtx4 = new Matrix4();
export const ZeroVec = new Vector3();
@ -73,7 +74,7 @@ interface P2
x: number; y: number;
}
export function equalv3(v1: Vector3, v2: Vector3, fuzz = 1e-8)
export function equalv3(v1: Vec3, v2: Vec3, fuzz = 1e-8)
{
return equaln(v1.x, v2.x, fuzz) && equaln(v1.y, v2.y, fuzz) && equaln(v1.z, v2.z, fuzz);
}

@ -2,12 +2,12 @@ import { Button, Card, Classes, Intent } from '@blueprintjs/core';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import React, { Component } from 'react';
import { Box3, Mesh, MeshBasicMaterial, Vector3 } from 'three';
import { Box3, Mesh, Vector3 } from 'three';
import { app } from '../../../ApplicationServices/Application';
import { Solid3D } from '../../../Common/InterfereUtil';
import { ColorMaterial } from './../../../Common/ColorPalette';
import { FixIndex } from './../../../Common/Utils';
import { CommonModal } from './ModalContainer';
import { Solid3D } from '../../../Common/InterfereUtil';
interface IInterfereProps
{
@ -72,10 +72,7 @@ export class InterfereModal extends Component<IInterfereProps, {}> {
private restore = (os: Mesh[]) =>
{
for (let o of os)
{
let mat = o.material as MeshBasicMaterial;
mat.color = ColorMaterial.GetColor(1);
}
o.material = ColorMaterial.GetConceptualMaterial(1);
app.Viewer.OutlinePass.selectedObjects = [];
};
private next = () =>
@ -96,8 +93,7 @@ export class InterfereModal extends Component<IInterfereProps, {}> {
};
private update = (o: Mesh) =>
{
let mat = o.material as MeshBasicMaterial;
mat.color = ColorMaterial.GetColor(5);
o.material = ColorMaterial.GetConceptualMaterial(5);
let box = new Box3();
app.Viewer.OutlinePass.selectedObjects = this.props.data.get(o).map(e =>
{

@ -1,5 +1,5 @@
import { BufferGeometry, Face3, Geometry, Vector2, Vector3 } from "three";
import { equalv3, ZeroVec } from "../../Geometry/GeUtils";
import { AsVector2, AsVector3, equalv3, ZeroVec } from "../../Geometry/GeUtils";
import { CSG } from "./CSG";
import { Polygon } from "./math/Polygon3";
import { Vector2D } from "./math/Vector2";
@ -34,7 +34,7 @@ export function Geometry2CSG(geometry: Geometry | BufferGeometry): CSG
}
let polygon = new Polygon(vertices);
let normal = Vector3DToVector3(polygon.plane.normal);
let normal = AsVector3(polygon.plane.normal);
if (!isNaN(polygon.plane.w) && !equalv3(normal, new Vector3()))
polygons.push(polygon);
}
@ -49,12 +49,12 @@ export function CSG2Geometry(csg: CSG): Geometry
for (let poly of csg.polygons)
{
let normal = Vector3DToVector3(poly.plane.normal);
let normal = AsVector3(poly.plane.normal);
if (equalv3(normal, ZeroVec)) continue;
for (let v of poly.vertices)
{
v.tag = geo.vertices.length;
geo.vertices.push(Vector3DToVector3(v.pos));
geo.vertices.push(AsVector3(v.pos));
}
let firstVertex = poly.vertices[0];
@ -70,9 +70,9 @@ export function CSG2Geometry(csg: CSG): Geometry
geo.faces.push(f);
uvs.push([
Vector2DToVector2(firstVertex.uv),
Vector2DToVector2(poly.vertices[i + 1].uv),
Vector2DToVector2(poly.vertices[i + 2].uv)
AsVector2(firstVertex.uv),
AsVector2(poly.vertices[i + 1].uv),
AsVector2(poly.vertices[i + 2].uv)
]);
}
}
@ -83,12 +83,3 @@ function Vector3ToVector3D(v: Vector3): Vector3D
{
return new Vector3D(v.x, v.y, v.z);
}
export function Vector3DToVector3(v: Vector3D): Vector3
{
return new Vector3(v.x, v.y, v.z);
}
function Vector2DToVector2(v: Vector2D): Vector2
{
return new Vector2(v.x, v.y);
}

@ -1,10 +1,11 @@
import { _CSGDEBUG, EPS } from "../constants";
import { Matrix4 } from "three";
import { arrayLast, arrayRemoveDuplicateBySort } from "../../../Common/ArrayExt";
import { equalv3 } from "../../../Geometry/GeUtils";
import { EPS, _CSGDEBUG } from "../constants";
import { IsMirror } from "./IsMirrot";
import { Plane } from "./Plane";
import { Vector3D } from "./Vector3";
import { Vertex3D } from "./Vertex3";
import { arrayRemoveDuplicateBySort } from "../../../Common/ArrayExt";
import { Matrix4 } from "three";
import { IsMirror } from "./IsMirrot";
export enum Type
{
@ -36,9 +37,9 @@ interface SplitPolygonData
* The plane of the polygon is calculated from the vertex coordinates if not provided.
* The plane can alternatively be passed as the third argument to avoid calculations.
*
 *
 *
 *
*
*
*
*/
export class Polygon
{
@ -201,15 +202,12 @@ export class Polygon
isBack = nextIsBack;
} // for vertexindex
// remove duplicate vertices:
let EPS_SQUARED = EPS * EPS;
arrayRemoveDuplicateBySort(backVertices, (v1, v2) =>
{
return v1.pos.distanceToSquared(v2.pos) < EPS_SQUARED;
});
arrayRemoveDuplicateBySort(frontVertices, (v1, v2) =>
{
return v1.pos.distanceToSquared(v2.pos) < EPS_SQUARED;
});
arrayRemoveDuplicateBySort(backVertices, (v1, v2) => equalv3(v1.pos, v2.pos, EPS));
if (backVertices.length > 2 && equalv3(backVertices[0].pos, arrayLast(backVertices).pos, EPS))
backVertices.pop();
arrayRemoveDuplicateBySort(frontVertices, (v1, v2) => equalv3(v1.pos, v2.pos, EPS));
if (frontVertices.length > 2 && equalv3(frontVertices[0].pos, arrayLast(frontVertices).pos, EPS))
frontVertices.pop();
if (frontVertices.length >= 3)
result.front = new Polygon(frontVertices, this.plane);
if (backVertices.length >= 3)
@ -219,7 +217,13 @@ export class Polygon
return result;
}
static verticesConvex(vertices: Vertex3D[], planenormal: Vector3D)
/**
*
* @param vertices
* @param planenormal 线
* @returns true: false:
*/
static verticesConvex(vertices: Vertex3D[], planenormal: Vector3D): boolean
{
let count = vertices.length;
if (count < 3) return false;

@ -425,8 +425,13 @@ class Node
}
let args: D = { node: this, polygontreenodes: polygonTreeNodes };
let stack: D[] = [];
let doCount = 0;
do
{
if (doCount > 1e3) throw "程序内部错误:尝试对平面进行切割失败!进入死循环!";
doCount++;
let node = args.node;
polygonTreeNodes = args.polygontreenodes;

Loading…
Cancel
Save