fix #IWRU6 面域布尔运算允许更大的容差,避免板件切割错误,提高布尔性能

pull/302/MERGE
ChenX 5 years ago
parent f8bfe68927
commit 3c16e714b0

@ -2,4 +2,4 @@
exports[`布尔_误差共线_误差交点 1`] = `739590.0297771678`; exports[`布尔_误差共线_误差交点 1`] = `739590.0297771678`;
exports[`布尔_误差共线_误差交点 2`] = `739582.752529773`; exports[`布尔_误差共线_误差交点 2`] = `739582.7655079779`;

@ -57,7 +57,7 @@ test("包含差集的对象,差一点就可以切断", () =>
let regs: Region[] = LoadRegionsFromFileData(data); let regs: Region[] = LoadRegionsFromFileData(data);
regs[0].BooleanOper(regs[1], BoolOpeartionType.Subtract); regs[0].BooleanOper(regs[1], BoolOpeartionType.Subtract);
expect(regs[0].ShapeManager.ShapeCount).toBe(1); expect(regs[0].ShapeManager.ShapeCount).toBe(2);
expect(regs[0].ShapeManager.ShapeList[0].Holes.length).toBe(0); expect(regs[0].ShapeManager.ShapeList[0].Holes.length).toBe(0);
}); });

@ -18,3 +18,11 @@ test('布尔_误差共线_误差交点', () =>
expect(regs[0].Area).toMatchSnapshot(); expect(regs[0].Area).toMatchSnapshot();
}); });
test('误差打断', () =>
{
let d = [2, "Region", 3, 2, 780, false, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1270.0801901174855, 251.0534593864627, 0, 1], 1, 1, 1, 1, "Polyline", 3, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1270.0801901174855, 251.0534593864627, 0, 1], 2, 7, [337.0932869688667, -418.03134104109404], 0, [482, -246.84009191289078], 0, [482, -146.84009191289078], 0, [582, -146.84009191289078], 0, [582, 573.0000000000002], 0, [0, 573.0000000000002], 0, [0, -418.03134104109404], 0, true, 0, "Region", 3, 2, 779, false, 1, 7, 0, [-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, -872.726286511064, -95.7866325264281, 0, 1], 1, 1, 1, 1, "Polyline", 3, 2, 0, false, 0, 7, 0, [-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, -872.726286511064, -95.7866325264281, 0, 1], 2, 4, [0, 0], 0, [397.3539036064214, 0], 0, [397.3539036064214, 18], 0, [0, 18], 0, true, 0]
let regs = LoadRegionsFromFileData(d);
regs[0].BooleanOper(regs[1], BoolOpeartionType.Subtract);
expect(regs[0].ShapeManager.ShapeList.length).toBe(2);
});

