!1275 优化:针对轴对齐的关联拉槽,使用快速盒子求交的方式来确定槽位置

pull/1275/MERGE
ChenX 4 years ago
parent 6dc7a8625d
commit faaed22302

@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`分裂的点在参数周围 1`] = `5782.013217639177`;
exports[`差集共线(圆) 1`] = `442426.78778792813`; exports[`差集共线(圆) 1`] = `442426.78778792813`;
exports[`差集错误 1`] = `1216051.1666666665`; exports[`差集错误 1`] = `1216051.1666666665`;

@ -57,3 +57,16 @@ test("差集错误", () =>
expect(s.Area).toMatchSnapshot(); expect(s.Area).toMatchSnapshot();
}); });
//由于切割的点在参数周围,导致分裂的时候,点出现了偏差(导致原先的算法 点在曲线内部了)
test("分裂的点在参数周围", () =>
{
let d = { "file": [2, "Region", 8, 2, 124, false, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2997.919883164752, -777.954629938351, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2997.919883164752, -777.954629938351, 0, 1], 0, 1, 1, 1, 1, "Polyline", 8, 2, 0, false, 0, 3, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2997.919883164752, -777.954629938351, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2997.919883164752, -777.954629938351, 0, 1], 0, 2, 4, [-965, -11], 0, [2603, -11], 0, [2603, 7], 0, [-965, 7], 0, true, 0, "Region", 8, 2, 125, false, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2994.919883164752, -770.954597934382, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2994.919883164752, -770.954597934382, 0, 1], 0, 1, 1, 1, 1, "Polyline", 8, 2, 0, false, 0, 3, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2994.919883164752, -770.954597934382, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2994.919883164752, -777.954629938351, 0, 1], 0, 2, 8, [829, -7.000032003968954], 0, [829, 2131], 0, [3, 2131], 0, [3, 2124.0000000000005], 0, [3, 2124.0000000000005], 0, [3, 0], 0, [3, 0], 0, [3, -7.000032003968954], 0, true, 0], "basePt": { "x": 2032.9198831647518, "y": -788.954629938351, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] };
let regs = LoadRegionsFromFileData(d);
regs[0].BooleanOper(regs[1], BoolOpeartionType.Intersection);
expect(regs[0].ShapeManager.ShapeList.length).toBe(1);
for (let s of regs[0].ShapeManager.ShapeList)
expect(s.Area).toMatchSnapshot();
});

