!1994 修复:布尔运算错误

pull/1996/head
ChenX 2 years ago
parent 99d36426d3
commit 844be4b87f

@ -12,6 +12,6 @@ exports[`弧形板差集 1`] = `"165548.36110"`;
exports[`弧形板差集 2`] = `"331151.31924"`; exports[`弧形板差集 2`] = `"331151.31924"`;
exports[`弧形板差集2 1`] = `"165548.36023"`; exports[`弧形板差集2 1`] = `"165548.36110"`;
exports[`弧形板差集2 2`] = `"331151.31924"`; exports[`弧形板差集2 2`] = `"331151.31924"`;

@ -181,3 +181,12 @@ test('精度不一致导致的错误', () =>
let brs = LoadBoardsFromFileData(d); let brs = LoadBoardsFromFileData(d);
testPathCount(brs[0]); testPathCount(brs[0]);
}); });
test('重复点过多导致的布尔错误', () =>
{
let d =
{ "file": [1, "Board", 8, 2, 136, false, 1, 2, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1542.6178010471249, -3757.536467706971, 295.8115183248293, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1542.6178010471249, -3757.536467706971, 295.8115183248293, 1], 0, 3, 940.000000000005, 2350.0000000000005, 15, false, "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, [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 3749.7485095917887, 3196.3743455497456, -295.8115183247719, 1], 0, 2, 5, [4.547473508864641e-13, 5.002220859751105e-12], 0, [2120.0000000000005, 0], 0, [2350.0000000000005, 470], 0, [2119.999999999999, 940.0000000000018], 0, [0, 940.000000000005], 0, true, 1, 3, 860.0000238166186, 1812.0534983379844, 6, false, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -490.0437608700008, -39.999988091681296, 0, 1], 0, 0, true, [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 3259.704748721788, 3156.3743574580644, -295.8115183247719, 1], 0, 2, 10, [490.04376087000173, 70.00000001851413], 0.41421356237309515, [520.0437608891084, 40.000000000005], 0, [2076.0437608563307, 40.00000000000682], 0.28638958411744386, [2103.043760858855, 56.8134140582747], 0, [2299.043760864549, 456.8134140698744], 0.23156094812233494, [2299.0437608753277, 483.186585909139], 0, [2103.0437608687926, 883.1865859224918], 0.2863895839754242, [2076.043760888381, 900.000000000005], 0, [520.0437608891084, 899.9999999999914], 0.41421356237309503, [490.0437608700008, 869.9999999808838], 0, true, 1, 3, 835.0035209518353, 1787.7812073629661, 6, false, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -502.0437608700008, -52.49823952408596, 0, 1], 0, 0, true, [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 3247.704748721788, 3143.8761060256597, -295.8115183247719, 1], 0, 2, 10, [520.0437608700017, 52.500000000005], 0, [2076.043760871718, 52.500000000005], 0.2863895839882779, [2092.0437608700017, 62.30782488000614], 0, [2288.043760862396, 462.3078248655029], 0.23156094827558482, [2288.0437608700017, 477.69217512000387], 0, [2092.043760870679, 877.6921751186296], 0.28638958402109244, [2076.0437608700017, 887.500000000005], 0, [520.0437608699726, 887.5000000000032], 0.4142135620001939, [502.04376087000173, 869.9999999999468], 0, [502.0437608700008, 70.00000000003229], 0.41421356200142434, true, 0, 3, 0, 0, 0, 0, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1490.119561523039, -3255.4927068369702, 304.8115183248293, 1], 3, 0, 0, 0, 0, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1502.6178129554437, -3267.4927068369702, 304.8115183248293, 1], 3, 0, 0, 0, 0, 0, 10, 0, "层板", "", "", "", "", "", 1, 0, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 5, "三合一", "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, 0, 0], "basePt": { "x": 602.6178010471199, "y": -3757.536467706971, "z": 295.8115183248293 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1542.6178010471249, -3757.536467706971, 295.8115183248293, 1] };
let brs = LoadBoardsFromFileData(d);
testPathCount(brs[0]);
});

