!2287 修复:圆弧偏移距离不一致时,无法计算封边

pull/2233/MERGE
ChenX 1 year ago
parent 9db05fde2c
commit d25da19eff

@ -1,5 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`圆弧连接,连接失败了强行连接 1`] = `"420668.28959"`;
exports[`圆弧连接,连接失败了强行连接 2`] = `"421170.51803"`;
exports[`圆弧连接,连接失败了强行连接 3`] = `"5"`;
exports[`圆弧连接,连接失败了强行连接 4`] = `"5"`;
exports[`圆弧连接,连接失败了强行连接 5`] = `"5"`;
exports[`圆弧连接,连接失败了强行连接 6`] = `"173013.57414"`;
exports[`圆弧连接,连接失败了强行连接 7`] = `"175223.47125"`;
exports[`圆弧连接,连接失败了强行连接 8`] = `"6"`;
exports[`圆弧连接,连接失败了强行连接 9`] = `"5"`;
exports[`圆弧连接,连接失败了强行连接 10`] = `"5"`;
exports[`封边 1`] = `"3274.96050"`;
exports[`封边 2`] = `"3282.89002"`;

@ -64,3 +64,23 @@ test('特殊链接 圆弧间', () =>
expect(seald.highSeals.length).toMatchNumberSnapshot(0);
});
test('圆弧连接,连接失败了强行连接', () =>
{
let d =
{ "file": [2, "Board", 10, 2, 250, 0, 1, 2, 71, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 5420.396189184161, -2536.8980307174484, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 5420.396189184161, -2536.8980307174484, 0, 1], 0, 0, 1, 3, 827.7272727272722, 600.0000000000002, 18, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, 1, [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, -172.0808080808082, 47706.26352358669, 4737.41794856498, 1], 0, 0, 1, 2, 5, [363.08080808080774, 0], 0, [600.0000000000001, 0], 0, [600.0000000000002, 827.7272727272721], 0, [1.4210854715202004e-13, 827.7272727272721], 0, [0, 326.3131313131307], -0.20262143281721134, true, 0, 3, 0, 0, 0, 0, 0, 11, 0, "层板", "", "", "", "", "", 0, 0, "三合一", 2, 5, 0, 0, 0, 0, 1, "0", "0", "0", "0", "", "", "", 5, "三合一", "三合一", "三合一", "三合一", "三合一", true, true, 1, "1", "1", 0, 0, 0, 0, 0, 0, 0, true, 0, 0, null, "Board", 10, 2, 445, 0, 1, 2, 71, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1480.3203606069178, 844.0742138083208, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1480.3203606069178, 844.0742138083208, 0, 1], 0, 0, 1, 3, 705.3016287401363, 763.5607321131454, 18, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, 1, [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, -1363.0853726921553, -1423.7469138504698, 0, 1], 0, 0, 1, 2, 5, [763.5607321131454, -2.2737367544323206e-13], 0, [600.0000000000007, 705.301628740136], 0, [600.0000000000007, 301.23270721914173], 0.3784142003682244, [440.4202016404272, 480.2205344191484], 0, [0, 359.0682196339435], 0, true, 0, 3, 0, 0, 0, 0, 0, 11, 0, "层板", "", "", "", "", "", 0, 0, "三合一", 2, 5, 0, 0, 2, 0, 2, "0", "2", "2", "0", "", "", "", 5, "三合一", "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, 0, 0, null], "basePt": { "x": 775.0187318667815, "y": -2536.8980307174484, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] };
let brs = LoadEntityFromFileData(d) as Board[];
for (let br of brs)
{
let seald = GetSealedBoardContour(br);
expect(seald.sealedContour.Area2).toMatchNumberSnapshot();
expect(seald.brContour.Area2).toMatchNumberSnapshot();
expect(seald.sealedContour.EndParam).toMatchNumberSnapshot(0);
expect(seald.brContour.EndParam).toMatchNumberSnapshot(0);
expect(seald.highSeals.length).toMatchNumberSnapshot(0);
}
});