@ -22,7 +22,7 @@
"@types/blueimp-md5": "^2.7.0", "@types/blueimp-md5": "^2.7.0",
"@types/html-webpack-plugin": "^3.2.0", "@types/html-webpack-plugin": "^3.2.0",
"@types/jest": "^24.0.13", "@types/jest": "^24.0.13",
"@types/node": "^12.0.1", "@types/node": "^12.0.2",
"@types/react": "^16.8.17", "@types/react": "^16.8.17",
"@types/react-color": "^3.0.0", "@types/react-color": "^3.0.0",
"@types/react-dom": "^16.8.4", "@types/react-dom": "^16.8.4",
@ -44,11 +44,11 @@
"gitlog": "^3.1.2", "gitlog": "^3.1.2",
"html-loader": "^0.5.5", "html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"jest": "^24.7.1", "jest": "^23.6.0",
"less": "^3.9.0", "less": "^3.9.0",
"less-loader": "^5.0.0", "less-loader": "^5.0.0",
"mobx-react-devtools": "^6.0.3", "mobx-react-devtools": "^6.0.3",
"react-hot-loader": "^4.8.4", "react-hot-loader": "^4.8.6",
"request": "^2.88.0", "request": "^2.88.0",
"request-promise-native": "^1.0.7", "request-promise-native": "^1.0.7",
"required-loader": "^1.3.16", "required-loader": "^1.3.16",
@ -58,7 +58,7 @@
"style-loader": "^0.23.1", "style-loader": "^0.23.1",
"terser-webpack-plugin": "^1.2.2", "terser-webpack-plugin": "^1.2.2",
"ts-jest": "^24.0.2", "ts-jest": "^24.0.2",
"ts-loader": "^6.0.0", "ts-loader": "^6.0.1",
"ts-node": "^8.1.0", "ts-node": "^8.1.0",
"tsconfig-paths": "^3.8.0", "tsconfig-paths": "^3.8.0",
"typescript": "^3.3.4000", "typescript": "^3.3.4000",
@ -66,7 +66,7 @@
"wallaby-webpack": "^3.9.15", "wallaby-webpack": "^3.9.15",
"webpack": "^4.31.0", "webpack": "^4.31.0",
"webpack-cli": "^3.3.2", "webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.3.1", "webpack-dev-server": "^3.4.1",
"webpack-merge": "^4.2.1" "webpack-merge": "^4.2.1"
}, },
"dependencies": { "dependencies": {
@ -74,7 +74,7 @@
"blueimp-md5": "^2.10.0", "blueimp-md5": "^2.10.0",
"golden-layout": "^1.5.9", "golden-layout": "^1.5.9",
"mobx": "^5.9.4", "mobx": "^5.9.4",
"mobx-react": "^5.4.3", "mobx-react": "^5.4.4",
"react": "^16.8.2", "react": "^16.8.2",
"react-color": "^2.17.3", "react-color": "^2.17.3",
"react-dom": "^16.8.2", "react-dom": "^16.8.2",

@ -31,7 +31,7 @@ export class DrawRegion implements Command
} }
if (lines.length > 0) if (lines.length > 0)
{ {
let reg = new RegionParse(lines); let reg = new RegionParse(lines, 3);
for (let routes of reg.m_RegionsOutline) for (let routes of reg.m_RegionsOutline)
this.DrawRegion(routes); this.DrawRegion(routes);

@ -178,7 +178,7 @@ export function curveLinkGroup(cus: Curve[]): Array<Array<Curve>>
return groupCus; return groupCus;
} }
export function equalCurve(cu1: Curve, cu2: Curve) export function equalCurve(cu1: Curve, cu2: Curve, tolerance = 1e-4)
{ {
if ((cu1 instanceof Polyline) && (cu2 instanceof Polyline)) if ((cu1 instanceof Polyline) && (cu2 instanceof Polyline))
{ {
@ -219,12 +219,12 @@ export function equalCurve(cu1: Curve, cu2: Curve)
buls2.push(buls2.shift()); buls2.push(buls2.shift());
} }
if (cu1.IsClose && equalv2(pts1[0], arrayLast(pts1), 1e-6)) if (cu1.IsClose && equalv2(pts1[0], arrayLast(pts1), tolerance))
{ {
pts1.pop(); pts1.pop();
buls1.pop(); buls1.pop();
} }
if (cu2.IsClose && equalv2(pts2[0], arrayLast(pts2), 1e-6)) if (cu2.IsClose && equalv2(pts2[0], arrayLast(pts2), tolerance))
{ {
pts2.pop(); pts2.pop();
buls2.pop(); buls2.pop();
@ -232,7 +232,7 @@ export function equalCurve(cu1: Curve, cu2: Curve)
let cu1Sp = Vec3DTo2D(cu1.StartPoint.applyMatrix4(cu2.OCSInv)); let cu1Sp = Vec3DTo2D(cu1.StartPoint.applyMatrix4(cu2.OCSInv));
let index = pts2.findIndex(p => equalv2(cu1Sp, p, 1e-5)); let index = pts2.findIndex(p => equalv2(cu1Sp, p, tolerance));
changeArrayStartIndex(buls2, index); changeArrayStartIndex(buls2, index);
changeArrayStartIndex(pts2, index); changeArrayStartIndex(pts2, index);
@ -241,7 +241,7 @@ export function equalCurve(cu1: Curve, cu2: Curve)
equalv3( equalv3(
Vec2DTo3D(p1).applyMatrix4(cu1.OCS), Vec2DTo3D(p1).applyMatrix4(cu1.OCS),
Vec2DTo3D(p2).applyMatrix4(cu2.OCS), Vec2DTo3D(p2).applyMatrix4(cu2.OCS),
1e-4 tolerance
) )
); );
} }

