diff --git a/src/DatabaseServices/Polyline.ts b/src/DatabaseServices/Polyline.ts index 2c56fe1c0..28c51919f 100644 --- a/src/DatabaseServices/Polyline.ts +++ b/src/DatabaseServices/Polyline.ts @@ -9,7 +9,7 @@ import { FixIndex } from '../Common/Utils'; import { equal, equaln, updateGeometry } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; import { IntersectOption, IntersectPolylineAndCurve } from '../GraphicsSystem/IntersectWith'; -import { PolyOffestUtil } from '../GraphicsSystem/OffsetPolyline'; +import { PolyOffsetUtil } from '../GraphicsSystem/OffsetPolyline'; import { Arc } from './Arc'; import { Factory } from './CADFactory'; import { CADFile } from './CADFile'; @@ -752,7 +752,7 @@ export class Polyline extends Curve //偏移 GetOffsetCurves(offsetDist: number): Array { - let polyOffestUtil = new PolyOffestUtil(this, offsetDist); + let polyOffestUtil = new PolyOffsetUtil(this, offsetDist); return polyOffestUtil.GetOffsetCurves(); } /** diff --git a/src/GraphicsSystem/IntersectWith.ts b/src/GraphicsSystem/IntersectWith.ts index b52cf8c64..b3757426c 100644 --- a/src/GraphicsSystem/IntersectWith.ts +++ b/src/GraphicsSystem/IntersectWith.ts @@ -335,7 +335,6 @@ export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOptio export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: IntersectOption): Vector3[] { - //TODO:若2多段线轮廓有完全重合的线段,会有多余交点 let cus: Curve[] = pl.Explode(); let cus2: Curve[]; @@ -366,7 +365,6 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte if ((cu instanceof Polyline && cu.CloseMark) || !(isStart2 || isEnd2)) ext = ext & ~IntersectOption.ExtendArg; - //TODO:去除重复的点 let ipts = cu1.IntersectWith(cu2, ext).filter(p1 => pts.every(p2 => !equal(p1, p2))); //校验延伸 diff --git a/src/GraphicsSystem/OffsetPolyline.ts b/src/GraphicsSystem/OffsetPolyline.ts index 17632bcc6..79374d8f3 100644 --- a/src/GraphicsSystem/OffsetPolyline.ts +++ b/src/GraphicsSystem/OffsetPolyline.ts @@ -13,16 +13,16 @@ import { EBox, SortEntityByBox } from "../Geometry/SortEntityByBox"; import { IsPtsAllOutOrOnReg } from "./BoolOperateUtils"; import { IntersectOption } from "./IntersectWith"; -interface offestRes +interface offsetRes { index: number; curve: Curve; } -export class PolyOffestUtil +export class PolyOffsetUtil { private m_Polyline: Polyline; - private m_OffestDist: number; + private m_OffsetDist: number; private m_Contours: Contour[] = [];//构建的轮廓 private m_RetCurves: Curve[] = [];//第一步修剪的数组 //偏移距离平方值 @@ -34,12 +34,12 @@ export class PolyOffestUtil //源线段点数量 private m_PtCount: number; - constructor(pl: Polyline, offest: number) + constructor(pl: Polyline, offset: number) { this.m_Polyline = pl; - this.m_OffestDist = offest; - this.m_dist2 = Math.pow(offest, 2); - this.m_AbsDist = Math.abs(this.m_OffestDist); + this.m_OffsetDist = offset; + this.m_dist2 = Math.pow(offset, 2); + this.m_AbsDist = Math.abs(this.m_OffsetDist); this.m_PtCount = pl.EndParam; } GetOffsetCurves(): Curve[] @@ -61,6 +61,7 @@ export class PolyOffestUtil // 裁剪并优化的曲线 let { boxCurves, outputCus } = this.trimByContours(this.m_RetCurves); + this.m_RetCurves = this.optimizeCus(boxCurves, outputCus); this.m_RetCurves.push(...this.unNeedCutCus); @@ -76,7 +77,7 @@ export class PolyOffestUtil private CheckPointDir(pt: Vector3) { let dir = GetPointAtCurveDir(this.m_Polyline, pt) ? 1 : -1; - return dir === Math.sign(this.m_OffestDist); + return dir === Math.sign(this.m_OffsetDist); } /** @@ -90,7 +91,6 @@ export class PolyOffestUtil */ private optimizeCus(boxCurves: Map, outputCus: Curve[]) { - //过滤掉无效的线段 outputCus = outputCus.filter(c => { @@ -123,7 +123,6 @@ export class PolyOffestUtil for (let j = i + 1; j < outputCus.length; j++) { let c2 = outputCus[j]; - let c2b = boxCurves.get(c2); //过滤掉不需要计算的曲线 @@ -132,17 +131,22 @@ export class PolyOffestUtil if (c2b.min.y > c1b.max.y) continue; + let c1StartPt = c1.StartPoint; + let c1EndPt = c1.EndPoint; + let c2StartPt = c2.StartPoint; + let c2EndPt = c2.EndPoint; + //被包含的直线删掉 if (c1 instanceof Line && c2 instanceof Line) { //c1完全在c2内 - if (c2.PtOnCurve(c1.StartPoint) && c2.PtOnCurve(c1.EndPoint)) + if (c2.PtOnCurve(c1StartPt) && c2.PtOnCurve(c1EndPt)) { outputCus.splice(i, 1); i--; break; } - else if (c1.PtOnCurve(c2.StartPoint) && c1.PtOnCurve(c2.EndPoint)) + else if (c1.PtOnCurve(c2StartPt) && c1.PtOnCurve(c2EndPt)) { // c2完全在c1内 outputCus.splice(j, 1); @@ -152,21 +156,20 @@ export class PolyOffestUtil } //如果线段端点相连,跳过 - let isLink = [c1.StartPoint, c1.EndPoint].some(p => equal(p, c2.StartPoint) || equal(p, c2.EndPoint)); + let isLink = [c1StartPt, c1EndPt].some(p => equal(p, c2StartPt) || equal(p, c2EndPt)); if (isLink) continue; let pts = c1.IntersectWith(c2, IntersectOption.OnBothOperands); if (pts.length > 0) { //按照从左到右,从上到下,分别取前后部分,即去掉中间部分 - [c1, c2].forEach((c, index) => { let cs = c.GetSplitCurvesByPts(pts); if (cs.length === 2) { let box = SortEntityByBox(cs, true); - index === 0 ? outputCus[i] = cs[index] : outputCus[j] = cs[index]; + outputCus[index === 0 ? i : j] = cs[index] boxCurves.set(cs[index], box.get(cs[index])); } }) @@ -177,11 +180,11 @@ export class PolyOffestUtil return outputCus; } //偏移曲线 - private OffestCurve(pls: Curve[]): offestRes[] + private OffestCurve(pls: Curve[]): offsetRes[] { return pls.map((cu, index) => { - let curve = cu.GetOffsetCurves(this.m_OffestDist)[0]; + let curve = cu.GetOffsetCurves(this.m_OffsetDist)[0]; return { curve, index }; }); } @@ -262,10 +265,10 @@ export class PolyOffestUtil * 连接修剪相邻曲线,并构造修剪轮廓 * * @private - * @param {offestRes[]} offResList + * @param {offsetRes[]} offResList * @memberof PolyOffestUtil */ - private TrimAndBuildContour(offResList: offestRes[]) + private TrimAndBuildContour(offResList: offsetRes[]) { arrayRemoveIf(offResList, r => !r.curve || equaln(r.curve.Length, 0, 1e-6)); @@ -561,6 +564,7 @@ export class PolyOffestUtil * @param {Circle} cir 补圆 * @param {Vector3} startPt 补圆的切割点1 * @param {Vector3} endPt 补圆的切割点2 + * @param {boolean} isbuildCir 是否构建圆轮廓 * @returns * @memberof PolyOffestUtil */ @@ -574,15 +578,19 @@ export class PolyOffestUtil { let arc1 = splitCus[0] as Arc; let arc2 = splitCus[1] as Arc; + let tmpPts = cir.IntersectWith(this.m_Polyline, IntersectOption.OnBothOperands); let onCu0Pts = tmpPts.filter(p => arc1.PtOnCurve(p)); let onCu1Pts = tmpPts.filter(p => arc2.PtOnCurve(p)); + let lastCu = arrayLast(this.m_RetCurves); + //让圆弧保持和最后一段首尾相连 if (!equal(arc1.StartPoint, lastCu.EndPoint)) arc1.Reverse(); if (!equal(arc2.StartPoint, lastCu.EndPoint)) arc2.Reverse(); + //优先选择和源线段不想交的圆弧,如果都相交或者都不相交,选择和最后一段切线接近的圆弧 let cu: Arc; if (onCu0Pts.length === onCu1Pts.length) @@ -652,7 +660,8 @@ export class PolyOffestUtil let cus = l.GetSplitCurves(iParams); //移除0长度线和在轮廓内的线. - arrayRemoveIf(cus, cu => equaln(cu.Length, 0, 1e-6) + arrayRemoveIf(cus, cu => + equaln(cu.Length, 0, 1e-6) || outline.PtInCurve(cu.GetPointAtParam(0.5)) ); cus.forEach(c => boxCurves.set(c, c.BoundingBox)) @@ -701,7 +710,7 @@ export class PolyOffestUtil { if (pts.length > 1) { - let rad2 = Math.pow(this.m_OffestDist, 2); + let rad2 = Math.pow(this.m_OffsetDist, 2); //计算到曲线的距离大于偏移距离 let [ptGtRad1, ptGtRad2] = pts.map(p =>