|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
import { Vector2, Vector3 } from "three";
|
|
|
|
|
import { Vec2DTo3D, Vec3DTo2D, isTargetCurInSourceCur, rotateLine } from "../Common/CurveUtils";
|
|
|
|
|
import { Vec2DTo3D, Vec3DTo2D, getCirAngleByChordAndTangent, rotateLine } from "../Common/CurveUtils";
|
|
|
|
|
import { sliceDeep } from "../Common/Utils";
|
|
|
|
|
import { Arc } from "../DatabaseServices/Arc";
|
|
|
|
|
import { Circle } from "../DatabaseServices/Circle";
|
|
|
|
@ -7,8 +7,8 @@ import { Curve } from "../DatabaseServices/Curve";
|
|
|
|
|
import { Line } from "../DatabaseServices/Line";
|
|
|
|
|
import { Polyline, PolylineProps } from "../DatabaseServices/Polyline";
|
|
|
|
|
import { MoveMatrix, angleTo, equal, equaln } from "../Geometry/GeUtils";
|
|
|
|
|
import { isTargetCurInSourceCur } from "./BoolOperateUtils";
|
|
|
|
|
import { IntersectOption } from "./IntersectWith";
|
|
|
|
|
import { app } from "../ApplicationServices/Application";
|
|
|
|
|
interface offestRes
|
|
|
|
|
{
|
|
|
|
|
index: number,
|
|
|
|
@ -22,6 +22,8 @@ interface offestRes
|
|
|
|
|
* 存在问题为仍有一些无效线段无法正确删除
|
|
|
|
|
* 移除自交线段时部分情况不正确
|
|
|
|
|
* 存在多封闭区域的时候无法都识别出来
|
|
|
|
|
* 分离自交曲线 存在问题
|
|
|
|
|
* //TODO:尝试先通过自交点把偏移后曲线数组打散,然后进行曲线切割(用源线段点和线段到源线段的最近点)
|
|
|
|
|
* @export
|
|
|
|
|
* @class PolyOffestUtil
|
|
|
|
|
*/
|
|
|
|
@ -40,16 +42,16 @@ export class PolyOffestUtil
|
|
|
|
|
let plList: offestRes[] = this.offestCurve(this.m_Polyline.Explode());
|
|
|
|
|
//连接全部连接点
|
|
|
|
|
let newPlList: Array<Polyline> = this.trimAndJointOffestPolyline(plList);
|
|
|
|
|
// //分离出自交的线
|
|
|
|
|
// // //分离出自交的线
|
|
|
|
|
let outputPls = this.removeSelfIntersect(newPlList);
|
|
|
|
|
this.linkPLine(newPlList);
|
|
|
|
|
|
|
|
|
|
this.cuttingPolyLine(newPlList);
|
|
|
|
|
//如果曲线闭合并且向内偏移,曲线应都在闭合曲线内
|
|
|
|
|
if (this.m_Polyline.IsClose)
|
|
|
|
|
{
|
|
|
|
|
//FIXME:没想好确定偏移方向
|
|
|
|
|
}
|
|
|
|
|
// //如果曲线闭合并且向内偏移,曲线应都在闭合曲线内
|
|
|
|
|
// if (this.m_Polyline.IsClose)
|
|
|
|
|
// {
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
outputPls.push(...this.arrangePlineList(newPlList));
|
|
|
|
|
return outputPls;
|
|
|
|
|
}
|
|
|
|
@ -158,21 +160,18 @@ export class PolyOffestUtil
|
|
|
|
|
//如果没有交点,则用圆弧连接
|
|
|
|
|
if (interPts.length === 0)
|
|
|
|
|
{
|
|
|
|
|
let srcLine = offResList[i + 1] ? offResList[i + 1] : offResList[0];
|
|
|
|
|
let centerPt = this.m_Polyline.GetCurveAtIndex(srcLine.index).StartPoint;
|
|
|
|
|
// 圆心到前面线end点向量
|
|
|
|
|
let startLine = frontLine.EndPoint.clone().sub(centerPt);
|
|
|
|
|
// 圆心到后面线start点向量
|
|
|
|
|
let endLine = laterLine.StartPoint.clone().sub(centerPt);
|
|
|
|
|
let circleAngle;
|
|
|
|
|
//偏移线段对应的源线段,取其起始点作为圆心
|
|
|
|
|
let srcOffestRes = offResList[i + 1] ? offResList[i + 1] : offResList[0];
|
|
|
|
|
let centerPt = this.m_Polyline.GetCurveAtIndex(srcOffestRes.index).StartPoint;
|
|
|
|
|
|
|
|
|
|
// 圆心到前面线end点距离
|
|
|
|
|
let startDist = frontLine.EndPoint.distanceToSquared(centerPt);
|
|
|
|
|
// 圆心到后面线start点距离
|
|
|
|
|
let endDist = laterLine.StartPoint.distanceToSquared(centerPt);
|
|
|
|
|
//补圆弧的起始交点
|
|
|
|
|
let intPt = Vec2DTo3D(frontLine.LineData[1].pt);
|
|
|
|
|
// 如果起始向量和终止向量相等,则都为半径
|
|
|
|
|
if (equaln(startLine.lengthSq(), endLine.lengthSq()))
|
|
|
|
|
{
|
|
|
|
|
circleAngle = angleTo(startLine, endLine);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
if (!equaln(startDist, endDist))
|
|
|
|
|
{
|
|
|
|
|
// 以centerPt为圆心,偏移距离为为半径画圆
|
|
|
|
|
let tmpCir = new Circle(centerPt, Math.abs(this.m_OffestDist));
|
|
|
|
@ -183,12 +182,11 @@ export class PolyOffestUtil
|
|
|
|
|
//选取交点,如果有多个选离前面线start点近的
|
|
|
|
|
intPt = this.selectPlInterPt(pts, frontLine.StartPoint);
|
|
|
|
|
let insLine = intPt.clone().sub(centerPt);
|
|
|
|
|
circleAngle = angleTo(insLine, endLine);
|
|
|
|
|
this.adjustFrontLine(startV, frontLine.LineData[1], intPt);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 与补线圆无交点,放弃补圆弧
|
|
|
|
|
//TODO: 与补线圆无交点,放弃补圆弧,若按CAD可以补
|
|
|
|
|
newPlList.push(new Polyline([
|
|
|
|
|
startV, this.clonePlData(frontLine.LineData[1])
|
|
|
|
|
]))
|
|
|
|
@ -196,6 +194,11 @@ export class PolyOffestUtil
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//改用根据laterline切线和弦判断圆心角及方向
|
|
|
|
|
let chord = intPt.clone().sub(laterLine.StartPoint);
|
|
|
|
|
let tangent = laterLine.GetFistDeriv(0).negate().normalize();
|
|
|
|
|
let circleAngle = -getCirAngleByChordAndTangent(chord, tangent);
|
|
|
|
|
|
|
|
|
|
let tmpPlData = {
|
|
|
|
|
pt: Vec3DTo2D(intPt),
|
|
|
|
|
bul: Math.tan(circleAngle / 4)
|
|
|
|
@ -343,6 +346,23 @@ export class PolyOffestUtil
|
|
|
|
|
}
|
|
|
|
|
return plLists;
|
|
|
|
|
}
|
|
|
|
|
//根据自交点分离多段线
|
|
|
|
|
private spliteOffestPolyline(plList: Polyline[])
|
|
|
|
|
{
|
|
|
|
|
for (let i = 0; i < plList.length - 1; i++)
|
|
|
|
|
{
|
|
|
|
|
//前一根线
|
|
|
|
|
let frontLine = plList[i];
|
|
|
|
|
let insertPt = new Vector3();
|
|
|
|
|
for (let j = i + 1; j < plList.length; j++)
|
|
|
|
|
{
|
|
|
|
|
// 后一根线
|
|
|
|
|
let laterLine = plList[j];
|
|
|
|
|
let intPts = frontLine.IntersectWith(laterLine, IntersectOption.OnBothOperands);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//处理分离出的多段线,把相交的部分提取出来
|
|
|
|
|
private handleRemoveLine(plList: Polyline[])
|
|
|
|
|
{
|
|
|
|
@ -1060,449 +1080,3 @@ export class PolyOffestUtil2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//合并前2个偏移算法,未完善
|
|
|
|
|
export class PolyOffestUtil3
|
|
|
|
|
{
|
|
|
|
|
private m_Polyline: Polyline;
|
|
|
|
|
private m_OffestDist: number
|
|
|
|
|
constructor(pl: Polyline, offest: number)
|
|
|
|
|
{
|
|
|
|
|
this.m_Polyline = pl;
|
|
|
|
|
this.m_OffestDist = offest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//偏移
|
|
|
|
|
GetOffsetCurves(): Curve[]
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//预处理源线段自交线段
|
|
|
|
|
let handledPl = this.handleIntersectToSelf();
|
|
|
|
|
let pls = handledPl.Explode();
|
|
|
|
|
let plList1: offestRes[] = this.offestCurve(pls, this.m_OffestDist);
|
|
|
|
|
let plList2: offestRes[] = this.offestCurve(pls, -this.m_OffestDist);
|
|
|
|
|
|
|
|
|
|
let l = plList1.map(l => l.pl).filter(l => l !== undefined);
|
|
|
|
|
let newPls = this.trimAndJointOffestPolyline(plList1, handledPl);
|
|
|
|
|
let refPls = this.trimAndJointOffestPolyline(plList2, handledPl);
|
|
|
|
|
newPls = this.arrangePlineList(newPls);
|
|
|
|
|
// console.log('newPls: ', newPls);
|
|
|
|
|
refPls = this.arrangePlineList(refPls);
|
|
|
|
|
return [...newPls, ...refPls]
|
|
|
|
|
// console.log('refPls: ', refPls);
|
|
|
|
|
// let outputPls: Polyline[] = [];
|
|
|
|
|
// for (let newPl of newPls)
|
|
|
|
|
// {
|
|
|
|
|
// for (let refPl of refPls)
|
|
|
|
|
// {
|
|
|
|
|
// outputPls.push(...this.clipOffestPolyline(handledPl, newPl, refPl));
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// return outputPls;
|
|
|
|
|
// return newPls;
|
|
|
|
|
}
|
|
|
|
|
//偏移曲线
|
|
|
|
|
private offestCurve(pls: Curve[], dist: number): offestRes[]
|
|
|
|
|
{
|
|
|
|
|
let plList: offestRes[] = [];
|
|
|
|
|
pls.forEach((pl, index) =>
|
|
|
|
|
{
|
|
|
|
|
let l1 = pl.GetOffsetCurves(dist)[0];
|
|
|
|
|
let offPl: Polyline;
|
|
|
|
|
if (l1 instanceof Line)
|
|
|
|
|
{
|
|
|
|
|
offPl = new Polyline([{
|
|
|
|
|
pt: Vec3DTo2D(l1.StartPoint),
|
|
|
|
|
bul: 0
|
|
|
|
|
}, {
|
|
|
|
|
pt: Vec3DTo2D(l1.EndPoint),
|
|
|
|
|
bul: 0
|
|
|
|
|
}]);
|
|
|
|
|
}
|
|
|
|
|
else if (l1 instanceof Arc)
|
|
|
|
|
{
|
|
|
|
|
offPl = new Polyline([{
|
|
|
|
|
pt: Vec3DTo2D(l1.StartPoint),
|
|
|
|
|
bul: Math.tan(l1.AllAngle / 4) * (l1.IsClockWise ? -1 : 1)
|
|
|
|
|
}, {
|
|
|
|
|
pt: Vec3DTo2D(l1.EndPoint),
|
|
|
|
|
bul: 0
|
|
|
|
|
}]);
|
|
|
|
|
}
|
|
|
|
|
offPl && plList.push({
|
|
|
|
|
index, pl: offPl
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
return plList;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 预处理源线段相邻线段自交
|
|
|
|
|
* @private
|
|
|
|
|
* @memberof PolyOffestUtil2
|
|
|
|
|
*/
|
|
|
|
|
private handleIntersectToSelf()
|
|
|
|
|
{
|
|
|
|
|
let newPlProps = sliceDeep(this.m_Polyline.LineData) as PolylineProps[];
|
|
|
|
|
//处理相邻线段自交
|
|
|
|
|
for (let i = 0; i < this.m_Polyline.EndParam - 1; i++)
|
|
|
|
|
{
|
|
|
|
|
let frontLine = this.m_Polyline.GetCurveAtIndex(i);
|
|
|
|
|
let laterLine = this.m_Polyline.GetCurveAtIndex(i + 1);
|
|
|
|
|
let interPts = frontLine.IntersectWith(laterLine, IntersectOption.OnBothOperands).filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return !equal(p, frontLine.EndPoint);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let newProp: PolylineProps;
|
|
|
|
|
if (interPts.length > 0)
|
|
|
|
|
{
|
|
|
|
|
newProp = {
|
|
|
|
|
pt: Vec3DTo2D(interPts[0]),
|
|
|
|
|
bul: 0
|
|
|
|
|
}
|
|
|
|
|
if (frontLine instanceof Arc)
|
|
|
|
|
{
|
|
|
|
|
let startV = this.m_Polyline.LineData[i];
|
|
|
|
|
this.adjustFrontLine(startV, newPlProps[i + 1], interPts[0]);
|
|
|
|
|
frontLine.StartPoint = interPts[0];
|
|
|
|
|
newProp.bul = Math.tan(frontLine.AllAngle * 0.25) * Math.sign(startV.bul);
|
|
|
|
|
}
|
|
|
|
|
newPlProps.splice(i + 1, 0, newProp);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return new Polyline(newPlProps)
|
|
|
|
|
}
|
|
|
|
|
private getSelfInterPts(pl: Polyline)
|
|
|
|
|
{
|
|
|
|
|
let interPts: Vector3[] = [];
|
|
|
|
|
for (let i = 0; i < pl.EndParam; i++)
|
|
|
|
|
{
|
|
|
|
|
let frontLine = pl.GetCurveAtIndex(i);
|
|
|
|
|
for (let j = i + 1; j < pl.EndParam; j++)
|
|
|
|
|
{
|
|
|
|
|
let laterLine = pl.GetCurveAtIndex(j);
|
|
|
|
|
let tmpPts = frontLine.IntersectWith(laterLine, IntersectOption.OnBothOperands).filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return !equal(p, frontLine.EndPoint);
|
|
|
|
|
});
|
|
|
|
|
interPts.push(...tmpPts);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return interPts;
|
|
|
|
|
}
|
|
|
|
|
// 修剪连接相邻曲线
|
|
|
|
|
private trimAndJointOffestPolyline(offsetRes: offestRes[], originLine: Polyline)
|
|
|
|
|
{
|
|
|
|
|
if (offsetRes.length <= 1)
|
|
|
|
|
{
|
|
|
|
|
return offsetRes[0] ? [offsetRes[0].pl] : [];
|
|
|
|
|
}
|
|
|
|
|
let newPlList: Array<Polyline> = [];
|
|
|
|
|
|
|
|
|
|
let startV = this.clonePlData(offsetRes[0].pl.LineData[0]);
|
|
|
|
|
let isStillClose = this.m_Polyline.IsClose;
|
|
|
|
|
for (let i = 0; i < offsetRes.length; i++)
|
|
|
|
|
{
|
|
|
|
|
//前面线
|
|
|
|
|
let frontLine = offsetRes[i].pl;
|
|
|
|
|
|
|
|
|
|
let laterLine = i === offsetRes.length - 1 ? undefined : offsetRes[i + 1].pl;
|
|
|
|
|
|
|
|
|
|
if (i === offsetRes.length - 1)
|
|
|
|
|
{
|
|
|
|
|
if (this.m_Polyline.IsClose && isStillClose)
|
|
|
|
|
laterLine = newPlList[0];
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
if (!laterLine) return []; //终点data
|
|
|
|
|
let endV = i === offsetRes.length - 1 ? laterLine.LineData[0] : this.clonePlData(laterLine.LineData[0]);
|
|
|
|
|
//交点
|
|
|
|
|
let interPt = Vec2DTo3D(endV.pt);
|
|
|
|
|
// 如果两线结合点不相等
|
|
|
|
|
if (!equal(frontLine.EndPoint, laterLine.StartPoint))
|
|
|
|
|
{
|
|
|
|
|
// 多段线交点数组
|
|
|
|
|
let interPts = frontLine.IntersectWith(laterLine, IntersectOption.ExtendBoth);
|
|
|
|
|
|
|
|
|
|
//如果没有交点,则用圆弧连接
|
|
|
|
|
if (interPts.length === 0)
|
|
|
|
|
{
|
|
|
|
|
let centerPt = this.m_Polyline.GetCurveAtIndex(offsetRes[i + 1].index).StartPoint;
|
|
|
|
|
// 圆心到前面线end点向量
|
|
|
|
|
let startLine = frontLine.EndPoint.clone().sub(centerPt);
|
|
|
|
|
// 圆心到后面线start点向量
|
|
|
|
|
let endLine = laterLine.StartPoint.clone().sub(centerPt);
|
|
|
|
|
let circleAngle;
|
|
|
|
|
//补圆弧的起始交点
|
|
|
|
|
let intPt = Vec2DTo3D(frontLine.LineData[1].pt);
|
|
|
|
|
// 如果起始向量和终止向量相等,则都为半径
|
|
|
|
|
if (equaln(startLine.lengthSq(), endLine.lengthSq()))
|
|
|
|
|
{
|
|
|
|
|
circleAngle = angleTo(startLine, endLine);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 以centerPt为圆心,偏移距离为为半径画圆
|
|
|
|
|
let tmpCir = new Circle(centerPt, Math.abs(this.m_OffestDist));
|
|
|
|
|
//只会和前面线相交,因为圆心选取是根据后面线startPoint偏移距离处的点,只会与后面线相切,允许前面线延伸
|
|
|
|
|
let pts = tmpCir.IntersectWith(frontLine, IntersectOption.OnBothOperands);
|
|
|
|
|
if (pts.length > 0)
|
|
|
|
|
{
|
|
|
|
|
//选取交点,如果有多个选离前面线start点近的
|
|
|
|
|
intPt = this.selectFitInterPt(pts, frontLine.StartPoint);
|
|
|
|
|
let insLine = intPt.clone().sub(centerPt);
|
|
|
|
|
circleAngle = angleTo(insLine, endLine);
|
|
|
|
|
this.adjustFrontLine(startV, frontLine.LineData[1], intPt);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 与补线圆无交点,放弃补圆弧
|
|
|
|
|
newPlList.push(new Polyline([
|
|
|
|
|
startV, this.clonePlData(frontLine.LineData[1])
|
|
|
|
|
]))
|
|
|
|
|
startV = this.clonePlData(laterLine.LineData[0]);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let tmpPlData = {
|
|
|
|
|
pt: Vec3DTo2D(intPt),
|
|
|
|
|
bul: Math.tan(circleAngle / 4)
|
|
|
|
|
};
|
|
|
|
|
newPlList.push(new Polyline([
|
|
|
|
|
startV, tmpPlData
|
|
|
|
|
]))
|
|
|
|
|
startV = this.clonePlData(tmpPlData);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let pts = frontLine.IntersectWith(laterLine, IntersectOption.OnBothOperands);
|
|
|
|
|
interPt = this.selectFitInterPt(pts.length ? pts : interPts, laterLine.StartPoint)
|
|
|
|
|
this.adjustFrontLine(startV, frontLine.LineData[1], interPt);
|
|
|
|
|
if (i === offsetRes.length - 1)
|
|
|
|
|
{
|
|
|
|
|
let tmpPar = laterLine.GetParamAtPoint(interPt);
|
|
|
|
|
tmpPar > 1 && newPlList.splice(0, 1);
|
|
|
|
|
}
|
|
|
|
|
this.adjustLaterLine(endV, laterLine.LineData[1], interPt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let pl = new Polyline([startV, endV]);
|
|
|
|
|
let tmpPar = frontLine.GetParamAtPoint(Vec2DTo3D(startV.pt));
|
|
|
|
|
let tmpCur = frontLine.GetCurveAtIndex(0) as Line | Arc;
|
|
|
|
|
if (tmpPar > 0) tmpCur.EndPoint = Vec2DTo3D(startV.pt);
|
|
|
|
|
else tmpCur.StartPoint = Vec2DTo3D(startV.pt);
|
|
|
|
|
let par = tmpCur.GetParamAtPoint(interPt);
|
|
|
|
|
// newSlope = pl.GetFistDeriv(0);
|
|
|
|
|
startV = this.clonePlData(endV);
|
|
|
|
|
|
|
|
|
|
if (equal(pl.StartPoint, pl.EndPoint) || par < 0)
|
|
|
|
|
{
|
|
|
|
|
if (isStillClose)
|
|
|
|
|
{
|
|
|
|
|
isStillClose = !(offsetRes[i].index === 0 || offsetRes[i].index === originLine.EndParam);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
newPlList.push(pl);
|
|
|
|
|
}
|
|
|
|
|
if (!this.m_Polyline.IsClose)
|
|
|
|
|
{
|
|
|
|
|
let frontLine = offsetRes[offsetRes.length - 1].pl;
|
|
|
|
|
let endV = this.clonePlData(frontLine.LineData[1]);
|
|
|
|
|
let tmpPar = frontLine.GetParamAtPoint(Vec2DTo3D(startV.pt));
|
|
|
|
|
if (tmpPar < 1)
|
|
|
|
|
{
|
|
|
|
|
if (offsetRes.length >= 3)
|
|
|
|
|
{
|
|
|
|
|
let laterLine = newPlList[0];
|
|
|
|
|
let pts = frontLine.IntersectWith(laterLine, IntersectOption.OnBothOperands);
|
|
|
|
|
if (pts.length === 1)
|
|
|
|
|
{
|
|
|
|
|
this.adjustFrontLine(startV, endV, pts[0]);
|
|
|
|
|
endV.pt = Vec3DTo2D(pts[0]);
|
|
|
|
|
if (newPlList.length > 0)
|
|
|
|
|
{
|
|
|
|
|
this.adjustLaterLine(laterLine.LineData[0], laterLine.LineData[1], pts[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let pl = new Polyline([startV, endV]);
|
|
|
|
|
let par = frontLine.GetParamAtPoint(Vec2DTo3D(endV.pt));
|
|
|
|
|
par > 0 && newPlList.push(pl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return newPlList;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 裁剪 偏移后的未修剪线段
|
|
|
|
|
* 在2测偏移线段之间的线段,剔除掉
|
|
|
|
|
* @private
|
|
|
|
|
* @param {Polyline} origin
|
|
|
|
|
* @param {Polyline} newPl
|
|
|
|
|
* @param {Polyline} refPl
|
|
|
|
|
* @memberof PolyOffestUtil2
|
|
|
|
|
*/
|
|
|
|
|
private clipOffestPolyline(origin: Polyline, newPl: Polyline, refPl: Polyline)
|
|
|
|
|
{
|
|
|
|
|
//结果曲线与参考曲线的交点
|
|
|
|
|
let interPts = newPl.IntersectWith(refPl, IntersectOption.OnBothOperands);
|
|
|
|
|
// 结果曲线自交点
|
|
|
|
|
let selfInterPts = this.getSelfInterPts(newPl);
|
|
|
|
|
//临时多段线数组
|
|
|
|
|
let tmpPlList: Polyline[] = [];
|
|
|
|
|
if (!interPts.length && !selfInterPts.length)
|
|
|
|
|
{
|
|
|
|
|
tmpPlList.push(newPl);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//根据交点顺序分割偏移线段
|
|
|
|
|
let params = [...interPts].map(pt => newPl.GetParamAtPoint(pt));
|
|
|
|
|
[...selfInterPts].forEach(pt =>
|
|
|
|
|
{
|
|
|
|
|
params.push(...this.getParsByPt(newPl, pt));
|
|
|
|
|
})
|
|
|
|
|
//分割的线段
|
|
|
|
|
let tmpPls = newPl.GetSplitCurves(params);
|
|
|
|
|
tmpPls.forEach(pl =>
|
|
|
|
|
{
|
|
|
|
|
let tmpInterPts = pl.IntersectWith(origin, IntersectOption.OnBothOperands);
|
|
|
|
|
if (tmpInterPts.length === 0)
|
|
|
|
|
tmpPlList.push(pl)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let tmpPt = tmpInterPts.filter(pt => equal(pt, origin.StartPoint) || equal(pt, origin.EndPoint));
|
|
|
|
|
if (tmpPt.length > 0)
|
|
|
|
|
{
|
|
|
|
|
//切割该分段
|
|
|
|
|
let tmpCir = new Circle(tmpPt[0], Math.abs(this.m_OffestDist));
|
|
|
|
|
tmpPlList.push(...this.cuttingPolyline(pl, tmpPt[0]))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
//用小于偏移距离最近点对结果多段线数组进行切割
|
|
|
|
|
// this.cuttingOffestPlByClosePt(origin, tmpPlList);
|
|
|
|
|
return tmpPlList.filter(pl => !equaln(pl.Length, 0));
|
|
|
|
|
}
|
|
|
|
|
private getParsByPt(pl: Polyline, pt: Vector3)
|
|
|
|
|
{
|
|
|
|
|
let pars: number[] = [];
|
|
|
|
|
let cus = pl.Explode();
|
|
|
|
|
for (let i = 0; i < cus.length; i++)
|
|
|
|
|
{
|
|
|
|
|
let cu = cus[i];
|
|
|
|
|
let param = cu.GetParamAtPoint(pt);
|
|
|
|
|
if (cu.ParamOnCurve(param))
|
|
|
|
|
pars.push(i + param); //返回点在曲线内部的参数
|
|
|
|
|
}
|
|
|
|
|
return pars;
|
|
|
|
|
}
|
|
|
|
|
private cuttingOffestPlByClosePt(origin: Polyline, pllist: Polyline[])
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < pllist.length; i++)
|
|
|
|
|
{
|
|
|
|
|
let pl = pllist[i];
|
|
|
|
|
for (let j = 0; j < pl.EndParam + 1; j++)
|
|
|
|
|
{
|
|
|
|
|
let pt = pl.GetPointAtParam(j);
|
|
|
|
|
let center = origin.GetClosestPointTo(pt, false);
|
|
|
|
|
let dist = center.distanceToSquared(pt);
|
|
|
|
|
if (dist - Math.pow(this.m_OffestDist, 2) < -1e-4)
|
|
|
|
|
{
|
|
|
|
|
let cutedPls = this.cuttingPolyline(pl, center).filter(l => !equaln(l.Length, 0, 0.1));
|
|
|
|
|
pllist.splice(i, 1, ...cutedPls);
|
|
|
|
|
i -= (cutedPls.length ? cutedPls.length : 1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
private cuttingPolyline(pl: Polyline, centerPt: Vector3)
|
|
|
|
|
{
|
|
|
|
|
let rad = Math.abs(this.m_OffestDist);
|
|
|
|
|
let circle = new Circle(centerPt, rad);
|
|
|
|
|
let pts = pl.IntersectWith(circle, IntersectOption.OnBothOperands);
|
|
|
|
|
let params = pts.map(p => pl.GetParamAtPoint(p));
|
|
|
|
|
let cutedPls = pl.GetSplitCurves(params).filter(l => !isTargetCurInSourceCur(circle, l));
|
|
|
|
|
return cutedPls;
|
|
|
|
|
}
|
|
|
|
|
// 根据交点调整前面线段的凸度
|
|
|
|
|
private adjustFrontLine(startV: PolylineProps, endV: PolylineProps, insertPt: Vector3)
|
|
|
|
|
{
|
|
|
|
|
if (startV.bul !== 0)
|
|
|
|
|
{
|
|
|
|
|
let arc = new Arc().ParseFromBul(startV.pt, endV.pt, startV.bul);
|
|
|
|
|
arc.EndPoint = insertPt;
|
|
|
|
|
//前面线的凸度调整
|
|
|
|
|
startV.bul = Math.tan(arc.AllAngle / 4) * Math.sign(startV.bul);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 根据交点调整后面线段的凸度和起始点
|
|
|
|
|
private adjustLaterLine(startV: PolylineProps, endV: PolylineProps, interPt: Vector3)
|
|
|
|
|
{
|
|
|
|
|
let bul = 0;
|
|
|
|
|
if (startV.bul !== 0)
|
|
|
|
|
{
|
|
|
|
|
let arc = new Arc().ParseFromBul(startV.pt, endV.pt, startV.bul);
|
|
|
|
|
arc.StartPoint = interPt;
|
|
|
|
|
bul = Math.tan(arc.AllAngle * 0.25) * Math.sign(startV.bul);
|
|
|
|
|
}
|
|
|
|
|
// 调整后面线起始点和凸度
|
|
|
|
|
startV.pt = Vec3DTo2D(interPt);
|
|
|
|
|
startV.bul = bul;
|
|
|
|
|
}
|
|
|
|
|
// 选择合适的交点
|
|
|
|
|
private selectFitInterPt(pts: Vector3[], refPt: Vector3)
|
|
|
|
|
{
|
|
|
|
|
let pt = pts[0];
|
|
|
|
|
if (pts.length > 1)
|
|
|
|
|
{
|
|
|
|
|
let dist1 = refPt.distanceToSquared(pts[0]);
|
|
|
|
|
let dist2 = refPt.distanceToSquared(pts[1]);
|
|
|
|
|
pt = dist1 <= dist2 ? pts[0] : pts[1];
|
|
|
|
|
}
|
|
|
|
|
return pt;
|
|
|
|
|
}
|
|
|
|
|
private clonePlData(pl: PolylineProps)
|
|
|
|
|
{
|
|
|
|
|
return {
|
|
|
|
|
pt: pl.pt,
|
|
|
|
|
bul: pl.bul
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//整理多段线数组,把相连的组合成多段线,返回多段线数组
|
|
|
|
|
private arrangePlineList(pls: Array<Polyline>)
|
|
|
|
|
{
|
|
|
|
|
if (pls.length === 0) return [];
|
|
|
|
|
let plDataList: PolylineProps[] = [];
|
|
|
|
|
let plList: Polyline[] = [];
|
|
|
|
|
plDataList.push(pls[0].LineData[0]);
|
|
|
|
|
for (let i = 0; i < pls.length - 1; i++)
|
|
|
|
|
{
|
|
|
|
|
let frontLine = pls[i];
|
|
|
|
|
let laterLine = pls[i + 1];
|
|
|
|
|
if (equal(frontLine.EndPoint, laterLine.StartPoint))
|
|
|
|
|
{
|
|
|
|
|
plDataList.push(laterLine.LineData[0]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
plDataList.push(frontLine.LineData[1]);
|
|
|
|
|
plList.push(new Polyline(plDataList));
|
|
|
|
|
plDataList = [laterLine.LineData[0]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
plDataList.push(pls[pls.length - 1].LineData[1]);
|
|
|
|
|
plList.push(new Polyline(plDataList));
|
|
|
|
|
|
|
|
|
|
return plList;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|