@ -1,10 +1,10 @@
import * as THREE from "three"; import * as THREE from "three";
import { Vector3 } from "three"; import { Vector3 } from "three";
import { arrayRemoveDuplicateBySort, arrayRemoveIf } from "../Common/ArrayExt"; import { arrayRemoveDuplicateBySort, arrayRemoveIf, arrayLast } from "../Common/ArrayExt";
import { curveLinkGroup, equalCurve, Vec3DTo2D, getCirAngleByChordAndTangent } from "../Common/CurveUtils"; import { curveLinkGroup, equalCurve } from "../Common/CurveUtils";
import { Status } from "../Common/Status"; import { Status } from "../Common/Status";
import { FixIndex } from "../Common/Utils"; import { FixIndex } from "../Common/Utils";
import { equaln, rotatePoint } from "../Geometry/GeUtils"; import { equaln, rotatePoint, equalv3, equalv2 } from "../Geometry/GeUtils";
import { RegionParse, Route } from "../Geometry/RegionParse"; import { RegionParse, Route } from "../Geometry/RegionParse";
import { isTargetCurInOrOnSourceCur } from "../GraphicsSystem/BoolOperateUtils"; import { isTargetCurInOrOnSourceCur } from "../GraphicsSystem/BoolOperateUtils";
import { IntersectOption } from "../GraphicsSystem/IntersectWith"; import { IntersectOption } from "../GraphicsSystem/IntersectWith";
@ -138,7 +138,7 @@ export class Contour
if (subtractList.every(c => c.IsClose)) if (subtractList.every(c => c.IsClose))
return Contour.GetAllContour(subtractList); return Contour.GetAllContour(subtractList);
let regParse = new RegionParse(subtractList); let regParse = new RegionParse(subtractList, 2);
let contours: Contour[] = []; let contours: Contour[] = [];
//分析封闭包围区域 //分析封闭包围区域
@ -264,62 +264,55 @@ export class Contour
} }
GetSubtractList(target: Contour) GetSubtractList(target: Contour)
{ {
let sourceOutline = this.m_Curve; let sourceOutline = this.m_Curve as Polyline;
let targetOutline = target.Curve; let targetOutline = target.Curve as Polyline;
if (target.CuInOutline(sourceOutline))
return [];
let interPts = sourceOutline.IntersectWith(targetOutline, IntersectOption.OnBothOperands);
let sourceContainerTarget = this.CuInOutline(targetOutline); let interPts = sourceOutline.IntersectWith(targetOutline, IntersectOption.OnBothOperands, 1e-3);
//包含.相交.分离(三种状态) if (interPts.length <= 1)
if (sourceContainerTarget && interPts.length <= 1)//源包含目标
{
return [sourceOutline, targetOutline];
}
else if (interPts.length <= 1)//分离
{ {
return [sourceOutline]; //反包含
if (fastCurveInCurve2(targetOutline, sourceOutline))
return [];
//包含
if (fastCurveInCurve2(sourceOutline, targetOutline))
return [sourceOutline, targetOutline];
else//分离
return [sourceOutline];
} }
else//相交 interPts.length > 0
{
let subtractList: Curve[] = [];
let sourceCus = sourceOutline.GetSplitCurvesByPts(interPts); //相交
let targetCus = targetOutline.GetSplitCurvesByPts(interPts); let subtractList: Curve[] = [];
let sourceCus = sourceOutline.GetSplitCurvesByPts(interPts) as Polyline[];
let targetCus = targetOutline.GetSplitCurvesByPts(interPts) as Polyline[];
for (let pl of sourceCus) for (let pl of sourceCus)
{
let hasEqualCus = false;
arrayRemoveIf(targetCus, cu =>
{ {
let hasEqualCus = false; if (hasEqualCus) return false;
arrayRemoveIf(targetCus, cu => hasEqualCus = fastEqualCurve(cu, pl);
{ return hasEqualCus;
if (hasEqualCus) return false; });
hasEqualCus = equalCurve(cu, pl); if (hasEqualCus)
return hasEqualCus; continue;
});
if (hasEqualCus) if (!fastCurveInCurve(targetOutline, pl))
continue; subtractList.push(pl);
}
if (!target.CuInOutline(pl))
subtractList.push(pl);
}
//源对象没有被破坏 //源对象没有被破坏
let sourceNotBreak = subtractList.length === sourceCus.length; let sourceNotBreak = subtractList.length === sourceCus.length;
for (let pl of targetCus) for (let pl of targetCus)
{ if (fastCurveInCurve(sourceOutline, pl))
if (this.CuInOutline(pl)) subtractList.push(pl);
subtractList.push(pl);
}
if (sourceNotBreak && subtractList.length === sourceCus.length) if (sourceNotBreak && subtractList.length === sourceCus.length)
return [sourceOutline]; return [sourceOutline];
return subtractList; return subtractList;
}
} }
/** /**
* 线 * 线
@ -348,7 +341,7 @@ export class Contour
* @param [needLink=true] * @param [needLink=true]
* @returns 线,1,. * @returns 线,1,.
*/ */
static Combine(cus: Curve[], needLink = true): Curve static Combine(cus: Curve[], needLink = true, tolerance = 1e-3): Curve
{ {
if (cus.length === 0) return undefined; if (cus.length === 0) return undefined;
@ -369,7 +362,15 @@ export class Contour
arrayRemoveDuplicateBySort(gclone, (cu1: Curve, cu2: Curve) => cu1.Join(cu2) === Status.True); arrayRemoveDuplicateBySort(gclone, (cu1: Curve, cu2: Curve) => cu1.Join(cu2) === Status.True);
for (let cu of gclone) for (let cu of gclone)
pl.Join(cu); pl.Join(cu, false, tolerance);
let d = pl.LineData;
if (d.length > 1)
{
let ld = arrayLast(d).pt;
if (equalv2(d[0].pt, ld, tolerance))
ld.copy(d[0].pt);
}
cache.set(g, pl); cache.set(g, pl);
@ -390,3 +391,35 @@ export class Contour
return equalCurve(this.m_Curve, tar.m_Curve); return equalCurve(this.m_Curve, tar.m_Curve);
} }
} }
/**
* 线,使
*/
function fastEqualCurve(c1: Polyline, c2: Polyline, tolerance = 1e-3)
{
let sp1 = c1.StartPoint;
let ep1 = c1.EndPoint;
let sp2 = c2.StartPoint;
let ep2 = c2.EndPoint;
if (!(
(equalv3(sp1, sp2, tolerance) && equalv3(ep1, ep2, tolerance))
|| (equalv3(sp1, ep2, tolerance) && equalv3(ep1, sp2, tolerance))
))
return false;
return equalv3(c1.GetPointAtParam(c1.EndParam * 0.5), c2.GetPointAtParam(c2.EndParam * 0.5), tolerance);
}
//对于双多段线互相切割后的结果,快速判断曲线是否在另一条曲线内部
function fastCurveInCurve(sourceCu: Polyline, targetCu: Polyline)
{
return sourceCu.PtInCurve(targetCu.GetPointAtParam(targetCu.EndParam * 0.5));
}
function fastCurveInCurve2(sourceCu: Polyline, targetCu: Polyline)
{
return sourceCu.PtInCurve(targetCu.StartPoint) &&
sourceCu.PtInCurve(targetCu.GetPointAtParam(targetCu.EndParam * 0.5));
}

