|
|
@ -1,6 +1,6 @@
|
|
|
|
import { Vector3 } from "three";
|
|
|
|
import { Vector3 } from "three";
|
|
|
|
import { arrayLast } from "../Common/ArrayExt";
|
|
|
|
import { arrayLast } from "../Common/ArrayExt";
|
|
|
|
import { Vec3DTo2D, curveLinkGroup, getCirAngleByChordAndTangent, Vec2DTo3D } from "../Common/CurveUtils";
|
|
|
|
import { Vec2DTo3D, Vec3DTo2D, curveLinkGroup, getCirAngleByChordAndTangent } from "../Common/CurveUtils";
|
|
|
|
import { FixIndex } from "../Common/Utils";
|
|
|
|
import { FixIndex } from "../Common/Utils";
|
|
|
|
import { Arc } from "../DatabaseServices/Arc";
|
|
|
|
import { Arc } from "../DatabaseServices/Arc";
|
|
|
|
import { Circle } from "../DatabaseServices/Circle";
|
|
|
|
import { Circle } from "../DatabaseServices/Circle";
|
|
|
@ -8,10 +8,10 @@ import { Contour } from "../DatabaseServices/Contour";
|
|
|
|
import { Curve } from "../DatabaseServices/Curve";
|
|
|
|
import { Curve } from "../DatabaseServices/Curve";
|
|
|
|
import { Line } from "../DatabaseServices/Line";
|
|
|
|
import { Line } from "../DatabaseServices/Line";
|
|
|
|
import { Polyline } from '../DatabaseServices/Polyline';
|
|
|
|
import { Polyline } from '../DatabaseServices/Polyline';
|
|
|
|
import { equal, equaln, midPoint } from "../Geometry/GeUtils";
|
|
|
|
import { equal, equaln } from "../Geometry/GeUtils";
|
|
|
|
import { isTargetCurInSourceCur, isTargetCurOutOrOnSourceCur } from "./BoolOperateUtils";
|
|
|
|
import { isTargetCurInSourceCur, isTargetCurOutOrOnSourceCur } from "./BoolOperateUtils";
|
|
|
|
import { IntersectOption } from "./IntersectWith";
|
|
|
|
import { IntersectOption } from "./IntersectWith";
|
|
|
|
import { app } from "../ApplicationServices/Application";
|
|
|
|
import { LinkSelf } from "./LinkSelft";
|
|
|
|
interface offestRes
|
|
|
|
interface offestRes
|
|
|
|
{
|
|
|
|
{
|
|
|
|
index: number,
|
|
|
|
index: number,
|
|
|
@ -22,13 +22,13 @@ export class PolyOffestUtil
|
|
|
|
{
|
|
|
|
{
|
|
|
|
private m_Polyline: Polyline;
|
|
|
|
private m_Polyline: Polyline;
|
|
|
|
private m_OffestDist: number;
|
|
|
|
private m_OffestDist: number;
|
|
|
|
private m_OffDir: number;
|
|
|
|
// private m_OffDir: number;
|
|
|
|
private IsKeepAllCurves = false; //为true时 保留全部,不优化裁剪
|
|
|
|
private IsKeepAllCurves = false; //为true时 保留全部,不优化裁剪
|
|
|
|
constructor(pl: Polyline, offest: number)
|
|
|
|
constructor(pl: Polyline, offest: number)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
this.m_Polyline = pl;
|
|
|
|
this.m_Polyline = pl;
|
|
|
|
this.m_OffestDist = offest;
|
|
|
|
this.m_OffestDist = offest;
|
|
|
|
this.m_OffDir = Math.sign(this.m_OffestDist) * Math.sign(this.m_Polyline.Area2);
|
|
|
|
// this.m_OffDir = Math.sign(this.m_OffestDist) * Math.sign(this.m_Polyline.Area2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//偏移
|
|
|
|
//偏移
|
|
|
|
GetOffsetCurves(): Curve[]
|
|
|
|
GetOffsetCurves(): Curve[]
|
|
|
@ -61,42 +61,86 @@ export class PolyOffestUtil
|
|
|
|
|
|
|
|
|
|
|
|
let newPls = this.trimAndJointOffestPolyline(offres1, this.m_Polyline);
|
|
|
|
let newPls = this.trimAndJointOffestPolyline(offres1, this.m_Polyline);
|
|
|
|
let cus = this.trimByContours(newPls, contours);
|
|
|
|
let cus = this.trimByContours(newPls, contours);
|
|
|
|
let rets = this.linkSelfingCurves(cus);
|
|
|
|
let rets = this.linkSelfingCurves2(cus);
|
|
|
|
if (!this.IsKeepAllCurves)
|
|
|
|
if (!this.IsKeepAllCurves)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 先尝试把线段相连成封闭区域
|
|
|
|
// rets = this.optimizeCus(rets);
|
|
|
|
rets = rets.map(cu => this.closePolyline(cu)).filter((l, i) =>
|
|
|
|
}
|
|
|
|
|
|
|
|
return rets;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 过滤优化曲线数组
|
|
|
|
|
|
|
|
* 先将曲线闭合,在排除和第一段有交点且不闭合的曲线
|
|
|
|
|
|
|
|
* @param {Polyline[]} rets
|
|
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
|
|
* @memberof PolyOffestUtil
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
optimizeCus(rets: Polyline[])
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (i === 0) return true;
|
|
|
|
if (rets.length <= 1) return rets;
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
|
|
if (this.m_Polyline.IsClose)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return l.IsClose || l.IntersectWith(rets[0], IntersectOption.OnBothOperands).length === 0;
|
|
|
|
return rets.filter(l => l.IsClose)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (this.m_Polyline.IsClose)
|
|
|
|
|
|
|
|
rets = rets.filter(l => l.IsClose);
|
|
|
|
|
|
|
|
else
|
|
|
|
else
|
|
|
|
rets = rets.sort((l1, l2) => l2.Length - l1.Length)
|
|
|
|
|
|
|
|
.filter((l, i) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (i == 0) return true;
|
|
|
|
let baseline = rets[0];
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
|
|
if (!baseline.IsClose)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let longestCu = baseline;
|
|
|
|
|
|
|
|
for (let i = 1; i < rets.length; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (l.IsClose)
|
|
|
|
if (rets[i].Length > longestCu.Length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let pts = l.PtsBuls.pts;
|
|
|
|
longestCu = rets[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (baseline !== longestCu)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let isVail = this.compareCus(longestCu, baseline);
|
|
|
|
|
|
|
|
if (!isVail)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rets.shift();
|
|
|
|
|
|
|
|
baseline = rets[0];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rets = rets.filter((l, i) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (i === 0) return true;
|
|
|
|
|
|
|
|
else return (l.IsClose || l.IntersectWith(baseline, IntersectOption.OnBothOperands).length === 0) && this.compareCus(baseline, l);
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
for (let i = 1; i < rets.length - 1; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let isvail1 = this.compareCus(rets[i], rets[i + 1]);
|
|
|
|
|
|
|
|
let isvail2 = this.compareCus(rets[i + 1], rets[i]);
|
|
|
|
|
|
|
|
if (!isvail1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rets.splice(i + 1, 1);
|
|
|
|
|
|
|
|
i--;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!isvail2 && !rets[i].IsClose)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
rets.splice(i, 1);
|
|
|
|
|
|
|
|
i--;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return rets;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
compareCus(srcLine: Polyline, tarLine: Polyline)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pts = tarLine.PtsBuls.pts;
|
|
|
|
return pts.some(p =>
|
|
|
|
return pts.some(p =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let p1 = Vec2DTo3D(p);
|
|
|
|
let p1 = Vec2DTo3D(p);
|
|
|
|
let closePt = rets[0].GetClosestPointTo(p1, false);
|
|
|
|
let closePt = srcLine.GetClosestPointTo(p1, false);
|
|
|
|
let dist = closePt.distanceToSquared(p1);
|
|
|
|
let dist = closePt.distanceToSquared(p1);
|
|
|
|
return dist > Math.pow(this.m_OffestDist, 2);
|
|
|
|
return dist > Math.pow(this.m_OffestDist, 2);
|
|
|
|
})
|
|
|
|
})
|
|
|
|
} else return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return rets;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//偏移曲线
|
|
|
|
//偏移曲线
|
|
|
|
private offestCurve(pls: Curve[], dis: number): offestRes[]
|
|
|
|
private offestCurve(pls: Curve[], dis: number): offestRes[]
|
|
|
@ -417,6 +461,7 @@ export class PolyOffestUtil
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private isSelfingCus(cus: Curve[]): boolean
|
|
|
|
private isSelfingCus(cus: Curve[]): boolean
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (cus.length <= 1) return false;
|
|
|
|
for (let i = 0; i < cus.length; i++)
|
|
|
|
for (let i = 0; i < cus.length; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let frontLine = cus[i];
|
|
|
|
let frontLine = cus[i];
|
|
|
@ -493,6 +538,7 @@ export class PolyOffestUtil
|
|
|
|
});
|
|
|
|
});
|
|
|
|
if (pts.length)
|
|
|
|
if (pts.length)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
//TODO:判断0~j之间的曲线是否自交,不自觉直接按顺序连接起来
|
|
|
|
let parForFront = frontLine.GetParamAtPoint(pts[0]);
|
|
|
|
let parForFront = frontLine.GetParamAtPoint(pts[0]);
|
|
|
|
let parForLater = laterLine.GetParamAtPoint(pts[0]);
|
|
|
|
let parForLater = laterLine.GetParamAtPoint(pts[0]);
|
|
|
|
|
|
|
|
|
|
|
@ -544,6 +590,41 @@ export class PolyOffestUtil
|
|
|
|
retPls.push(...this.linkCurves(cus));
|
|
|
|
retPls.push(...this.linkCurves(cus));
|
|
|
|
return retPls;
|
|
|
|
return retPls;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
linkSelfingCurves2(cus: Curve[]): Polyline[]
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let retPls: Polyline[] = [];
|
|
|
|
|
|
|
|
let retsCus = new LinkSelf(cus);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
retsCus.noSealCus.forEach(cs =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pl = new Polyline();
|
|
|
|
|
|
|
|
cs.forEach(c =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pl.Join(c)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
retPls.push(pl);
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// let seals: Polyline[] = [];
|
|
|
|
|
|
|
|
retsCus.sealCus.forEach(s =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pl = new Polyline();
|
|
|
|
|
|
|
|
s.forEach(c =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pl.Join(c)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
retPls.push(pl);
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// retPls = retPls.filter((l, i) =>
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// if (i === 0) return true;
|
|
|
|
|
|
|
|
// return seals.every(l1 => l1.IntersectWith(l, IntersectOption.OnBothOperands).length === 0)
|
|
|
|
|
|
|
|
// })
|
|
|
|
|
|
|
|
// retPls.push(...seals);
|
|
|
|
|
|
|
|
return retPls;
|
|
|
|
|
|
|
|
}
|
|
|
|
closePolyline(pl: Polyline)
|
|
|
|
closePolyline(pl: Polyline)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//闭合或者只有一条线段或者2条线段都是直线的,直接返回
|
|
|
|
//闭合或者只有一条线段或者2条线段都是直线的,直接返回
|
|
|
|