@ -884,6 +884,7 @@ test('多段线因为合并问题造成的错误', () =>
testOffset(pl, 37.8831);
});
//TODO: 这么小的测试用例似乎是没有意义的
test("正确的裁剪多段线", () =>
{
let pl = loadFile(

@ -1,5 +1,6 @@
import { Vector3 } from "three";
import { app } from "../ApplicationServices/Application";
import { Log } from "../Common/Log";
import { Intent, ToasterShowEntityMsg } from "../Common/Toaster";
import { FixedNotZero } from "../Common/Utils";
import { Board } from "../DatabaseServices/Entity/Board";
@ -39,7 +40,7 @@ export class TestFb implements Command
if (sealData)
{
let { brContour: brCon, sealedContour: sealedCon } = sealData;
sealedCon.ColorIndex = 8;//红色 扣封边的
sealedCon.ColorIndex = 1;//红色 扣封边的
showCus.push(brCon, sealedCon);
brSealMap.set(brCon, sealData);
}
@ -69,6 +70,8 @@ export class TestFb implements Command
let moveDist = 0;//x move
let moveV = new Vector3();//
Log("红色为扣完封边的轮廓!");
for (let i = 0; i < showCus.length; i++)
{
let curve = showCus[i];

@ -3,6 +3,8 @@ import { Entity } from "../../DatabaseServices/Entity/Entity";
export async function TestDraw(en: Entity | Entity[] | Object3D | Object3D[], colorIndex = 0)
{
if (!(globalThis.document && globalThis.document.getElementById("Webgl"))) return;
let app = (await import("../../ApplicationServices/Application"))?.app;
if (!app) return;

@ -19,6 +19,7 @@ export function Log(message?: any, ...optionalParams: any[]): void
export const _LogInjectInteractionFunctions: LogFunction[] = [];
//InteractionLog([{ msg: "警告:" }, { msg: `板件${br.Name}`, entity: [br, cyHole] }, { msg: "侧孔与板无交点,无法加工该侧孔!" }], LogType.Warning);
export function InteractionLog(message?: any, ...optionalParams: any[]): void
{
for (let f of _LogInjectInteractionFunctions)

@ -1,5 +1,7 @@
//为了避免Core对UI库的依赖,导致测试用例失败,导致外部项目引用失败,我们分离了这个函数
import { InteractionLog, LogType } from "./Log";
export enum Intent
{
NONE = "none",
@ -47,4 +49,9 @@ export function ToasterShowEntityMsg(option: {
{
for (let f of ToasterShowEntityMsgInjectFunctions)
f(option);
let logMsgs = [{ msg: option.msg }] as any[];
if (option.ent)
logMsgs.push({ msg: "点击查看", entity: Array.isArray(option.ent) ? option.ent : [option.ent] });
InteractionLog(logMsgs, LogType.Warning);
}

@ -2,6 +2,8 @@ import { Vector3 } from "three";
import { arrayRemoveIf } from "../Common/ArrayExt";
import { EBoardKeyList } from "../Common/BoardKeyList";
import { MergeCurvelist } from "../Common/CurveUtils";
import { InteractionLog, LogType } from "../Common/Log";
import { Intent, Toaster } from "../Common/Toaster";
import { FixIndex } from "../Common/Utils";
import { Contour } from "../DatabaseServices/Contour";
import { Board } from "../DatabaseServices/Entity/Board";
@ -282,7 +284,26 @@ class OffsetPolyline2 extends OffsetPolyline
/**
*
* ()()
* ()
*/
export function GetBoardContour(br: Board): ExtrudeContourCurve | undefined
{
if (Math.abs(br.ContourCurve.Area) < 10)
return;
let curves = GetBoardSealingCurves(br);
if (curves.length === 1 && curves[0] instanceof Circle)
return curves[0];
let brContour = Polyline.Combine(curves, 1e-3);
return brContour;
}
/**
* ()()
*/
export function GetSealedBoardContour(br: Board): BrSealedData | undefined
{
@ -342,14 +363,16 @@ export function GetSealedBoardContour(br: Board): BrSealedData | undefined
polylineOffset._SubCurves.push(c);//sub
//trim Circle
polylineOffset._Circles.push(new Circle(c.StartPoint, j === 0 ? Math.min(preSeal.size, seal.size) : seal.size));
if (seal.size && (j || seal.size === preSeal.size))
polylineOffset._Circles.push(new Circle(c.StartPoint, seal.size));
//offset
let offsetC = c.GetOffsetCurves(dir * -seal.size)[0];
if (offsetC)
polylineOffset._SubOffsetedCurves.push({
index: subIndex,
curve: offsetC
curve: offsetC,
dist: seal.size,
});
else
polylineOffset._TrimArcContours.push(Contour.CreateContour([c, new Line(c.StartPoint, c.EndPoint)], false));
@ -364,14 +387,16 @@ export function GetSealedBoardContour(br: Board): BrSealedData | undefined
polylineOffset._SubCurves.push(curve);//sub
//trim Circle
polylineOffset._Circles.push(new Circle(curve.StartPoint, Math.min(preSeal.size, seal.size)));
if (seal.size && seal.size === preSeal.size)
polylineOffset._Circles.push(new Circle(curve.StartPoint, seal.size));
//offset
let offsetC = curve.GetOffsetCurves(dir * -seal.size)[0];
if (offsetC)
polylineOffset._SubOffsetedCurves.push({
index: subIndex,
curve: offsetC
curve: offsetC,
dist: seal.size,
});
else
polylineOffset._TrimArcContours.push(Contour.CreateContour([curve, new Line(curve.StartPoint, curve.EndPoint)], false));
@ -388,6 +413,15 @@ export function GetSealedBoardContour(br: Board): BrSealedData | undefined
//如果有多个 取最大
if (sealedContours.length > 1)
{
Toaster({
message: `有板计算封边异常,请检查!(点击左下角提示可以查看该板)`,
timeout: 15000,
intent: Intent.WARNING,
key: "sealerror"
});
InteractionLog([{ msg: "警告:" }, { msg: `板:${br.Name}`, entity: [br] }, { msg: `在扣除封边计算中,得到了${sealedContours.length}条轮廓,请检查!` }], LogType.Warning);
let areas = sealedContours.map(p => p.Area);
let maxIndex = Max(areas, (a1, a2) => a2 > a1);
sealedContours = [sealedContours[maxIndex]];

@ -18,6 +18,8 @@ interface IOffsetResult
{
index: number;
curve: Curve;
/**偏移距离(仅在局部偏移时提供) */
dist?: number;
sp?: Vector3;
ep?: Vector3;
preCurve?: Curve;
@ -273,8 +275,9 @@ export class OffsetPolyline
if (equalv3(sp, ep, 1e-3))
continue;
let iPts = curveNow.IntersectWith(curveNext, IntersectOption.ExtendBoth);
let tPts = iPts.filter(p => curveNow.PtOnCurve3(p) && curveNext.PtOnCurve3(p));
let iPtsP = curveNow.IntersectWith2(curveNext, IntersectOption.ExtendBoth, 1e-6);
let iPts = iPtsP.map(p => p.pt);
let tPts = iPtsP.filter(p => curveNow.ParamOnCurve(p.thisParam) && curveNext.ParamOnCurve(p.argParam)).map(p => p.pt);
let code = EntityEncode2(curveNow, curveNext);
@ -285,7 +288,7 @@ export class OffsetPolyline
tp = iPts[0];
else
{
if (iPts.length > 0 && curveNow.GetParamAtPoint(iPts[0]) > 1)
if (iPts.length > 0 && iPtsP[0].thisParam > 1)
{
let refP = this._Vertexs[curveResNext.index];
let distSq = iPts[0].distanceToSquared(refP);
@ -304,8 +307,21 @@ export class OffsetPolyline
else
{
let refP = this._Vertexs[curveResNext.index];
//在局部偏移中,当偏移距离不一致时,我们总是倾向于直接连接
if (this._IsTopoOffset && tPts.length === 0 && curveResNow.dist !== curveResNext.dist)
{
if (iPts.length)
tPts = iPts;
else
{
curveResNow.paddingCurve = [new Line(sp, ep)];//补直线
continue;
}
}
if (tPts.length > 0) //ipts = 1 or ipts = 2
tp = SelectNearP(iPts, refP);
tp = SelectNearP(tPts, refP);
else //补圆弧 或者尝试连接
{
if (iPts.length > 0 && !this._ToolPath && this.IsSharpCorner(curveResNow, curveResNext, refP))//非加工刀路 并且尖角化时
@ -369,7 +385,7 @@ export class OffsetPolyline
if (curveResNext.ep)
curveNext.EndPoint = oldp2;
if (this._IsTopoOffset || onPre && onNext)
if (onPre && onNext)
tp = p;
else
curveResNow.paddingCurve = [this.CreateArc(refP, sp, ep)];//补圆弧
@ -377,7 +393,8 @@ export class OffsetPolyline
else
curveResNow.paddingCurve = [this.CreateArc(refP, sp, ep)];//补圆弧
this._TrimCircleContours.push(this._Circles[curveResNext.index]);
let circle = this._Circles[curveResNext.index];
if (circle) this._TrimCircleContours.push(circle);//因为局部偏移可能未提供圆
}
}
if (tp)
@ -394,9 +411,10 @@ export class OffsetPolyline
let padCirs: Circle[] = [];
for (let s = FixIndex(curveResNow.index + 1, this._Circles); ; s = FixIndex(s + 1, this._Circles))
{
let c = this._Circles[s];
this._TrimCircleContours.push(c);
padCirs.push(c);
let circle = this._Circles[s];
if (!circle) continue;//因为局部偏移可能未提供圆
this._TrimCircleContours.push(circle);
padCirs.push(circle);
if (s === curveResNext.index)
break;
}

@ -22,7 +22,7 @@ import { RegionParse } from "../../Geometry/RegionParse";
import { FixIndex } from "../../Nest/Common/Util";
import { FaceDirection } from "../../UI/Store/BoardInterface";
import { BoolOpeartionType, isTargetCurInOrOnSourceCur } from "../BoolOperateUtils";
import { GetSealedBoardContour } from "../CalcEdgeSealing";
import { GetBoardContour } from "../CalcEdgeSealing";
import { GetCurveToInDir, GetOffsetCurves, OptimizeToolPath } from "./OptimizeToolPath";
/**
@ -502,8 +502,7 @@ export class FeedingToolPath extends Singleton
export function GetModelingFromCustomDrill(br: Board)
{
let normal = br.Normal;
let sealedData = GetSealedBoardContour(br);
let outline = sealedData.brContour;
let outline = GetBoardContour(br);
let modeling: (IModeling & { originEn: ExtrudeHole; })[] = [];
let sideModeling: (IModeling & { originEn: ExtrudeHole; })[] = [];

Loading…
Cancel
Save