|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
import { Box3, Vector3 } from "three";
|
|
|
|
|
import { arrayLast, arrayRemoveIf } from "../Common/ArrayExt";
|
|
|
|
|
import { curveLinkGroup, getCirAngleByChordAndTangent, Vec2DTo3D, Vec3DTo2D } from "../Common/CurveUtils";
|
|
|
|
|
import { curveLinkGroup, getCirAngleByChordAndTangent, Vec2DTo3D } from "../Common/CurveUtils";
|
|
|
|
|
import { FixIndex } from "../Common/Utils";
|
|
|
|
|
import { Arc } from "../DatabaseServices/Arc";
|
|
|
|
|
import { Circle } from "../DatabaseServices/Circle";
|
|
|
|
@ -9,723 +9,56 @@ import { Curve } from "../DatabaseServices/Curve";
|
|
|
|
|
import { Line } from "../DatabaseServices/Line";
|
|
|
|
|
import { Polyline } from '../DatabaseServices/Polyline';
|
|
|
|
|
import { equal, equaln } from "../Geometry/GeUtils";
|
|
|
|
|
import { IsPtsAllOutOrOnReg, isTargetCurInOrOnSourceCur, isTargetCurOutOrOnSourceCur } from "./BoolOperateUtils";
|
|
|
|
|
import { IsPtsAllOutOrOnReg } from "./BoolOperateUtils";
|
|
|
|
|
import { IntersectOption } from "./IntersectWith";
|
|
|
|
|
import { LinkSelf } from "./LinkSelft";
|
|
|
|
|
import { ptInRectOrCircle } from "../DatabaseServices/PointInPolyline";
|
|
|
|
|
interface offestRes
|
|
|
|
|
{
|
|
|
|
|
index: number,
|
|
|
|
|
curve: Curve
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//FIXME:1当轮廓自交时,会丢失自交的线段
|
|
|
|
|
//FIXME:2往内偏移到极限位置,会有多余线段
|
|
|
|
|
//FIXME:3线段共线时,有时造成线段不连续
|
|
|
|
|
export class PolyOffestUtil
|
|
|
|
|
{
|
|
|
|
|
private m_Polyline: Polyline;
|
|
|
|
|
private m_OffestDist: number;
|
|
|
|
|
// private m_OffDir: number;
|
|
|
|
|
private IsKeepAllCurves = false; //为true时 保留全部,不优化裁剪
|
|
|
|
|
constructor(pl: Polyline, offest: number)
|
|
|
|
|
{
|
|
|
|
|
this.m_Polyline = pl;
|
|
|
|
|
this.m_OffestDist = offest;
|
|
|
|
|
// this.m_OffDir = Math.sign(this.m_OffestDist) * Math.sign(this.m_Polyline.Area2);
|
|
|
|
|
}
|
|
|
|
|
//偏移
|
|
|
|
|
GetOffsetCurves(): Curve[]
|
|
|
|
|
{
|
|
|
|
|
let expCus = this.m_Polyline.Explode();
|
|
|
|
|
let offres1 = this.offestCurve(expCus, this.m_OffestDist);
|
|
|
|
|
let offres2 = this.offestCurve(expCus, -this.m_OffestDist);
|
|
|
|
|
|
|
|
|
|
let contours: Contour[] = [];
|
|
|
|
|
for (let i = 0; i < offres1.length; i++)
|
|
|
|
|
{
|
|
|
|
|
let cu1 = offres1[i].curve;
|
|
|
|
|
let cu2 = offres2[i].curve;
|
|
|
|
|
let con = this.buildContourByTwoSideOfest(cu1, cu2);
|
|
|
|
|
con && contours.push(con);
|
|
|
|
|
|
|
|
|
|
//加入每个顶点的圆
|
|
|
|
|
let originCu = this.m_Polyline.GetCurveAtIndex(i);
|
|
|
|
|
if (i === 0 && !this.m_Polyline.IsClose)
|
|
|
|
|
contours.push(Contour.CreateContour([new Circle(originCu.StartPoint, Math.abs(this.m_OffestDist))]));
|
|
|
|
|
contours.push(Contour.CreateContour([new Circle(originCu.EndPoint, Math.abs(this.m_OffestDist))]));
|
|
|
|
|
}
|
|
|
|
|
// contours.forEach(c =>
|
|
|
|
|
// {
|
|
|
|
|
// c.Outline.ColorIndex = 2;
|
|
|
|
|
// app.m_Database.ModelSpace.Append(c.Outline);
|
|
|
|
|
// })
|
|
|
|
|
// console.time("trim");
|
|
|
|
|
let newPls = this.trimAndJointOffestPolyline(offres1);
|
|
|
|
|
console.timeEnd("trim");
|
|
|
|
|
console.time("con");
|
|
|
|
|
let cus = this.trimByContours(newPls, contours);
|
|
|
|
|
// console.timeEnd("con");
|
|
|
|
|
|
|
|
|
|
// console.time("link");
|
|
|
|
|
let rets = this.linkSelfingCurves2(cus);
|
|
|
|
|
// console.timeEnd('link');
|
|
|
|
|
|
|
|
|
|
if (!this.IsKeepAllCurves)
|
|
|
|
|
{
|
|
|
|
|
// console.time('k');
|
|
|
|
|
rets = this.optimizeCus(rets);
|
|
|
|
|
// console.timeEnd('k');
|
|
|
|
|
}
|
|
|
|
|
return rets;
|
|
|
|
|
// return [];
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 过滤优化曲线数组
|
|
|
|
|
* 先将曲线闭合,在排除和第一段有交点且不闭合的曲线
|
|
|
|
|
* @param {Polyline[]} rets
|
|
|
|
|
* @returns
|
|
|
|
|
* @memberof PolyOffestUtil
|
|
|
|
|
*/
|
|
|
|
|
optimizeCus(rets: Polyline[])
|
|
|
|
|
{
|
|
|
|
|
if (this.m_Polyline.IsClose)
|
|
|
|
|
{
|
|
|
|
|
return rets.map(l => this.closePolyline(l)).filter(l => l.IsClose)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (rets.length <= 1) return rets;
|
|
|
|
|
let deleteCus: Set<Polyline> = new Set();
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < rets.length; i++)
|
|
|
|
|
{
|
|
|
|
|
let cu1 = rets[0];
|
|
|
|
|
if (cu1.IsClose) continue;
|
|
|
|
|
for (let j = i + 1; j < rets.length; j++)
|
|
|
|
|
{
|
|
|
|
|
let cu2 = rets[j];
|
|
|
|
|
if (cu2.IsClose) continue;
|
|
|
|
|
|
|
|
|
|
let [tmpCu1, tmpCu2] = cu1.Length > cu2.Length ? [cu1, cu2] : [cu2, cu1];
|
|
|
|
|
if (!this.compareCus(tmpCu1, tmpCu2))
|
|
|
|
|
{
|
|
|
|
|
deleteCus.add(tmpCu2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rets = rets.filter(cu => !deleteCus.has(cu));
|
|
|
|
|
}
|
|
|
|
|
return rets;
|
|
|
|
|
}
|
|
|
|
|
compareCus(srcLine: Polyline, tarLine: Polyline)
|
|
|
|
|
{
|
|
|
|
|
let pts = tarLine.PtsBuls.pts;
|
|
|
|
|
return pts.some(p =>
|
|
|
|
|
{
|
|
|
|
|
let p1 = Vec2DTo3D(p);
|
|
|
|
|
let closePt = srcLine.GetClosestPointTo(p1, false);
|
|
|
|
|
let dist = closePt.distanceToSquared(p1);
|
|
|
|
|
return dist > Math.pow(this.m_OffestDist, 2);
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
//偏移曲线
|
|
|
|
|
private offestCurve(pls: Curve[], dis: number): offestRes[]
|
|
|
|
|
{
|
|
|
|
|
return pls.map((cu, index) =>
|
|
|
|
|
{
|
|
|
|
|
let curve = cu.GetOffsetCurves(dis)[0];
|
|
|
|
|
return { curve, index };
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
//通过2侧偏移曲线构建封闭轮廓,由于是双向偏移,所以不可能出现2个曲线都为空的情况
|
|
|
|
|
private buildContourByTwoSideOfest(pl1: Curve, pl2: Curve)
|
|
|
|
|
{
|
|
|
|
|
if (pl1 && pl2)
|
|
|
|
|
{
|
|
|
|
|
// let dir = Math.sign(this.m_OffestDist);
|
|
|
|
|
// let arc1 = new Arc().ParseFromBul(pl1.StartPoint, pl2.StartPoint, -dir);
|
|
|
|
|
// let arc2 = new Arc().ParseFromBul(pl1.EndPoint, pl2.EndPoint, dir);
|
|
|
|
|
// return Contour.CreateContour([pl1.Clone() as Curve, pl2.Clone() as Curve, arc1, arc2]);
|
|
|
|
|
return Contour.CreateContour([pl1.Clone() as Curve, pl2.Clone() as Curve, new Line(pl1.StartPoint, pl2.StartPoint), new Line(pl1.EndPoint, pl2.EndPoint)]);
|
|
|
|
|
}
|
|
|
|
|
else if (pl1 || pl2)
|
|
|
|
|
{
|
|
|
|
|
let arc = pl1 ? pl1.Clone() as Arc : pl2.Clone() as Arc;
|
|
|
|
|
let l1 = new Line(arc.Center, arc.StartPoint);
|
|
|
|
|
let l2 = new Line(arc.Center, arc.EndPoint);
|
|
|
|
|
return Contour.CreateContour([arc, l1, l2]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
console.error("错误,2曲线为未定义");
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 修剪连接相邻曲线
|
|
|
|
|
private trimAndJointOffestPolyline(offResList: offestRes[])
|
|
|
|
|
{
|
|
|
|
|
offResList = offResList.filter(r => r.curve && !equaln(r.curve.Length, 0, 1e-6));
|
|
|
|
|
if (offResList.length <= 1)
|
|
|
|
|
return offResList.map(r => r.curve);
|
|
|
|
|
|
|
|
|
|
let retPlList: Array<Curve> = [];
|
|
|
|
|
|
|
|
|
|
let nextPt: Vector3 = offResList[0].curve.StartPoint;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < offResList.length; i++)
|
|
|
|
|
{
|
|
|
|
|
//前面线
|
|
|
|
|
let frontLine = offResList[i].curve;
|
|
|
|
|
|
|
|
|
|
//后面线
|
|
|
|
|
let laterLine: Curve;
|
|
|
|
|
//如果是闭合的,继续循环,否则直接添加到新数组列表
|
|
|
|
|
if (i === offResList.length - 1)
|
|
|
|
|
{
|
|
|
|
|
if (retPlList.length === 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (this.m_Polyline.IsClose)
|
|
|
|
|
laterLine = retPlList[0];
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, frontLine.EndPoint, retPlList);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
laterLine = offResList[i + 1].curve;
|
|
|
|
|
|
|
|
|
|
//默认交点
|
|
|
|
|
let interPt = frontLine.EndPoint;
|
|
|
|
|
// 如果两线结合点不相等,调整交点位置
|
|
|
|
|
if (!equal(frontLine.EndPoint, laterLine.StartPoint))
|
|
|
|
|
{
|
|
|
|
|
// 源线段对应索引
|
|
|
|
|
let startIndex = offResList[i].index;
|
|
|
|
|
let endIndex = offResList[FixIndex(i + 1, offResList)].index;
|
|
|
|
|
let isFillArc = endIndex - startIndex !== 1;
|
|
|
|
|
if (endIndex === 0)
|
|
|
|
|
{
|
|
|
|
|
endIndex = this.m_Polyline.EndParam - 1;
|
|
|
|
|
isFillArc = this.m_Polyline.EndParam - 1 !== startIndex;
|
|
|
|
|
endIndex = isFillArc ? endIndex : 0;
|
|
|
|
|
}
|
|
|
|
|
// 多段线交点数组
|
|
|
|
|
let interPts = frontLine.IntersectWith(laterLine, IntersectOption.ExtendBoth);
|
|
|
|
|
|
|
|
|
|
//如果有圆弧丢失或者没有交点,则用圆弧连接
|
|
|
|
|
if (isFillArc || interPts.length === 0)
|
|
|
|
|
{
|
|
|
|
|
//偏移线段对应的源线段,取其起始点作为圆心
|
|
|
|
|
this.fillArc(startIndex, endIndex, nextPt, frontLine, laterLine, retPlList);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let pts = interPts.filter(p => frontLine.PtOnCurve(p) && laterLine.PtOnCurve(p));
|
|
|
|
|
interPt = this.selectFitInterPt(pts.length ? pts : interPts, frontLine.EndPoint);
|
|
|
|
|
if (pts.length > 0)
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, interPt, retPlList);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.checkCuAndAppendList(frontLine, laterLine, interPt, nextPt, retPlList, endIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, frontLine.EndPoint, retPlList);
|
|
|
|
|
|
|
|
|
|
if (i === offResList.length - 1)//曲线闭合时,修改第一条线的起点
|
|
|
|
|
{
|
|
|
|
|
laterLine.StartPoint = nextPt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return retPlList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//将线段拷贝并修改,加入到结果数组里面.
|
|
|
|
|
appendNewPllist(frontLine: Curve, nextPt: Vector3, interPt: Vector3, newPlList: Curve[], laterLine?: Curve)
|
|
|
|
|
{
|
|
|
|
|
let newCu = frontLine.Clone() as Curve;
|
|
|
|
|
|
|
|
|
|
newCu.StartPoint = nextPt;
|
|
|
|
|
newCu.EndPoint = interPt;
|
|
|
|
|
nextPt.copy(interPt);
|
|
|
|
|
newPlList.push(newCu);
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 检测偏移线段是否有效并加入结果曲线数组
|
|
|
|
|
*
|
|
|
|
|
* @private
|
|
|
|
|
* @param {Curve} frontLine
|
|
|
|
|
* @param {Curve} laterLine
|
|
|
|
|
* @param {Vector3} intPt
|
|
|
|
|
* @param {Vector3} nextPt
|
|
|
|
|
* @param {Curve[]} newPlList
|
|
|
|
|
* @param {number} endIndex
|
|
|
|
|
* @memberof PolyOffestUtil
|
|
|
|
|
*/
|
|
|
|
|
private checkCuAndAppendList(frontLine: Curve, laterLine: Curve, intPt: Vector3, nextPt: Vector3, newPlList: Curve[], endIndex: number)
|
|
|
|
|
{
|
|
|
|
|
let par1 = frontLine.GetParamAtPoint(intPt);
|
|
|
|
|
|
|
|
|
|
if (frontLine instanceof Arc && laterLine instanceof Arc)
|
|
|
|
|
{
|
|
|
|
|
let isOnFline = frontLine.PtOnCurve(intPt);
|
|
|
|
|
let isOnLline = laterLine.PtOnCurve(intPt);
|
|
|
|
|
if ((!isOnFline && !isOnLline))
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, intPt, newPlList);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.fillArc(endIndex - 1, endIndex, nextPt, frontLine, laterLine, newPlList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let par2 = laterLine.GetParamAtPoint(intPt);
|
|
|
|
|
if (par1 > 1)
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, intPt, newPlList);
|
|
|
|
|
}
|
|
|
|
|
else if (par1 < 0 && par2 < 0 && frontLine instanceof Arc)
|
|
|
|
|
{
|
|
|
|
|
this.fillArc(endIndex - 1, endIndex, nextPt, frontLine, laterLine, newPlList);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, frontLine.EndPoint, newPlList);
|
|
|
|
|
newPlList.push(new Line(frontLine.EndPoint, laterLine.StartPoint));
|
|
|
|
|
nextPt.copy(laterLine.StartPoint);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 补圆弧
|
|
|
|
|
*
|
|
|
|
|
* @param {number} startIndex 源线段索引
|
|
|
|
|
* @param {number} endIndex 源线段索引
|
|
|
|
|
* @param {Vector3} nextPt
|
|
|
|
|
* @param {Curve} frontLine
|
|
|
|
|
* @param {Curve} laterLine
|
|
|
|
|
* @param {Curve[]} retPlList
|
|
|
|
|
* @returns
|
|
|
|
|
* @memberof PolyOffestUtil3
|
|
|
|
|
*/
|
|
|
|
|
fillArc(startIndex: number, endIndex: number, nextPt: Vector3, frontLine: Curve, laterLine: Curve, retPlList: Curve[])
|
|
|
|
|
{
|
|
|
|
|
let centerPt = this.m_Polyline.GetPointAtParam(endIndex);
|
|
|
|
|
//圆心到前面线end点距离
|
|
|
|
|
let startDist = frontLine.EndPoint.distanceToSquared(centerPt);
|
|
|
|
|
//圆心到后面线start点距离
|
|
|
|
|
let endDist = laterLine.StartPoint.distanceToSquared(centerPt);
|
|
|
|
|
//补圆弧的起始交点
|
|
|
|
|
let intPt = frontLine.EndPoint;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
const buildArcJoinList = (cir1: Circle, intPt: Vector3) =>
|
|
|
|
|
{
|
|
|
|
|
let pars = [nextPt, intPt].map(p => cir1.GetParamAtPoint(p));
|
|
|
|
|
let splitCus = cir1.GetSplitCurves(pars);
|
|
|
|
|
if (splitCus.length === 2)
|
|
|
|
|
{
|
|
|
|
|
let cu = splitCus[0].Length < splitCus[1].Length ? splitCus[0] : splitCus[1];
|
|
|
|
|
let lastCu = arrayLast(retPlList);
|
|
|
|
|
//如果不是首尾相连,就反转后在存入数组
|
|
|
|
|
if (!equal(cu.StartPoint, lastCu.EndPoint))
|
|
|
|
|
cu.Reverse();
|
|
|
|
|
|
|
|
|
|
nextPt.copy(intPt);
|
|
|
|
|
if (equaln(cu.Length, 0, 1e-6))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
retPlList.push(cu);
|
|
|
|
|
} else nextPt.copy(intPt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!equaln(startDist, endDist))
|
|
|
|
|
{
|
|
|
|
|
let rad = Math.abs(this.m_OffestDist);
|
|
|
|
|
// 以centerPt为圆心,偏移距离为为半径画圆
|
|
|
|
|
let tmpCir = new Circle(centerPt, rad);
|
|
|
|
|
//只会和前面线相交,因为圆心选取是根据后面线startPoint偏移距离处的点,只会与后面线相切,允许前面线延伸
|
|
|
|
|
let pts = tmpCir.IntersectWith(frontLine, IntersectOption.OnBothOperands);
|
|
|
|
|
if (pts.length > 0)
|
|
|
|
|
{
|
|
|
|
|
//选取交点,如果有多个选离前面线start点近的
|
|
|
|
|
intPt = this.selectFitInterPt(pts, frontLine.StartPoint);
|
|
|
|
|
frontLine.EndPoint = intPt;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let cirs: Circle[] = [];
|
|
|
|
|
for (let i = startIndex + 1; i <= endIndex; i++)
|
|
|
|
|
{
|
|
|
|
|
let center = this.m_Polyline.GetPointAtParam(i);
|
|
|
|
|
cirs.push(new Circle(center, rad));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let pts = frontLine.IntersectWith(cirs[0], IntersectOption.OnBothOperands);
|
|
|
|
|
let inPt = this.selectFitInterPt(pts, frontLine.EndPoint);
|
|
|
|
|
if (!inPt)
|
|
|
|
|
{
|
|
|
|
|
console.log(this.m_OffestDist);
|
|
|
|
|
}
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, inPt, retPlList);
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < cirs.length - 1; i++)
|
|
|
|
|
{
|
|
|
|
|
let cir1 = cirs[i];
|
|
|
|
|
let cir2 = cirs[i + 1];
|
|
|
|
|
let pts = cir1.IntersectWith(cir2, IntersectOption.OnBothOperands);
|
|
|
|
|
let intPt = this.selectFitInterPt(pts, nextPt);
|
|
|
|
|
buildArcJoinList(cir1, intPt);
|
|
|
|
|
|
|
|
|
|
if (i === cirs.length - 2)
|
|
|
|
|
{
|
|
|
|
|
buildArcJoinList(cir2, laterLine.StartPoint);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 补完圆弧直接退出函数
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//改用根据laterline切线和弦判断圆心角及方向
|
|
|
|
|
let chord = intPt.clone().sub(laterLine.StartPoint);
|
|
|
|
|
let tangent = laterLine.GetFistDeriv(0).negate().normalize();
|
|
|
|
|
let circleAngle = -getCirAngleByChordAndTangent(chord, tangent);
|
|
|
|
|
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, intPt, retPlList, laterLine);
|
|
|
|
|
|
|
|
|
|
nextPt.copy(laterLine.StartPoint);
|
|
|
|
|
|
|
|
|
|
let arc = new Arc().ParseFromBul(intPt, laterLine.StartPoint, Math.tan(circleAngle / 4));
|
|
|
|
|
retPlList.push(arc);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通过构建的轮廓对偏移曲线进行裁剪
|
|
|
|
|
private trimByContours(needCutCus: Curve[], cons: Contour[]): Curve[]
|
|
|
|
|
{
|
|
|
|
|
cons.forEach(c =>
|
|
|
|
|
{
|
|
|
|
|
let tmpCus: Curve[] = [];
|
|
|
|
|
let outline = c.Outline;
|
|
|
|
|
for (let l of needCutCus)
|
|
|
|
|
{
|
|
|
|
|
// let posSrcForTar = TargetCurPosForSourceCur(outline, l as Arc | Line);
|
|
|
|
|
// if (posSrcForTar.onSrc || posSrcForTar.outSrc)
|
|
|
|
|
// {
|
|
|
|
|
// tmpCus.push(l);
|
|
|
|
|
// }
|
|
|
|
|
// else if (posSrcForTar.throughSrc)
|
|
|
|
|
// {
|
|
|
|
|
// let par = posSrcForTar.pts.map(p => l.GetParamAtPoint(p));
|
|
|
|
|
// let cus = l.GetSplitCurves(par);
|
|
|
|
|
// if (cus.length === 0)
|
|
|
|
|
// {
|
|
|
|
|
// tmpCus.push(l);
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// tmpCus.push(...cus.filter(cu => !equaln(cu.Length, 0, 1e-6) && isTargetCurOutOrOnSourceCur(outline, cu)));
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// l instanceof Arc && tmpCus.push(l);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// 在上面或者在外面
|
|
|
|
|
if (isTargetCurOutOrOnSourceCur(outline, l))
|
|
|
|
|
{
|
|
|
|
|
tmpCus.push(l);
|
|
|
|
|
}
|
|
|
|
|
else if (!isTargetCurInOrOnSourceCur(outline, l))
|
|
|
|
|
{
|
|
|
|
|
let pts = l.IntersectWith(outline, IntersectOption.OnBothOperands);
|
|
|
|
|
if (pts.length > 0)
|
|
|
|
|
{
|
|
|
|
|
let par = pts.map(p => l.GetParamAtPoint(p));
|
|
|
|
|
let cus = l.GetSplitCurves(par);
|
|
|
|
|
|
|
|
|
|
if (cus.length > 0)
|
|
|
|
|
tmpCus.push(...cus.filter(cu => !equaln(cu.Length, 0, 1e-6) && !isTargetCurInOrOnSourceCur(outline, cu)));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tmpCus.push(l);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// l instanceof Arc && tmpCus.push(l);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
needCutCus = tmpCus;
|
|
|
|
|
})
|
|
|
|
|
return needCutCus;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 判断曲线是否自交
|
|
|
|
|
*
|
|
|
|
|
* @private
|
|
|
|
|
* @param {Curve[]} cus
|
|
|
|
|
* @returns
|
|
|
|
|
* @memberof PolyOffestUtil3
|
|
|
|
|
*/
|
|
|
|
|
private isSelfingCus(cus: Curve[]): boolean
|
|
|
|
|
{
|
|
|
|
|
if (cus.length <= 1) return false;
|
|
|
|
|
for (let i = 0; i < cus.length; i++)
|
|
|
|
|
{
|
|
|
|
|
let frontLine = cus[i];
|
|
|
|
|
for (let j = cus.length - 1; j > i; j--)
|
|
|
|
|
{
|
|
|
|
|
let laterLine = cus[j];
|
|
|
|
|
let pts = frontLine.IntersectWith(laterLine, IntersectOption.OnBothOperands);
|
|
|
|
|
pts = pts.filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return !(equal(p, frontLine.StartPoint) && equal(p, laterLine.EndPoint) || (equal(frontLine.EndPoint, p) && equal(laterLine.StartPoint, p)))
|
|
|
|
|
});
|
|
|
|
|
if (pts.length) return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//连接最终曲线
|
|
|
|
|
private linkCurves(cus: Curve[]): Polyline[]
|
|
|
|
|
{
|
|
|
|
|
let groups = curveLinkGroup(cus);
|
|
|
|
|
let resultPls: Polyline[] = [];
|
|
|
|
|
for (let g of groups)
|
|
|
|
|
{
|
|
|
|
|
let pl = new Polyline();
|
|
|
|
|
for (let cu of g)
|
|
|
|
|
{
|
|
|
|
|
pl.Join(cu);
|
|
|
|
|
}
|
|
|
|
|
resultPls.push(pl)
|
|
|
|
|
}
|
|
|
|
|
return resultPls;
|
|
|
|
|
}
|
|
|
|
|
private linkCurves2(cus: Curve[] | Set<Curve>): Polyline
|
|
|
|
|
{
|
|
|
|
|
let pl = new Polyline();
|
|
|
|
|
for (let cu of cus)
|
|
|
|
|
{
|
|
|
|
|
pl.Join(cu);
|
|
|
|
|
}
|
|
|
|
|
return pl;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
*连接自交曲线数组
|
|
|
|
|
*
|
|
|
|
|
* @param {Curve[]} cus
|
|
|
|
|
* @returns
|
|
|
|
|
* @memberof PolyOffestUtil3
|
|
|
|
|
*/
|
|
|
|
|
linkSelfingCurves(cus: Curve[]): Polyline[]
|
|
|
|
|
{
|
|
|
|
|
let retPls: Polyline[] = [];
|
|
|
|
|
let isSelfing = this.isSelfingCus(cus);
|
|
|
|
|
while (cus.length && isSelfing)
|
|
|
|
|
{
|
|
|
|
|
let pl = new Polyline();
|
|
|
|
|
let frontLine = cus.shift();
|
|
|
|
|
|
|
|
|
|
let end = 0;
|
|
|
|
|
|
|
|
|
|
for (let j = cus.length - 1; j >= end; j--)
|
|
|
|
|
{
|
|
|
|
|
let laterLine = cus[j];
|
|
|
|
|
let pts = frontLine.IntersectWith(laterLine, IntersectOption.OnBothOperands);
|
|
|
|
|
if (pts.length === 2)
|
|
|
|
|
{
|
|
|
|
|
pts = pts.filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return !(equal(frontLine.EndPoint, p) && equal(laterLine.StartPoint, p))
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
pts = pts.filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return !(equal(frontLine.StartPoint, p) && equal(laterLine.EndPoint, p))
|
|
|
|
|
});
|
|
|
|
|
if (pts.length)
|
|
|
|
|
{
|
|
|
|
|
//TODO:判断0~j之间的曲线是否自交,不自觉直接按顺序连接起来
|
|
|
|
|
let parForFront = frontLine.GetParamAtPoint(pts[0]);
|
|
|
|
|
let parForLater = laterLine.GetParamAtPoint(pts[0]);
|
|
|
|
|
|
|
|
|
|
if (equaln(parForLater, 1))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (equaln(parForFront, 0, 1e-6))
|
|
|
|
|
{
|
|
|
|
|
//理论应该把该段移除出来
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else if (equaln(parForFront, 1, 1e-6))
|
|
|
|
|
{
|
|
|
|
|
pl.Join(frontLine);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let spliteCusForFront = frontLine.GetSplitCurves(parForFront);
|
|
|
|
|
pl.Join(spliteCusForFront[0]);
|
|
|
|
|
cus.unshift(spliteCusForFront[1]);
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
if (equaln(parForLater, 0, 1e-6))
|
|
|
|
|
frontLine = cus.splice(j, 1)[0];
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let splitCus = laterLine.GetSplitCurves(parForLater);
|
|
|
|
|
cus[j].EndPoint = pts[0];
|
|
|
|
|
frontLine = splitCus[1];
|
|
|
|
|
}
|
|
|
|
|
end = j;
|
|
|
|
|
j = cus.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//搜索到尽头,先直接join,先不判断
|
|
|
|
|
if (end >= j)
|
|
|
|
|
{
|
|
|
|
|
pl.Join(frontLine);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retPls.push(pl);
|
|
|
|
|
isSelfing = this.isSelfingCus(cus);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
retPls.push(...this.linkCurves(cus));
|
|
|
|
|
return retPls;
|
|
|
|
|
}
|
|
|
|
|
//
|
|
|
|
|
linkSelfingCurves2(cus: Curve[]): Polyline[]
|
|
|
|
|
{
|
|
|
|
|
let retPls: Polyline[] = [];
|
|
|
|
|
let retsCus = new LinkSelf(cus);
|
|
|
|
|
let noSealCus = retsCus.noSealCus.map(cs =>
|
|
|
|
|
{
|
|
|
|
|
return this.linkCurves2(cs);
|
|
|
|
|
})
|
|
|
|
|
let sealCus = retsCus.sealCus.map(s =>
|
|
|
|
|
{
|
|
|
|
|
return this.linkCurves2(s);
|
|
|
|
|
})
|
|
|
|
|
// let firstLine = noSealCus[0];
|
|
|
|
|
// noSealCus.sort((a, b) => b.Length - a.Length);
|
|
|
|
|
// if (firstLine !== noSealCus[0])
|
|
|
|
|
// {
|
|
|
|
|
// retPls.push(noSealCus[0]);
|
|
|
|
|
// }
|
|
|
|
|
// firstLine && retPls.push(firstLine);
|
|
|
|
|
retPls.push(...noSealCus);
|
|
|
|
|
retPls.push(...sealCus);
|
|
|
|
|
return retPls;
|
|
|
|
|
}
|
|
|
|
|
closePolyline(pl: Polyline)
|
|
|
|
|
{
|
|
|
|
|
//闭合或者只有一条线段或者2条线段都是直线的,直接返回
|
|
|
|
|
if (pl.IsClose || pl.EndParam < 2 || ((pl.EndParam === 2 && pl.GetBuilgeAt(0) == 0 && pl.GetBuilgeAt(1) == 0)))
|
|
|
|
|
return pl;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < pl.EndParam; i++)
|
|
|
|
|
{
|
|
|
|
|
let frontCu = pl.GetCurveAtIndex(i);
|
|
|
|
|
for (let j = pl.EndParam - 1; j > i; j--)
|
|
|
|
|
{
|
|
|
|
|
let lastCu = pl.GetCurveAtIndex(j);
|
|
|
|
|
let pts = frontCu.IntersectWith(lastCu, IntersectOption.OnBothOperands);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pts = pts.filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return !(equal(p, frontCu.EndPoint) && equal(p, lastCu.StartPoint)) && !(equal(p, frontCu.StartPoint) && equal(p, lastCu.EndPoint))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (pts.length == 1)
|
|
|
|
|
{
|
|
|
|
|
let polyProps = pl.LineData.slice(i, j + 2);
|
|
|
|
|
polyProps[0].pt = Vec3DTo2D(pts[0]);
|
|
|
|
|
if (frontCu instanceof Arc)
|
|
|
|
|
{
|
|
|
|
|
frontCu.StartPoint = pts[0];
|
|
|
|
|
polyProps[0].bul = Math.tan(frontCu.AllAngle / 4) * Math.sign(polyProps[0].bul);
|
|
|
|
|
}
|
|
|
|
|
arrayLast(polyProps).pt = Vec3DTo2D(pts[0]);
|
|
|
|
|
return new Polyline(polyProps);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (pts.length > 1)
|
|
|
|
|
{
|
|
|
|
|
console.warn("未知情况");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return pl;
|
|
|
|
|
}
|
|
|
|
|
// 选择合适的交点
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
export class PolyOffestUtil1
|
|
|
|
|
{
|
|
|
|
|
private m_Polyline: Polyline;
|
|
|
|
|
private m_OffestDist: number;
|
|
|
|
|
constructor(pl: Polyline, offest: number)
|
|
|
|
|
{
|
|
|
|
|
this.m_Polyline = pl;
|
|
|
|
|
this.m_OffestDist = offest;
|
|
|
|
|
}
|
|
|
|
|
//偏移
|
|
|
|
|
GetOffsetCurves(): Curve[]
|
|
|
|
|
{
|
|
|
|
|
let expCus = this.m_Polyline.Explode();
|
|
|
|
|
let offres1 = this.offestCurve(expCus, this.m_OffestDist);
|
|
|
|
|
|
|
|
|
|
let contours: Contour[] = [];
|
|
|
|
|
let rad = Math.abs(this.m_OffestDist)
|
|
|
|
|
let rad = Math.abs(this.m_OffestDist);
|
|
|
|
|
this.m_Polyline.PtsBuls.pts.forEach(p =>
|
|
|
|
|
{
|
|
|
|
|
let cir = new Circle(Vec2DTo3D(p).applyMatrix4(this.m_Polyline.OCS), rad);
|
|
|
|
|
contours.push(Contour.CreateContour([cir]))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
console.time("join")
|
|
|
|
|
// console.time("join")
|
|
|
|
|
let cus = this.trimAndJointOffestPolyline(offres1, contours);
|
|
|
|
|
console.timeEnd("join")
|
|
|
|
|
// console.timeEnd("join")
|
|
|
|
|
// testContours(contours);
|
|
|
|
|
|
|
|
|
|
console.time("trim")
|
|
|
|
|
// console.time("trim")
|
|
|
|
|
cus = this.trimByContours(cus, contours).filter(c =>
|
|
|
|
|
{
|
|
|
|
|
if (c.IntersectWith(this.m_Polyline, IntersectOption.OnBothOperands).length !== 0) return false;
|
|
|
|
|
let rad2 = Math.pow(this.m_OffestDist, 2);
|
|
|
|
|
let dist1 = this.m_Polyline.GetClosestPointTo(c.StartPoint, false).distanceToSquared(c.StartPoint);
|
|
|
|
|
if (dist1 - rad2 < -1e-3) return false;
|
|
|
|
|
let dist2 = this.m_Polyline.GetClosestPointTo(c.EndPoint, false).distanceToSquared(c.EndPoint);
|
|
|
|
|
let rad2 = Math.pow(this.m_OffestDist, 2);
|
|
|
|
|
return (dist1 - rad2 >= -1e-3 || dist2 - rad2 >= -1e-3);
|
|
|
|
|
return dist2 - rad2 >= -1e-3;
|
|
|
|
|
});
|
|
|
|
|
console.timeEnd("trim")
|
|
|
|
|
|
|
|
|
|
// console.timeEnd("trim")
|
|
|
|
|
return this.linkCurves(cus);
|
|
|
|
|
}
|
|
|
|
|
//偏移曲线
|
|
|
|
@ -767,7 +100,7 @@ export class PolyOffestUtil1
|
|
|
|
|
|
|
|
|
|
let rets: Array<Curve> = [];
|
|
|
|
|
|
|
|
|
|
let nextPt: Vector3 = offResList[0].curve.StartPoint;
|
|
|
|
|
let nextStartPt: Vector3 = offResList[0].curve.StartPoint;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < offResList.length; i++)
|
|
|
|
|
{
|
|
|
|
@ -787,7 +120,7 @@ export class PolyOffestUtil1
|
|
|
|
|
laterLine = rets[0];
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, frontLine.EndPoint, rets, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextStartPt, frontLine.EndPoint, rets, startIndex, cons);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -799,59 +132,60 @@ export class PolyOffestUtil1
|
|
|
|
|
// 如果两线结合点不相等,调整交点位置
|
|
|
|
|
if (!equal(frontLine.EndPoint, laterLine.StartPoint))
|
|
|
|
|
{
|
|
|
|
|
// 后面线对应源线段索引
|
|
|
|
|
let endIndex = offResList[FixIndex(i + 1, offResList)].index;
|
|
|
|
|
//是否补圆弧,如果中间缺线段就补,如果最后一段不是源线段最大索引,也补圆弧
|
|
|
|
|
let isFillArc = endIndex - startIndex !== 1;
|
|
|
|
|
if (endIndex === 0)
|
|
|
|
|
{
|
|
|
|
|
endIndex = this.m_Polyline.EndParam - 1;
|
|
|
|
|
isFillArc = this.m_Polyline.EndParam - 1 !== startIndex;
|
|
|
|
|
isFillArc = endIndex !== startIndex;
|
|
|
|
|
endIndex = isFillArc ? endIndex : 0;
|
|
|
|
|
}
|
|
|
|
|
// 多段线交点数组
|
|
|
|
|
let interPts = frontLine.IntersectWith(laterLine, IntersectOption.ExtendBoth);
|
|
|
|
|
let pts = interPts.filter(p => frontLine.PtOnCurve(p) && laterLine.PtOnCurve(p));
|
|
|
|
|
|
|
|
|
|
//如果有圆弧丢失或者没有交点,则用圆弧连接
|
|
|
|
|
if (isFillArc || interPts.length === 0)
|
|
|
|
|
//如果有圆弧丢失或者没有交点,则用圆弧连接,如果有交点同时存在2线段,则直接连接(与AutoCad一致)
|
|
|
|
|
if ((isFillArc && pts.length === 0) || interPts.length === 0)
|
|
|
|
|
{
|
|
|
|
|
//偏移线段对应的源线段,取其起始点作为圆心
|
|
|
|
|
this.fillArc(startIndex, endIndex, nextPt, frontLine, laterLine, rets, cons);
|
|
|
|
|
this.fillArc(startIndex, endIndex, nextStartPt, frontLine, laterLine, rets, cons);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
let pts = interPts.filter(p => frontLine.PtOnCurve(p) && laterLine.PtOnCurve(p));
|
|
|
|
|
interPt = this.selectFitInterPt1(pts.length ? pts : interPts);
|
|
|
|
|
interPt = this.selectFitInterPt(pts.length ? pts : interPts, frontLine.EndPoint);
|
|
|
|
|
if (pts.length > 0)
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, interPt, rets, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextStartPt, interPt, rets, startIndex, cons);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.checkCuAndAppendList(frontLine, laterLine, interPt, nextPt, rets, startIndex, endIndex, cons);
|
|
|
|
|
this.checkCuAndAppendList(frontLine, laterLine, interPt, nextStartPt, rets, startIndex, endIndex, cons);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, frontLine.EndPoint, rets, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextStartPt, frontLine.EndPoint, rets, startIndex, cons);
|
|
|
|
|
|
|
|
|
|
if (i === offResList.length - 1)//曲线闭合时,修改第一条线的起点
|
|
|
|
|
{
|
|
|
|
|
laterLine.StartPoint = nextPt;
|
|
|
|
|
laterLine.StartPoint = nextStartPt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return rets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//将线段拷贝并修改,加入到结果数组里面.
|
|
|
|
|
appendNewPllist(frontLine: Curve, nextPt: Vector3, interPt: Vector3, newPlList: Curve[], index: number, cons: Contour[])
|
|
|
|
|
//将线段拷贝并修改,加入到结果数组里面,构建轮廓加入轮廓数组.
|
|
|
|
|
appendNewCuAndContour(frontLine: Curve, nextStartPt: Vector3, interPt: Vector3, newCuList: Curve[], index: number, cons: Contour[])
|
|
|
|
|
{
|
|
|
|
|
//复制一条新曲线,修改起始点和终止点,并修改下一段的起始点
|
|
|
|
|
let newCu = frontLine.Clone() as Curve;
|
|
|
|
|
|
|
|
|
|
newCu.StartPoint = nextPt;
|
|
|
|
|
newCu.StartPoint = nextStartPt;
|
|
|
|
|
newCu.EndPoint = interPt;
|
|
|
|
|
nextPt.copy(interPt);
|
|
|
|
|
newPlList.push(newCu);
|
|
|
|
|
nextStartPt.copy(interPt);
|
|
|
|
|
newCuList.push(newCu);
|
|
|
|
|
let originCu = this.m_Polyline.GetCurveAtParam(index);
|
|
|
|
|
cons.push(this.buildContourByTwoSideOfest(originCu, newCu));
|
|
|
|
|
}
|
|
|
|
@ -875,9 +209,9 @@ export class PolyOffestUtil1
|
|
|
|
|
{
|
|
|
|
|
let isOnFline = frontLine.PtOnCurve(intPt);
|
|
|
|
|
let isOnLline = laterLine.PtOnCurve(intPt);
|
|
|
|
|
if ((!isOnFline && !isOnLline))
|
|
|
|
|
if (!isOnFline && !isOnLline)
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, intPt, newPlList, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextPt, intPt, newPlList, startIndex, cons);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -889,7 +223,7 @@ export class PolyOffestUtil1
|
|
|
|
|
let par2 = laterLine.GetParamAtPoint(intPt);
|
|
|
|
|
if (par1 > 1)
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, intPt, newPlList, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextPt, intPt, newPlList, startIndex, cons);
|
|
|
|
|
}
|
|
|
|
|
else if (par1 < 0 && par2 < 0 && frontLine instanceof Arc)
|
|
|
|
|
{
|
|
|
|
@ -897,7 +231,7 @@ export class PolyOffestUtil1
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, frontLine.EndPoint, newPlList, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextPt, frontLine.EndPoint, newPlList, startIndex, cons);
|
|
|
|
|
newPlList.push(new Line(frontLine.EndPoint, laterLine.StartPoint));
|
|
|
|
|
nextPt.copy(laterLine.StartPoint);
|
|
|
|
|
}
|
|
|
|
@ -957,7 +291,7 @@ export class PolyOffestUtil1
|
|
|
|
|
if (pts.length > 0)
|
|
|
|
|
{
|
|
|
|
|
//选取交点,如果有多个选离前面线start点近的
|
|
|
|
|
intPt = this.selectFitInterPt1(pts);
|
|
|
|
|
intPt = this.selectFitInterPt(pts, frontLine.StartPoint);
|
|
|
|
|
frontLine.EndPoint = intPt;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
@ -979,20 +313,20 @@ export class PolyOffestUtil1
|
|
|
|
|
cirs.shift();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let inPt = this.selectFitInterPt1(pts);
|
|
|
|
|
let inPt = this.selectFitInterPt(pts, frontLine.EndPoint);
|
|
|
|
|
|
|
|
|
|
if (!inPt)
|
|
|
|
|
{
|
|
|
|
|
console.log(this.m_OffestDist);
|
|
|
|
|
}
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, inPt, retPlList, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextPt, inPt, retPlList, startIndex, cons);
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < cirs.length - 1; i++)
|
|
|
|
|
{
|
|
|
|
|
let cir1 = cirs[i];
|
|
|
|
|
let cir2 = cirs[i + 1];
|
|
|
|
|
let pts = cir1.IntersectWith(cir2, IntersectOption.OnBothOperands);
|
|
|
|
|
let intPt = this.selectFitInterPt1(pts);
|
|
|
|
|
let intPt = this.selectFitInterPt(pts, nextPt);
|
|
|
|
|
buildArcJoinList(cir1, intPt);
|
|
|
|
|
|
|
|
|
|
if (i === cirs.length - 2)
|
|
|
|
@ -1009,7 +343,7 @@ export class PolyOffestUtil1
|
|
|
|
|
let tangent = laterLine.GetFistDeriv(0).negate().normalize();
|
|
|
|
|
let circleAngle = -getCirAngleByChordAndTangent(chord, tangent);
|
|
|
|
|
|
|
|
|
|
this.appendNewPllist(frontLine, nextPt, intPt, retPlList, startIndex, cons);
|
|
|
|
|
this.appendNewCuAndContour(frontLine, nextPt, intPt, retPlList, startIndex, cons);
|
|
|
|
|
|
|
|
|
|
nextPt.copy(laterLine.StartPoint);
|
|
|
|
|
|
|
|
|
@ -1093,26 +427,14 @@ export class PolyOffestUtil1
|
|
|
|
|
return resultPls;
|
|
|
|
|
}
|
|
|
|
|
// 选择合适的交点
|
|
|
|
|
private selectFitInterPt1(pts: Vector3[])
|
|
|
|
|
private selectFitInterPt(pts: Vector3[], refPt: Vector3)
|
|
|
|
|
{
|
|
|
|
|
let pt = pts[0];
|
|
|
|
|
if (pts.length > 1)
|
|
|
|
|
{
|
|
|
|
|
let dist1 = this.m_Polyline.GetClosestPointTo(pts[0], false).distanceToSquared(pts[0]);
|
|
|
|
|
let dist2 = this.m_Polyline.GetClosestPointTo(pts[1], false).distanceToSquared(pts[1]);
|
|
|
|
|
let rad2 = Math.pow(this.m_OffestDist, 2);
|
|
|
|
|
if (equaln(dist1, rad2))
|
|
|
|
|
{
|
|
|
|
|
pt = pts[0]
|
|
|
|
|
}
|
|
|
|
|
else if (equaln(dist2, rad2))
|
|
|
|
|
{
|
|
|
|
|
pt = pts[1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pt = dist1 <= dist2 ? pts[0] : pts[1];
|
|
|
|
|
}
|
|
|
|
|
let dist1 = refPt.distanceToSquared(pts[0]);
|
|
|
|
|
let dist2 = refPt.distanceToSquared(pts[1]);
|
|
|
|
|
pt = dist1 <= dist2 ? pts[0] : pts[1];
|
|
|
|
|
}
|
|
|
|
|
return pt;
|
|
|
|
|
}
|
|
|
|
|