@ -304,6 +304,10 @@ exports[`造型的外框和内框厚度等于刀直径 1`] = `"1459.45340"`;
exports[`造型的外框和内框厚度等于刀直径: 走刀数量 1`] = `1`; exports[`造型的外框和内框厚度等于刀直径: 走刀数量 1`] = `1`;
exports[`重复点过多导致的布尔错误 1`] = `"23133.26713"`;
exports[`重复点过多导致的布尔错误: 走刀数量 1`] = `1`;
exports[`门字部分 1`] = `"1.76759"`; exports[`门字部分 1`] = `"1.76759"`;
exports[`门字部分 2`] = `"8.75659"`; exports[`门字部分 2`] = `"8.75659"`;

@ -88,7 +88,7 @@ exports[`千年舟 绿色健康之家 43`] = `"127.53520"`;
exports[`千年舟 绿色健康之家 44`] = `"130.77685"`; exports[`千年舟 绿色健康之家 44`] = `"130.77685"`;
exports[`千年舟 绿色健康之家 45`] = `"112.29087"`; exports[`千年舟 绿色健康之家 45`] = `"112.29088"`;
exports[`千年舟 绿色健康之家 46`] = `"141.29953"`; exports[`千年舟 绿色健康之家 46`] = `"141.29953"`;