@ -126,7 +126,7 @@ export abstract class Curve extends Entity
* @returns {boolean} * @returns {boolean}
* @memberof Curve * @memberof Curve
*/ */
Join(cu: Curve): Status { return Status.False; } Join(cu: Curve, allowGap = false, tolerance = 1e-4): Status { return Status.False; }
//翻转曲线.首尾调换. //翻转曲线.首尾调换.
Reverse(): this { return this; } Reverse(): this { return this; }
@ -155,7 +155,7 @@ export abstract class Curve extends Entity
* @returns {Vector3[]} * @returns {Vector3[]}
* @memberof Curve * @memberof Curve
*/ */
IntersectWith(curve: Curve, intType: IntersectOption): Vector3[] { return []; } IntersectWith(curve: Curve, intType: IntersectOption, tolerance = 1e-6): Vector3[] { return []; }
//------------------绘制相关------------------ //------------------绘制相关------------------
GetDrawObjectFromRenderType(renderType: RenderType = RenderType.Wireframe): Object3D GetDrawObjectFromRenderType(renderType: RenderType = RenderType.Wireframe): Object3D

@ -157,27 +157,27 @@ export class Line extends Curve
return this.EndPoint.sub(this.StartPoint); return this.EndPoint.sub(this.StartPoint);
} }
IntersectWith(curve: Curve, intType: IntersectOption): Vector3[] IntersectWith(curve: Curve, intType: IntersectOption, tolerance = 1e-6): Vector3[]
{ {
if (curve instanceof Line) if (curve instanceof Line)
{ {
return IntersectLineAndLine(this, curve, intType); return IntersectLineAndLine(this, curve, intType, tolerance);
} }
if (curve instanceof Arc) if (curve instanceof Arc)
{ {
return IntersectLineAndArc(this, curve, intType); return IntersectLineAndArc(this, curve, intType, tolerance);
} }
if (curve instanceof Circle) if (curve instanceof Circle)
{ {
return IntersectLineAndCircle(this, curve, intType); return IntersectLineAndCircle(this, curve, intType, tolerance);
} }
if (curve instanceof Polyline) if (curve instanceof Polyline)
{ {
return IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType)); return IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType), tolerance);
} }
if (curve instanceof Ellipse) if (curve instanceof Ellipse)
return IntersectEllipseAndLine(this, curve, intType); return IntersectEllipseAndLine(this, curve, intType, tolerance);
//其他的尚未实现. //其他的尚未实现.
return []; return [];
@ -294,7 +294,7 @@ export class Line extends Curve
} }
} }
Join(cu: Curve, allowGap = false, fuzz = 1e-5): Status Join(cu: Curve, allowGap = false, tolerance = 1e-5): Status
{ {
if (cu instanceof Line) if (cu instanceof Line)
{ {
@ -304,18 +304,18 @@ export class Line extends Curve
let sp = cu.StartPoint; let sp = cu.StartPoint;
let { closestPt: cp1, param: param1 } = this.GetClosestAtPoint(sp, true); let { closestPt: cp1, param: param1 } = this.GetClosestAtPoint(sp, true);
if (!equalv3(sp, cp1, fuzz))//点在曲线上,允许较低的精度 if (!equalv3(sp, cp1, tolerance))//点在曲线上,允许较低的精度
return Status.False; return Status.False;
let ep = cu.EndPoint; let ep = cu.EndPoint;
let { closestPt: cp2, param: param2 } = this.GetClosestAtPoint(ep, true); let { closestPt: cp2, param: param2 } = this.GetClosestAtPoint(ep, true);
if (!equalv3(ep, cp2, fuzz)) if (!equalv3(ep, cp2, tolerance))
return Status.False; return Status.False;
if (param1 > param2) if (param1 > param2)
[param1, param2] = [param2, param1]; [param1, param2] = [param2, param1];
if (allowGap || Math.max(0, param1) < Math.min(1, param2) + fuzz) if (allowGap || Math.max(0, param1) < Math.min(1, param2) + tolerance)
{ {
if (param1 < 0) if (param1 < 0)
this.Extend(param1); this.Extend(param1);

@ -688,7 +688,7 @@ export class Polyline extends Curve
} }
} }
Join(cu: Curve, fuzz = 1e-4) Join(cu: Curve, allowGap = false, tolerance = 1e-4)
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
if (this.m_ClosedMark) if (this.m_ClosedMark)
@ -727,19 +727,19 @@ export class Polyline extends Curve
if (cu instanceof Line) if (cu instanceof Line)
{ {
if (equalv3(cuSp, sp, fuzz)) if (equalv3(cuSp, sp, tolerance))
{ {
this.m_LineData.unshift({ pt: cuEp2, bul: 0 }); this.m_LineData.unshift({ pt: cuEp2, bul: 0 });
} }
else if (equalv3(cuSp, ep, fuzz)) else if (equalv3(cuSp, ep, tolerance))
{ {
this.m_LineData.push({ pt: cuEp2, bul: 0 }); this.m_LineData.push({ pt: cuEp2, bul: 0 });
} }
else if (equalv3(cuEp, sp, fuzz)) else if (equalv3(cuEp, sp, tolerance))
{ {
this.m_LineData.unshift({ pt: cuSp2, bul: 0 }); this.m_LineData.unshift({ pt: cuSp2, bul: 0 });
} }
else if (equalv3(cuEp, ep, fuzz)) else if (equalv3(cuEp, ep, tolerance))
{ {
this.m_LineData.push({ pt: cuSp2, bul: 0 }); this.m_LineData.push({ pt: cuSp2, bul: 0 });
} }
@ -750,20 +750,20 @@ export class Polyline extends Curve
{ {
let dir = equalv3(this.Normal, cu.Normal.negate()) ? -1 : 1; let dir = equalv3(this.Normal, cu.Normal.negate()) ? -1 : 1;
let bul = cu.Bul * dir; let bul = cu.Bul * dir;
if (equalv3(cuSp, sp, fuzz)) if (equalv3(cuSp, sp, tolerance))
{ {
this.m_LineData.unshift({ pt: cuEp2, bul: -bul }); this.m_LineData.unshift({ pt: cuEp2, bul: -bul });
} }
else if (equalv3(cuSp, ep, fuzz)) else if (equalv3(cuSp, ep, tolerance))
{ {
arrayLast(this.m_LineData).bul = bul; arrayLast(this.m_LineData).bul = bul;
this.m_LineData.push({ pt: cuEp2, bul: 0 }); this.m_LineData.push({ pt: cuEp2, bul: 0 });
} }
else if (equalv3(cuEp, sp, fuzz)) else if (equalv3(cuEp, sp, tolerance))
{ {
this.m_LineData.unshift({ pt: cuSp2, bul: bul }); this.m_LineData.unshift({ pt: cuSp2, bul: bul });
} }
else if (equalv3(cuEp, ep, fuzz)) else if (equalv3(cuEp, ep, tolerance))
{ {
arrayLast(this.m_LineData).bul = -bul; arrayLast(this.m_LineData).bul = -bul;
this.m_LineData.push({ pt: cuSp2, bul: 0 }); this.m_LineData.push({ pt: cuSp2, bul: 0 });
@ -779,7 +779,7 @@ export class Polyline extends Curve
let { pts, buls } = this.PtsBuls; let { pts, buls } = this.PtsBuls;
if (equalv3(cuSp, sp, fuzz)) if (equalv3(cuSp, sp, tolerance))
{ {
cu.Reverse(); cu.Reverse();
let cuPtsBul = cu.PtsBuls; let cuPtsBul = cu.PtsBuls;
@ -788,7 +788,7 @@ export class Polyline extends Curve
pts = cuPtsBul.pts.concat(pts); pts = cuPtsBul.pts.concat(pts);
buls = cuPtsBul.buls.concat(buls); buls = cuPtsBul.buls.concat(buls);
} }
else if (equalv3(cuSp, ep, fuzz)) else if (equalv3(cuSp, ep, tolerance))
{ {
pts.pop(); pts.pop();
buls.pop(); buls.pop();
@ -797,7 +797,7 @@ export class Polyline extends Curve
pts = pts.concat(cuPtsBul.pts); pts = pts.concat(cuPtsBul.pts);
buls = buls.concat(cuPtsBul.buls); buls = buls.concat(cuPtsBul.buls);
} }
else if (equalv3(cuEp, sp, fuzz)) else if (equalv3(cuEp, sp, tolerance))
{ {
let cuPtsBul = cu.PtsBuls; let cuPtsBul = cu.PtsBuls;
cuPtsBul.pts.pop(); cuPtsBul.pts.pop();
@ -805,7 +805,7 @@ export class Polyline extends Curve
pts = cuPtsBul.pts.concat(pts); pts = cuPtsBul.pts.concat(pts);
buls = cuPtsBul.buls.concat(buls); buls = cuPtsBul.buls.concat(buls);
} }
else if (equalv3(cuEp, ep, fuzz)) else if (equalv3(cuEp, ep, tolerance))
{ {
pts.pop(); pts.pop();
buls.pop(); buls.pop();
@ -987,9 +987,9 @@ export class Polyline extends Curve
} }
} }
IntersectWith(curve: Curve, intType: IntersectOption): Vector3[] IntersectWith(curve: Curve, intType: IntersectOption, tolerance = 1e-6): Vector3[]
{ {
return IntersectPolylineAndCurve(this, curve, intType); return IntersectPolylineAndCurve(this, curve, intType, tolerance);
} }
//计算自交点. //计算自交点.

@ -46,7 +46,7 @@ export class RegionParse
* @param {Curve[]} cuList . * @param {Curve[]} cuList .
* @memberof RegionParse * @memberof RegionParse
*/ */
constructor(cuList: Curve[], public fractionDigits?) constructor(cuList: Curve[], public fractionDigits = 3)
{ {
//需要搜索的站 //需要搜索的站
let needFinds = this.GenerateNodeMap(cuList); let needFinds = this.GenerateNodeMap(cuList);

@ -52,11 +52,11 @@ export function reverseIntersectOption(intType: IntersectOption)
* @param {Intersect} extType . * @param {Intersect} extType .
* @returns {Array<Vector3>} * @returns {Array<Vector3>}
*/ */
function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, extType: IntersectOption, fuzz = 1e-4): Array<Vector3> function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, extType: IntersectOption, tolerance = 1e-6): Array<Vector3>
{ {
return intPts.filter(p => return intPts.filter(p =>
{ {
return (extType & IntersectOption.ExtendThis || c1.PtOnCurve(p, fuzz)) && (extType & IntersectOption.ExtendArg || c2.PtOnCurve(p, fuzz)) return (extType & IntersectOption.ExtendThis || c1.PtOnCurve(p, tolerance)) && (extType & IntersectOption.ExtendArg || c2.PtOnCurve(p, tolerance))
}); });
} }
@ -119,10 +119,10 @@ export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
* @param {IntersectOption} extType * @param {IntersectOption} extType
* @returns * @returns
*/ */
export function IntersectCircleAndArc(circle: Circle, arc: Arc, extType: IntersectOption) export function IntersectCircleAndArc(circle: Circle, arc: Arc, extType: IntersectOption, tolerance = 1e-6)
{ {
let pts = IntersectCircleAndCircle(circle, arc); let pts = IntersectCircleAndCircle(circle, arc);
return CheckPointOnCurve(pts, circle, arc, extType | IntersectOption.ExtendThis); return CheckPointOnCurve(pts, circle, arc, extType | IntersectOption.ExtendThis, tolerance);
} }
/** /**
@ -134,16 +134,16 @@ export function IntersectCircleAndArc(circle: Circle, arc: Arc, extType: Interse
* @param {IntersectOption} extType * @param {IntersectOption} extType
* @returns * @returns
*/ */
export function IntersectArcAndArc(arc1: Arc, arc2: Arc, extType: IntersectOption) export function IntersectArcAndArc(arc1: Arc, arc2: Arc, extType: IntersectOption, tolerance = 1e-6)
{ {
let pts = IntersectCircleAndCircle(arc1, arc2); let pts = IntersectCircleAndCircle(arc1, arc2);
return CheckPointOnCurve(pts, arc1, arc2, extType); return CheckPointOnCurve(pts, arc1, arc2, extType, tolerance);
} }
export function IntersectEllipseAndLine(l: Line, el: Ellipse, extType: IntersectOption) export function IntersectEllipseAndLine(l: Line, el: Ellipse, extType: IntersectOption, tolerance = 1e-6)
{ {
let pts = IntersectLineAndEllipseFor2D(l, el); let pts = IntersectLineAndEllipseFor2D(l, el);
return CheckPointOnCurve(pts, l, el, extType); return CheckPointOnCurve(pts, l, el, extType, tolerance);
} }
/** /**
@ -183,19 +183,19 @@ function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc)
} }
//直线和圆 //直线和圆
export function IntersectLineAndCircle(line: Line, circle: Circle, extType: IntersectOption) export function IntersectLineAndCircle(line: Line, circle: Circle, extType: IntersectOption, tolerance = 1e-6)
{ {
let ptArr = IntersectLineAndCircleOrArc(line, circle); let ptArr = IntersectLineAndCircleOrArc(line, circle);
return CheckPointOnCurve(ptArr, line, circle, extType | IntersectOption.ExtendArg); return CheckPointOnCurve(ptArr, line, circle, extType | IntersectOption.ExtendArg);
} }
//直线和圆弧 //直线和圆弧
export function IntersectLineAndArc(line: Line, arc: Arc, extType: IntersectOption) export function IntersectLineAndArc(line: Line, arc: Arc, extType: IntersectOption, tolerance = 1e-6)
{ {
let ptArr = IntersectLineAndCircleOrArc(line, arc); let ptArr = IntersectLineAndCircleOrArc(line, arc);
return CheckPointOnCurve(ptArr, line, arc, extType); return CheckPointOnCurve(ptArr, line, arc, extType);
} }
//直线和直线 //直线和直线
export function IntersectLAndLFor2D(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3): Vector3 export function IntersectLAndLFor2D(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3, tolerance = 1e-6): Vector3
{ {
let dx1 = p1.x - p2.x; let dx1 = p1.x - p2.x;
let dx2 = p3.x - p4.x; let dx2 = p3.x - p4.x;
@ -317,7 +317,7 @@ export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOptio
return [pt]; return [pt];
} }
export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: IntersectOption): Vector3[] export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: IntersectOption, tolerance = 1e-6): Vector3[]
{ {
let cus: Curve[] = pl.Explode(); let cus: Curve[] = pl.Explode();
let cus2: Curve[]; let cus2: Curve[];
@ -349,7 +349,7 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte
if ((cu instanceof Polyline && cu.CloseMark) || !(isStart2 || isEnd2)) if ((cu instanceof Polyline && cu.CloseMark) || !(isStart2 || isEnd2))
ext = ext & ~IntersectOption.ExtendArg; ext = ext & ~IntersectOption.ExtendArg;
let ipts = cu1.IntersectWith(cu2, ext).filter(p1 => pts.every(p2 => !equalv3(p1, p2))); let ipts = cu1.IntersectWith(cu2, ext, tolerance).filter(p1 => pts.every(p2 => !equalv3(p1, p2)));
//校验延伸 //校验延伸
if (IntersectOption.ExtendThis & ext) if (IntersectOption.ExtendThis & ext)

@ -0,0 +1,70 @@
import * as fs from "fs";
import * as path from "path";
import { LoadRegionsFromFileData } from "../__test__/Utils/LoadEntity.util";
import { Region } from "../src/DatabaseServices/Region";
import { BoolOpeartionType } from "../src/GraphicsSystem/BoolOperateUtils";
function a(testfile: string)
{
testfile = path.resolve(__dirname, testfile);
let stream = fs.createReadStream(testfile);
let remaining = "";
stream.on("data", function (data: string)
{
remaining += data;
let index = remaining.indexOf('\n');
while (index > -1)
{
let line = remaining.substring(0, index);
remaining = remaining.substring(index + 1);
gg(line);
index = remaining.indexOf('\n');
}
});
stream.on('end', function ()
{
console.log(JSON.stringify(datas));
stream.close();
});
}
function testBool(regs: Region[])
{
console.time();
regs[0].Clone().BooleanOper(regs[1].Clone(), BoolOpeartionType.Intersection);
regs[0].Clone().BooleanOper(regs[1].Clone(), BoolOpeartionType.Subtract);
regs[0].Clone().BooleanOper(regs[1].Clone(), BoolOpeartionType.Union);
console.timeEnd();
}
let datas = [];
function gg(d: string)
{
d = d.trimLeft();
try
{
if (d[0] === "[")
{
let data = JSON.parse(d);
let regs = LoadRegionsFromFileData(data);
// testBool(regs);
datas.push(d);
}
}
catch (error)
{
}
}
a("../__test__/Booloperate/bool2.test.ts");
Loading…
Cancel
Save