|
|
@ -616,21 +616,22 @@ export class PolyOffestUtil2
|
|
|
|
//偏移
|
|
|
|
//偏移
|
|
|
|
GetOffsetCurves(): Curve[]
|
|
|
|
GetOffsetCurves(): Curve[]
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
//预处理源线段自交线段
|
|
|
|
//预处理源线段自交线段
|
|
|
|
let handledPl = this.handleIntersectToSelf();
|
|
|
|
// let handledPl = this.handleIntersectToSelf();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let plList1: offestRes[] = this.offestCurve(this.m_Polyline.Explode());
|
|
|
|
|
|
|
|
let plList2: offestRes[] = this.offestCurve(this.m_Polyline.Explode(), true);
|
|
|
|
|
|
|
|
|
|
|
|
let plList1: offestRes[] = this.offestCurve(handledPl.Explode());
|
|
|
|
let newProps = this.trimAndJointOffestPolyline(plList1, this.m_Polyline);
|
|
|
|
let plList2: offestRes[] = this.offestCurve(handledPl.Explode(), true);
|
|
|
|
let refProps = this.trimAndJointOffestPolyline(plList2, this.m_Polyline);
|
|
|
|
|
|
|
|
|
|
|
|
let newProps = this.trimAndJointOffestPolyline(plList1, handledPl);
|
|
|
|
|
|
|
|
let refProps = this.trimAndJointOffestPolyline(plList2, handledPl);
|
|
|
|
|
|
|
|
let newPl = new Polyline(newProps);
|
|
|
|
let newPl = new Polyline(newProps);
|
|
|
|
let refPl = new Polyline(refProps);
|
|
|
|
let refPl = new Polyline(refProps);
|
|
|
|
|
|
|
|
|
|
|
|
newPl.ColorIndex = 1;
|
|
|
|
newPl.ColorIndex = 1;
|
|
|
|
refPl.ColorIndex = 2;
|
|
|
|
refPl.ColorIndex = 2;
|
|
|
|
// return [...this.clipOffestPolyline(handledPl, newPl, refPl)];
|
|
|
|
// return [newPl, refPl]
|
|
|
|
return [newPl, refPl]
|
|
|
|
return [...this.clipOffestPolyline(this.m_Polyline, newPl, refPl)]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//偏移曲线
|
|
|
|
//偏移曲线
|
|
|
|
private offestCurve(pls: Curve[], isContrary: boolean = false): offestRes[]
|
|
|
|
private offestCurve(pls: Curve[], isContrary: boolean = false): offestRes[]
|
|
|
@ -710,47 +711,38 @@ export class PolyOffestUtil2
|
|
|
|
if (offestPlList.length === 0) return [];
|
|
|
|
if (offestPlList.length === 0) return [];
|
|
|
|
const addArc = (i: number, frontLine: Polyline, laterLine: Polyline, newProps: PolylineProps[]) =>
|
|
|
|
const addArc = (i: number, frontLine: Polyline, laterLine: Polyline, newProps: PolylineProps[]) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
try
|
|
|
|
let center = originLine.GetCurveAtParam(i).StartPoint;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 圆心到前面线end点距离
|
|
|
|
|
|
|
|
let startDist = frontLine.EndPoint.distanceToSquared(center);
|
|
|
|
|
|
|
|
// 圆心到后面线start点距离
|
|
|
|
|
|
|
|
let endDist = laterLine.StartPoint.distanceToSquared(center);
|
|
|
|
|
|
|
|
//补圆弧的起始交点
|
|
|
|
|
|
|
|
let intPt = Vec2DTo3D(frontLine.LineData[1].pt);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!equaln(startDist, endDist))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let center = originLine.GetCurveAtParam(i).StartPoint;
|
|
|
|
// 以centerPt为圆心,偏移距离为为半径画圆
|
|
|
|
let startLine = frontLine.EndPoint.clone().sub(center);
|
|
|
|
let tmpCir = new Circle(center, Math.abs(this.m_OffestDist));
|
|
|
|
// 圆心到后面线start点向量
|
|
|
|
//只会和前面线相交,因为圆心选取是根据后面线startPoint偏移距离处的点,只会与后面线相切,允许前面线延伸
|
|
|
|
let endLine = laterLine.StartPoint.clone().sub(center);
|
|
|
|
let pts = tmpCir.IntersectWith(frontLine, IntersectOption.OnBothOperands);
|
|
|
|
let circleAngle;
|
|
|
|
if (pts.length > 0)
|
|
|
|
//补圆弧的起始交点
|
|
|
|
|
|
|
|
let intPt = Vec2DTo3D(frontLine.LineData[1].pt);
|
|
|
|
|
|
|
|
// 如果起始向量和终止向量相等,则都为半径
|
|
|
|
|
|
|
|
if (equaln(startLine.lengthSq(), endLine.lengthSq()))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
circleAngle = angleTo(startLine, endLine);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 以center为圆心,偏移距离为为半径画圆
|
|
|
|
//选取交点,如果有多个选离前面线start点近的
|
|
|
|
let tmpCir = new Circle(center, Math.abs(this.m_OffestDist));
|
|
|
|
intPt = this.selectFitInterPt(pts, frontLine.StartPoint);
|
|
|
|
let pts = tmpCir.IntersectWith(frontLine, IntersectOption.ExtendBoth);
|
|
|
|
let insLine = intPt.clone().sub(center);
|
|
|
|
if (pts.length > 0)
|
|
|
|
this.adjustFrontLine(newProps[newProps.length - 1], frontLine.LineData[1], intPt);
|
|
|
|
{
|
|
|
|
|
|
|
|
//选取交点,如果有多个选离前面线start点近的
|
|
|
|
|
|
|
|
intPt = this.selectFitInterPt(pts, frontLine.EndPoint
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
let insLine = intPt.clone().sub(center);
|
|
|
|
|
|
|
|
circleAngle = angleTo(insLine, endLine);
|
|
|
|
|
|
|
|
this.adjustFrontLine(newProps[newProps.length - 1], frontLine.LineData[1], intPt);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
throw new Error("无法补圆弧")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newProps.push({
|
|
|
|
|
|
|
|
pt: Vec3DTo2D(intPt),
|
|
|
|
|
|
|
|
bul: Math.tan(circleAngle / 4)
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (err)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
console.log(err);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//改用根据laterline切线和弦判断圆心角及方向
|
|
|
|
|
|
|
|
let chord = intPt.clone().sub(laterLine.StartPoint);
|
|
|
|
|
|
|
|
let tangent = laterLine.GetFistDeriv(0).negate().normalize();
|
|
|
|
|
|
|
|
let circleAngle = -getCirAngleByChordAndTangent(chord, tangent);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newProps.push({
|
|
|
|
|
|
|
|
pt: Vec3DTo2D(intPt),
|
|
|
|
|
|
|
|
bul: Math.tan(circleAngle / 4)
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let newProps = [offestPlList[0].pl.LineData[0]];
|
|
|
|
let newProps = [offestPlList[0].pl.LineData[0]];
|
|
|
|
for (let i = 0; i < offestPlList.length; i++)
|
|
|
|
for (let i = 0; i < offestPlList.length; i++)
|
|
|
@ -808,7 +800,6 @@ export class PolyOffestUtil2
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (par1 > 1)
|
|
|
|
if (par1 > 1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// addArc(offestPlList[i + 1].index, frontLine, laterLine, newProps);
|
|
|
|
|
|
|
|
this.adjustLaterLine(newProp, laterLine.LineData[1], intPt);
|
|
|
|
this.adjustLaterLine(newProp, laterLine.LineData[1], intPt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -902,14 +893,12 @@ export class PolyOffestUtil2
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//切割该分段
|
|
|
|
//切割该分段
|
|
|
|
let tmpCir = new Circle(tmpPt[0], Math.abs(this.m_OffestDist));
|
|
|
|
let tmpCir = new Circle(tmpPt[0], Math.abs(this.m_OffestDist));
|
|
|
|
tmpPlList.push(...this.cuttingPolyline(pl, tmpPt[0]))
|
|
|
|
tmpPlList.push(...this.cuttingPolyline(pl, tmpPt[0]).cus)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//用小于偏移距离最近点对结果多段线数组进行切割
|
|
|
|
return this.cuttingOffestPlByClosePt(origin, tmpPlList);
|
|
|
|
this.cuttingOffestPlByClosePt(origin, tmpPlList);
|
|
|
|
|
|
|
|
return tmpPlList;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private getParsByPt(pl: Polyline, pt: Vector3)
|
|
|
|
private getParsByPt(pl: Polyline, pt: Vector3)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -926,86 +915,58 @@ export class PolyOffestUtil2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private cuttingOffestPlByClosePt(origin: Polyline, pllist: Polyline[])
|
|
|
|
private cuttingOffestPlByClosePt(origin: Polyline, pllist: Polyline[])
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (let i = 0; i <= origin.EndParam; i++)
|
|
|
|
let originPts = this.m_Polyline.PtsBuls.pts.map(p => Vec2DTo3D(p));
|
|
|
|
|
|
|
|
let closePts = this.getAllClosestPtAndInterPtOffToSrc(pllist);
|
|
|
|
|
|
|
|
let cuttedPlList: Polyline[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let pl of pllist)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let center = Vec2DTo3D(origin.LineData[i].pt);
|
|
|
|
let needCutPls = [pl]
|
|
|
|
for (let j = 0; j < pllist.length; j++)
|
|
|
|
for (let p of [...originPts, ...closePts])
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let offPl = pllist[j];
|
|
|
|
let tmpPl: Polyline[] = [];
|
|
|
|
let closePt = offPl.GetClosestPointTo(center, false);
|
|
|
|
needCutPls.forEach(pl =>
|
|
|
|
if (!closePt) continue;
|
|
|
|
|
|
|
|
let dist = closePt.distanceToSquared(center);
|
|
|
|
|
|
|
|
if (dist - this.m_OffestDist * this.m_OffestDist < -1e-8)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let cutedPls = this.cuttingPolyline(offPl, center);
|
|
|
|
let cus = this.cuttingPolyline(pl, p);
|
|
|
|
if (cutedPls.length === 2)
|
|
|
|
tmpPl.push(...cus.cus);
|
|
|
|
{
|
|
|
|
})
|
|
|
|
pllist.splice(j - 1, 0, cutedPls[0]);
|
|
|
|
needCutPls = tmpPl
|
|
|
|
j++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cuttedPlList.push(...needCutPls);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cuttedPlList
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private cuttingPolyline(pl: Polyline, centerPt: Vector3)
|
|
|
|
private cuttingPolyline(pl: Polyline, centerPt: Vector3)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let rad = Math.abs(this.m_OffestDist);
|
|
|
|
let rad = Math.abs(this.m_OffestDist);
|
|
|
|
let plList: Polyline[] = [];
|
|
|
|
|
|
|
|
let sDist = pl.StartPoint.distanceTo(centerPt);
|
|
|
|
|
|
|
|
let eDist = pl.EndPoint.distanceTo(centerPt);
|
|
|
|
|
|
|
|
let circle = new Circle(centerPt, rad);
|
|
|
|
let circle = new Circle(centerPt, rad);
|
|
|
|
let pts = pl.IntersectWith(circle, IntersectOption.OnBothOperands);
|
|
|
|
if (isTargetCurInSourceCur(circle, pl))
|
|
|
|
if (pts.length === 1)
|
|
|
|
return { cus: [], isCutted: true }
|
|
|
|
{
|
|
|
|
|
|
|
|
let par = pl.GetParamAtPoint(pts[0]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (sDist < rad)
|
|
|
|
let pars = circle.IntersectWith(pl, IntersectOption.OnBothOperands).map(p => pl.GetParamAtPoint(p));
|
|
|
|
{
|
|
|
|
let cus = pl.GetSplitCurves(pars);
|
|
|
|
pl.LineData.splice(0, ~~par);
|
|
|
|
if (cus.length === 1)
|
|
|
|
this.adjustLaterLine(pl.LineData[0], pl.LineData[1], pts[0]);
|
|
|
|
return { cus, isCutted: false }
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else if (eDist < rad)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pl.LineData.splice(~~par + 2);
|
|
|
|
|
|
|
|
this.adjustFrontLine(pl.LineData[~~par], pl.LineData[~~par + 1], pts[0]);
|
|
|
|
|
|
|
|
pl.LineData[~~par + 1].pt = Vec3DTo2D(pts[0]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
plList.push(pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (pts.length === 2)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
return {
|
|
|
|
let par1 = pl.GetParamAtPoint(pts[0]);
|
|
|
|
cus: cus.filter(l => !isTargetCurInSourceCur(circle, l)),
|
|
|
|
let par2 = pl.GetParamAtPoint(pts[1]);
|
|
|
|
isCutted: true
|
|
|
|
let pt: Vector3, pt1: Vector3;
|
|
|
|
|
|
|
|
[par1, par2, pt, pt1] = par1 < par2 ? [par1, par2, pts[0], pts[1]] : [par2, par1, pts[1], pts[0]];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//区分到pl的startPT近的和远的交点z
|
|
|
|
|
|
|
|
let frontSeg: PolylineProps[];
|
|
|
|
|
|
|
|
if (par1 === ~~par1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
frontSeg = sliceDeep(pl.LineData, 0, par1 + 1) as PolylineProps[];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
frontSeg = sliceDeep(pl.LineData, 0, ~~par1 + 2) as PolylineProps[];
|
|
|
|
|
|
|
|
this.adjustFrontLine(frontSeg[frontSeg.length - 2], frontSeg[frontSeg.length - 1], pt);
|
|
|
|
|
|
|
|
frontSeg[frontSeg.length - 1].pt = Vec3DTo2D(pt)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let laterSeg = sliceDeep(pl.LineData, ~~par2) as PolylineProps[];
|
|
|
|
|
|
|
|
pl.LineData.splice(0, ~~par2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (par2 !== ~~par2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
this.adjustLaterLine(pl.LineData[0], pl.LineData[1], pt1);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
plList.push(new Polyline(frontSeg), pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return plList;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private getAllClosestPtAndInterPtOffToSrc(pllist: Curve[])
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let closestPts: Vector3[] = [];
|
|
|
|
|
|
|
|
pllist.forEach(pl =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let closePt1 = this.m_Polyline.GetClosestPointTo(pl.StartPoint, false);
|
|
|
|
|
|
|
|
let closePt2 = this.m_Polyline.GetClosestPointTo(pl.EndPoint, false);
|
|
|
|
|
|
|
|
closePt1.distanceToSquared(pl.StartPoint) < Math.pow(this.m_OffestDist, 2) && closestPts.push(closePt1);
|
|
|
|
|
|
|
|
closePt2.distanceToSquared(pl.EndPoint) < Math.pow(this.m_OffestDist, 2) && closestPts.push(closePt2);
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
return closestPts;
|
|
|
|
|
|
|
|
}
|
|
|
|
// 根据交点调整前面线段的凸度
|
|
|
|
// 根据交点调整前面线段的凸度
|
|
|
|
private adjustFrontLine(startV: PolylineProps, endV: PolylineProps, insertPt: Vector3)
|
|
|
|
private adjustFrontLine(startV: PolylineProps, endV: PolylineProps, insertPt: Vector3)
|
|
|
|
{
|
|
|
|
{
|
|
|
|