@ -6,7 +6,7 @@ import { FixIndex } from "../Common/Utils";
import { IntersectBox2 } from "../Geometry/Box"; import { IntersectBox2 } from "../Geometry/Box";
import { CreateContour2 } from "../Geometry/CreateContour2"; import { CreateContour2 } from "../Geometry/CreateContour2";
import { Route } from "../Geometry/CurveMap"; import { Route } from "../Geometry/CurveMap";
import { equaln, equalv2, equalv3 } from "../Geometry/GeUtils"; import { ComparePointFnGenerate, equaln, equalv2, equalv3 } from "../Geometry/GeUtils";
import { RegionParse } from "../Geometry/RegionParse"; import { RegionParse } from "../Geometry/RegionParse";
import { isTargetCurInOrOnSourceCur } from "../GraphicsSystem/BoolOperateUtils"; import { isTargetCurInOrOnSourceCur } from "../GraphicsSystem/BoolOperateUtils";
import { IntersectOption } from "../GraphicsSystem/IntersectWith"; import { IntersectOption } from "../GraphicsSystem/IntersectWith";
@ -424,7 +424,7 @@ export class Contour
let subtractList: Polyline[] = []; let subtractList: Polyline[] = [];
let holes: Polyline[] = []; let holes: Polyline[] = [];
let intPars: number[] = []; let intPars: number[] = [];
let cuMap = new Map<Curve, number[]>(); let curveIntParamsMap = new Map<Curve, number[]>();
let outBox = sourceOutline.BoundingBox; let outBox = sourceOutline.BoundingBox;
@ -451,59 +451,61 @@ export class Contour
} }
else else
{ {
let fn = ComparePointFnGenerate("xyz", 1e-4);
pts.sort((p1, p2) => fn(p1.pt, p2.pt));
arrayRemoveDuplicateBySort(pts, (p1, p2) => equalv2(p1.pt, p2.pt, 1e-4));
intPars.push(...pts.map(r => r.thisParam)); intPars.push(...pts.map(r => r.thisParam));
cuMap.set(targetOutline, pts.map(r => r.argParam)); curveIntParamsMap.set(targetOutline, pts.map(r => r.argParam));
} }
} }
intPars.sort((a, b) => a - b);
arrayRemoveDuplicateBySort(intPars, (e1, e2) => equaln(e1, e2, 1e-8));
let sourceCus = sourceOutline.GetSplitCurves(intPars) as Polyline[];
let targetCus: Polyline[] = [];
let targetMap = new WeakMap<Curve, Curve>(); let sourceSplitCurves = sourceOutline.GetSplitCurves(intPars) as Polyline[];
let targetSplitCurves: Polyline[] = [];
let isEqualNormal: boolean; let targetSplitCurve_CurvesMap = new WeakMap<Curve, Curve>();//分裂后->原始曲线 映射
for (let [c, pars] of cuMap) for (let [curve, intParams] of curveIntParamsMap)
{ {
let cus = c.GetSplitCurves(pars) as Polyline[];
cus.forEach(cu => targetMap.set(cu, c)); let splitCurves = curve.GetSplitCurves(intParams) as Polyline[];
targetCus.push(...cus); for (let splitCurve of splitCurves)
{
targetSplitCurve_CurvesMap.set(splitCurve, curve);
targetSplitCurves.push(splitCurve);
}
} }
for (let pl of sourceCus) for (let sourceSplitcu of sourceSplitCurves)
{ {
let plMidParam = pl.MidParam; let sourceDir = sourceSplitcu.GetFistDeriv(sourceSplitcu.MidParam).normalize();
let plDir = pl.GetFistDeriv(plMidParam).normalize();
let index = targetCus.findIndex(cu => fastEqualCurve(cu, pl, 0.05)); let index = targetSplitCurves.findIndex(cu => fastEqualCurve(cu, sourceSplitcu, 0.05));
if (index !== -1) if (index !== -1)
{ {
let cu = targetCus[index]; let targetSplitcu = targetSplitCurves[index];
isEqualNormal = equalv3(sourceOutline.Normal, targetMap.get(cu).Normal, 1e-3); let isEqualNormal = equalv3(sourceOutline.Normal, targetSplitCurve_CurvesMap.get(targetSplitcu).Normal, 1e-3);
let cuMidParam = cu.MidParam; let targetDir = targetSplitcu.GetFistDeriv(targetSplitcu.MidParam).normalize();
let cuDir = cu.GetFistDeriv(cuMidParam).normalize();
if (isEqualNormal === !equalv3(cuDir, plDir, 1e-3))//不同向 if (isEqualNormal === !equalv3(targetDir, sourceDir, 1e-3))//不同向
subtractList.push(pl); subtractList.push(sourceSplitcu);
targetCus.splice(index, 1); targetSplitCurves.splice(index, 1);
continue; continue;
} }
if (targets.every(t => !fastCurveInCurve(t.Curve as Polyline, pl))) if (targets.every(t => !fastCurveInCurve(t.Curve as Polyline, sourceSplitcu)))
subtractList.push(pl); subtractList.push(sourceSplitcu);
} }
//源对象没有被破坏 //源对象没有被破坏
let sourceNotBreak = subtractList.length === sourceCus.length; let sourceNotBreak = subtractList.length === sourceSplitCurves.length;
for (let pl of targetCus) for (let pl of targetSplitCurves)
if (fastCurveInCurve(sourceOutline, pl)) if (fastCurveInCurve(sourceOutline, pl))
subtractList.push(pl); subtractList.push(pl);
if (sourceNotBreak && subtractList.length === sourceCus.length) if (sourceNotBreak && subtractList.length === sourceSplitCurves.length)
return { subtractList: [sourceOutline], holes }; return { subtractList: [sourceOutline], holes };
return { subtractList, holes }; return { subtractList, holes };

@ -335,7 +335,7 @@ const comparePointCache: Map<string, compareVectorFn> = new Map();
* @param {string} sortKey * @param {string} sortKey
* @returns {compareVectorFn} * @returns {compareVectorFn}
*/ */
export function ComparePointFnGenerate(sortKey: string): compareVectorFn export function ComparePointFnGenerate(sortKey: string, fuzz = 1e-8): compareVectorFn
{ {
if (comparePointCache.has(sortKey)) if (comparePointCache.has(sortKey))
return comparePointCache.get(sortKey); return comparePointCache.get(sortKey);
@ -360,7 +360,7 @@ export function ComparePointFnGenerate(sortKey: string): compareVectorFn
{ {
let vv1 = v1.getComponent(s[0]); let vv1 = v1.getComponent(s[0]);
let vv2 = v2.getComponent(s[0]); let vv2 = v2.getComponent(s[0]);
if (equaln(vv1, vv2)) continue; if (equaln(vv1, vv2, fuzz)) continue;
if (vv2 > vv1) return s[1]; if (vv2 > vv1) return s[1];
else return -s[1]; else return -s[1];
} }

Loading…
Cancel
Save