代码清理优化,bug修复

pull/68/head
Zoe 6 years ago
parent c93b94ba6e
commit ecf4449962

@ -56,6 +56,25 @@ export function arrayRemoveIf<T>(arr: Array<T>, checkFuntion: (e: T) => boolean)
return arr;
}
export function arrayRemoveIf2<T>(arr: Array<T>, checkFuntion: (e: T) => boolean): Array<T>
{
let j = 0;
let removeArr = [];
for (let i = 0, l = arr.length; i < l; i++)
{
if (!checkFuntion(arr[i]))
{
arr[j++] = arr[i];
}
else
{
removeArr.push(arr[i]);
}
}
arr.length = j;
return removeArr;
}
export function arrayFirst<T>(arr: Array<T>): T
{

@ -103,10 +103,9 @@ export function curveLinkGroup(cus: Curve[]): Array<Array<Curve>>
let isClose = c.IsClose;
if (isClose)
groupCus.push([c]);
return !isClose;
});
if (cus.length === 0) return groupCus;
//曲线节点图
let cuMap = new CurveMap();
cus.forEach(c => cuMap.addCurveToMap(c));

@ -9,7 +9,7 @@ import { FixIndex } from '../Common/Utils';
import { equal, equaln, rotatePoint, updateGeometry } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum';
import { IntersectOption, IntersectPolylineAndCurve } from '../GraphicsSystem/IntersectWith';
import { PolyOffestUtil, PolyOffestUtil1 } from '../GraphicsSystem/OffestPolyline';
import { PolyOffestUtil } from '../GraphicsSystem/OffestPolyline';
import { Arc } from './Arc';
import { Factory } from './CADFactory';
import { CADFile } from './CADFile';
@ -746,7 +746,7 @@ export class Polyline extends Curve
//偏移
GetOffsetCurves(offsetDist: number): Array<Curve>
{
let polyOffestUtil = new PolyOffestUtil1(this, offsetDist);
let polyOffestUtil = new PolyOffestUtil(this, offsetDist);
return polyOffestUtil.GetOffsetCurves();
}
/**

@ -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;
}

Loading…
Cancel
Save