@ -1,9 +1,11 @@
import { Object3D } from "three"; import { Object3D } from "three";
import { app } from "../../ApplicationServices/Application";
import { Entity } from "../../DatabaseServices/Entity/Entity"; import { Entity } from "../../DatabaseServices/Entity/Entity";
export function TestDraw(en: Entity | Entity[] | Object3D | Object3D[], colorIndex = 0) export async function TestDraw(en: Entity | Entity[] | Object3D | Object3D[], colorIndex = 0)
{ {
let app = (await import("../../ApplicationServices/Application"))?.app;
if (!app) return;
if (en instanceof Object3D) if (en instanceof Object3D)
app.Viewer.Scene.add(en); app.Viewer.Scene.add(en);
else if (en instanceof Entity) else if (en instanceof Entity)

@ -288,7 +288,7 @@ export class Contour
if (hasEqualCus) if (hasEqualCus)
continue; continue;
if (target.CuInOutline(pl)) if (fastCurveInCurve(targetOutline, pl))
intersectionList.push(pl); intersectionList.push(pl);
else else
unionList.push(pl); unionList.push(pl);
@ -296,7 +296,7 @@ export class Contour
for (let pl of targetCus) for (let pl of targetCus)
{ {
if (this.CuInOutline(pl)) if (fastCurveInCurve(sourceOutline, pl))
intersectionList.push(pl); intersectionList.push(pl);
else else
unionList.push(pl); unionList.push(pl);
@ -590,12 +590,13 @@ function fastEqualCurve(c1: Curve, c2: Curve, tolerance = 1e-3)
//对于双多段线互相切割后的结果,快速判断曲线是否在另一条曲线内部 //对于双多段线互相切割后的结果,快速判断曲线是否在另一条曲线内部
function fastCurveInCurve(sourceCu: Polyline, targetCu: Polyline) //也许有一天这个中点算法需要改一下, 使用 src\Geometry\ExtrudeEdgeGeometry2.ts->CenterPoint 会比较稳妥
function fastCurveInCurve(sourceCu: Polyline | Circle, targetCu: Curve)
{ {
return sourceCu.PtInCurve(targetCu.GetPointAtParam(targetCu.EndParam * 0.5)); return sourceCu.PtInCurve(targetCu.GetPointAtParam(targetCu.EndParam * 0.5));
} }
function fastCurveInCurve2(sourceCu: Polyline, targetCu: Polyline) function fastCurveInCurve2(sourceCu: Polyline | Circle, targetCu: Curve)
{ {
return sourceCu.PtInCurve(targetCu.StartPoint) && return sourceCu.PtInCurve(targetCu.StartPoint) &&
sourceCu.PtInCurve(targetCu.GetPointAtParam(targetCu.EndParam * 0.5)); sourceCu.PtInCurve(targetCu.GetPointAtParam(targetCu.EndParam * 0.5));

@ -1,4 +1,4 @@
import { Box3, BufferGeometry, EllipseCurve, Line as TLine, Material, Matrix3, Matrix4, Object3D, Vector3 } from 'three'; import { BufferGeometry, EllipseCurve, Line as TLine, Material, Matrix3, Matrix4, Object3D, 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 { arrayLast, arrayRemoveDuplicateBySort } from '../../Common/ArrayExt'; import { arrayLast, arrayRemoveDuplicateBySort } from '../../Common/ArrayExt';
@ -7,6 +7,7 @@ import { getArcOrCirNearPts, GetTanPtsOnArcOrCircle } from '../../Common/CurveUt
import { reviseMirrorMatrix } from '../../Common/Matrix4Utils'; import { reviseMirrorMatrix } from '../../Common/Matrix4Utils';
import { clamp } from '../../Common/Utils'; import { clamp } from '../../Common/Utils';
import { ObjectSnapMode } from '../../Editor/ObjectSnapMode'; import { ObjectSnapMode } from '../../Editor/ObjectSnapMode';
import { Box3Ext } from '../../Geometry/Box';
import { BufferGeometryUtils } from '../../Geometry/BufferGeometryUtils'; import { BufferGeometryUtils } from '../../Geometry/BufferGeometryUtils';
import { angle, AsVector3, equaln, MoveMatrix, polar } from '../../Geometry/GeUtils'; import { angle, AsVector3, equaln, MoveMatrix, polar } from '../../Geometry/GeUtils';
import { IntersectCircleAndArc, IntersectCircleAndCircle, IntersectEllipseAndCircleOrArc, IntersectLineAndCircle, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../../GraphicsSystem/IntersectWith'; import { IntersectCircleAndArc, IntersectCircleAndCircle, IntersectEllipseAndCircleOrArc, IntersectLineAndCircle, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../../GraphicsSystem/IntersectWith';
@ -236,9 +237,9 @@ export class Circle extends Curve
} }
//******************** Curve function end*****************// //******************** Curve function end*****************//
get BoundingBox(): Box3 get BoundingBox(): Box3Ext
{ {
return new Box3().setFromPoints(this.GetGripPoints()); return new Box3Ext().setFromPoints(this.GetGripPoints());
} }
InitDrawObject(renderType: RenderType = RenderType.Wireframe) InitDrawObject(renderType: RenderType = RenderType.Wireframe)

@ -143,6 +143,9 @@ export class ExtrudeSolid extends Entity
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
this.groovesAddLength = v; this.groovesAddLength = v;
//更改它的时候,关联切割被更新,拆单的时候才会正确,否则使用缓存将不正确
this.__UpdateVersion__++;
} }
} }
get GroovesAddWidth() get GroovesAddWidth()
@ -156,6 +159,9 @@ export class ExtrudeSolid extends Entity
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
this.groovesAddWidth = v; this.groovesAddWidth = v;
//更改它的时候,关联切割被更新,拆单的时候才会正确,否则使用缓存将不正确
this.__UpdateVersion__++;
} }
} }
get GroovesAddDepth() get GroovesAddDepth()
@ -169,6 +175,9 @@ export class ExtrudeSolid extends Entity
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
this.groovesAddDepth = v; this.groovesAddDepth = v;
//更改它的时候,关联切割被更新,拆单的时候才会正确,否则使用缓存将不正确
this.__UpdateVersion__++;
} }
} }
@ -495,7 +504,7 @@ export class ExtrudeSolid extends Entity
let thisShape = this.Shape; let thisShape = this.Shape;
let targetShape = target.Shape.ApplyMatrix(matrixToLocal); let targetShape = target.Shape.ApplyMatrix(matrixToLocal);
let unionShapes = thisShape.UnionBoolOperation(targetShape); let unionShapes = thisShape.UnionBoolOperation(targetShape, true);
if (unionShapes.length === 1) if (unionShapes.length === 1)
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
@ -1006,12 +1015,37 @@ export class ExtrudeSolid extends Entity
} }
else else
{ {
//当切割刀是矩形板,并且没有槽的时候,如果轴对齐,我们可以直接用aabb进行求交
if (target.isRect && target.grooves.length === 0)
{
let diffMtx = target.OCS.premultiply(this.OCSInv);
let box = target.BoundingBoxInOCS.applyMatrix4(diffMtx);
let size = box.getSize(new Vector3);
//轴对齐
if (equaln(size.x * size.y * size.z, target.Width * target.Height * target.Thickness, 1))
{
let ibox = this.BoundingBoxInOCS.intersect(box);
if (!(ibox.getSize(size).toArray().every(x => x > 1))) return [];
//构造新槽(因为我们当前的槽加长是根据槽的长短边进行加长的,所以我们可以这么构建)
let g2 = new ExtrudeSolid().ConverToRectSolid(size.x, size.y, size.z);
g2.Position = ibox.min;
g2.ApplyMatrix(this._Matrix);
g2.groovesAddDepth = target.groovesAddDepth;
g2.groovesAddLength = target.groovesAddLength;
g2.groovesAddWidth = target.groovesAddWidth;
g2.knifeRadius = target.knifeRadius;
return [g2];
}
}
let grooves: ExtrudeSolid[] = []; let grooves: ExtrudeSolid[] = [];
let project = ProjectBoard(target, this); let project = ProjectBoard(target, this);
if (!project) if (!project)
{ {
let yv = target.Normal; let yv = n2;
let zv = this.Normal; let zv = n1;
let xv = yv.clone().cross(zv); let xv = yv.clone().cross(zv);
yv.copy(zv).cross(xv); yv.copy(zv).cross(xv);
let m = new Matrix4().makeBasis(xv, yv, zv).copyPosition(this.OCS); let m = new Matrix4().makeBasis(xv, yv, zv).copyPosition(this.OCS);
@ -1055,8 +1089,8 @@ export class ExtrudeSolid extends Entity
else else
outlines.push(c.Curve); outlines.push(c.Curve);
} }
let xv = this.Normal; let xv = n1;
let zv = target.Normal; let zv = n2;
let yv = zv.clone().cross(xv); let yv = zv.clone().cross(xv);
//把<投影轮廓>对齐到肉的侧面坐标系上 //把<投影轮廓>对齐到肉的侧面坐标系上

@ -233,8 +233,10 @@ export class Shape
} }
//并集,如果成功返回1个形状,不成功返回2个形状 //并集,如果成功返回1个形状,不成功返回2个形状
UnionBoolOperation(targetShape: Shape): Shape[] UnionBoolOperation(targetShape: Shape, checkIntersect = false): Shape[]
{ {
if (checkIntersect && !this.BoundingBox.intersectsBox(targetShape.BoundingBox, 1e-3)) return [this, targetShape];
let { contours, holes } = this._Outline.UnionBoolOperation(targetShape._Outline); let { contours, holes } = this._Outline.UnionBoolOperation(targetShape._Outline);
let shapes: Shape[] = []; let shapes: Shape[] = [];

@ -138,10 +138,10 @@ export class FeedingToolPath extends Singleton
//若最外轮廓内偏移一个刀半径的曲线 和最内轮廓相交或者被包含,则去掉.且不与洞曲线相等 //若最外轮廓内偏移一个刀半径的曲线 和最内轮廓相交或者被包含,则去掉.且不与洞曲线相等
if (isOut) if (isOut)
{ {
let outlineOffsetCus = outline.GetOffsetCurves(dir * knifRadius).filter(c => c.IsClose); let outlineOffsetCus = outline.GetOffsetCurves(dir * knifRadius).filter(c => c.IsClose) as Curve[];
let outlineCus = GetOffsetCurves(outline, dir * knifRadius); let outlineCus = GetOffsetCurves(outline, dir * knifRadius);
let ho = holeOffsetCus[i]; let ho = holeOffsetCus[i];
let maxArea = Math.max(...outlineOffsetCus.map(c => c.Area)); let maxArea = Math.max(...(outlineOffsetCus.map(c => c.Area)));
for (let j = 0; j < outlineOffsetCus.length; j++) for (let j = 0; j < outlineOffsetCus.length; j++)
{ {
let c = outlineOffsetCus[j]; let c = outlineOffsetCus[j];

@ -25,6 +25,7 @@ import { PreViewer } from './PreViewer';
import { RenderType } from './RenderType'; import { RenderType } from './RenderType';
import { UpdateDraw } from '../Common/Status'; import { UpdateDraw } from '../Common/Status';
import { ColorMaterial } from '../Common/ColorPalette'; import { ColorMaterial } from '../Common/ColorPalette';
import { IsDev } from '../Common/Deving';
export class Viewer export class Viewer
{ {
@ -510,6 +511,7 @@ export class Viewer
{ {
const renderModelEntitys = async () => const renderModelEntitys = async () =>
{ {
console.time("开图渲染");
Entity.__ReadFileIng__ = true; Entity.__ReadFileIng__ = true;
const down = DownPanelStore.GetInstance() as DownPanelStore; const down = DownPanelStore.GetInstance() as DownPanelStore;
@ -553,6 +555,7 @@ export class Viewer
} }
down.progressName = ""; down.progressName = "";
console.timeEnd("开图渲染");
}; };
const renderLayoutEntitys = async () => const renderLayoutEntitys = async () =>

@ -19,6 +19,8 @@ async function UpdateRelevanceGroove(ents: CADObject[])
{ {
if (ExtrudeConfig.DisableRefCut) return; if (ExtrudeConfig.DisableRefCut) return;
console.time("更新关联拉槽");
let needUpdateBoardSet = new Set<ObjectId>(); let needUpdateBoardSet = new Set<ObjectId>();
for (let i = 0; i < ents.length; i++) for (let i = 0; i < ents.length; i++)
@ -58,7 +60,7 @@ async function UpdateRelevanceGroove(ents: CADObject[])
await Sleep(0); await Sleep(0);
} }
} }
console.timeEnd("更新关联拉槽");
app.Editor.UpdateScreen(); app.Editor.UpdateScreen();
down.EndProgress(); down.EndProgress();
} }

Loading…
Cancel
Save