重构算法2切割

pull/68/head
Zoe 6 years ago
parent 4aff6935c4
commit d7e6669793

@ -82,30 +82,47 @@ export class Command_TestOffset implements Command
{
if (lastpls) lastpls.forEach(cu => cu.Erase());
let dist = p.distanceTo(cu.GetClosestPointTo(p, !cu.IsClose));
// let dist = p.distanceTo(cu.GetClosestPointTo(p, !cu.IsClose));
if (cu instanceof Polyline && cu.EndParam > 1 && cu.Area > 0)
{
let pls1 = cu.GetOffsetCurves(dist);
let pls2 = cu.GetOffsetCurves(-dist);
// if (cu instanceof Polyline && cu.EndParam > 1 && cu.Area > 0)
// {
// let pls1 = cu.GetOffsetCurves(dist);
// let pls2 = cu.GetOffsetCurves(-dist);
let dis1 = Math.min.apply(undefined, pls1.map(c => p.distanceTo(c.GetClosestPointTo(p, false))));
let dis2 = Math.min.apply(undefined, pls2.map(c => p.distanceTo(c.GetClosestPointTo(p, false))));
// let dis1 = Math.min(...pls1.map(c => p.distanceTo(c.GetClosestPointTo(p, false))));
// let dis2 = Math.min(...pls2.map(c => p.distanceTo(c.GetClosestPointTo(p, false))));
if (dis1 < dis2)
lastpls = pls1;
else
lastpls = pls2;
}
else
// if (dis1 < dis2)
// lastpls = pls1;
// else
// lastpls = pls2;
// }
// else
// {
// let ptClose = cu.GetClosestPointTo(p, false);
// let toPtVec = p.clone().sub(ptClose); //点击处向量
// let d = cu.GetFistDeriv(cu.GetParamAtPoint(ptClose));//切线。
// let c = toPtVec.cross(d);
// lastpls = cu.GetOffsetCurves(p.distanceTo(cu.GetClosestPointTo(p, !cu.IsClose)) * Math.sign(c.z));
// }
let ptClose = cu.GetClosestPointTo(p, false);
let toPtVec = p.clone().sub(ptClose); //点击处向量
let d = cu.GetFistDeriv(ptClose);//切线。
let dir = Math.sign(toPtVec.clone().cross(d).z);
if (cu instanceof Polyline)
{
let ptClose = cu.GetClosestPointTo(p, false);
let toPtVec = p.clone().sub(ptClose); //点击处向量
let d = cu.GetFistDeriv(cu.GetParamAtPoint(ptClose));//切线。
let c = toPtVec.cross(d);
lastpls = cu.GetOffsetCurves(p.distanceTo(cu.GetClosestPointTo(p, !cu.IsClose)) * Math.sign(c.z));
let par = cu.GetParamAtPoint(ptClose);
if (par === Math.floor(par) && par)
{
let fd = cu.GetFistDeriv(par - 0.1);
let fc = toPtVec.cross(fd);
let tmpDir = Math.sign(fd.clone().cross(d).z);
if (dir * fc.z < 0)
dir = tmpDir;
}
}
lastpls = cu.GetOffsetCurves(p.distanceTo(cu.GetClosestPointTo(p, !cu.IsClose)) * dir);
lastpls.forEach((offCur) =>
{
app.m_Database.ModelSpace.Append(offCur);

@ -8,7 +8,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/OffestPolyline';
import { PolyOffestUtil, PolyOffestUtil2 } from '../GraphicsSystem/OffestPolyline';
import { Arc } from './Arc';
import { Factory } from './CADFactory';
import { CADFile } from './CADFile';
@ -637,7 +637,7 @@ export class Polyline extends Curve
//偏移
GetOffsetCurves(offsetDist: number): Array<Curve>
{
let polyOffestUtil = new PolyOffestUtil(this, offsetDist);
let polyOffestUtil = new PolyOffestUtil2(this, offsetDist);
return polyOffestUtil.GetOffsetCurves();
}
/**

@ -616,21 +616,22 @@ export class PolyOffestUtil2
//偏移
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 plList2: offestRes[] = this.offestCurve(handledPl.Explode(), true);
let newProps = this.trimAndJointOffestPolyline(plList1, this.m_Polyline);
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 refPl = new Polyline(refProps);
newPl.ColorIndex = 1;
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[]
@ -710,47 +711,38 @@ export class PolyOffestUtil2
if (offestPlList.length === 0) return [];
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;
let startLine = frontLine.EndPoint.clone().sub(center);
// 圆心到后面线start点向量
let endLine = laterLine.StartPoint.clone().sub(center);
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(center, Math.abs(this.m_OffestDist));
//只会和前面线相交,因为圆心选取是根据后面线startPoint偏移距离处的点,只会与后面线相切,允许前面线延伸
let pts = tmpCir.IntersectWith(frontLine, IntersectOption.OnBothOperands);
if (pts.length > 0)
{
// 以center为圆心偏移距离为为半径画圆
let tmpCir = new Circle(center, Math.abs(this.m_OffestDist));
let pts = tmpCir.IntersectWith(frontLine, IntersectOption.ExtendBoth);
if (pts.length > 0)
{
//选取交点,如果有多个选离前面线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("无法补圆弧")
}
//选取交点,如果有多个选离前面线start点近的
intPt = this.selectFitInterPt(pts, frontLine.StartPoint);
let insLine = intPt.clone().sub(center);
this.adjustFrontLine(newProps[newProps.length - 1], frontLine.LineData[1], intPt);
}
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]];
for (let i = 0; i < offestPlList.length; i++)
@ -808,7 +800,6 @@ export class PolyOffestUtil2
{
if (par1 > 1)
{
// addArc(offestPlList[i + 1].index, frontLine, laterLine, newProps);
this.adjustLaterLine(newProp, laterLine.LineData[1], intPt);
}
else
@ -902,14 +893,12 @@ export class PolyOffestUtil2
{
//切割该分段
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)
}
}
})
}
//用小于偏移距离最近点对结果多段线数组进行切割
this.cuttingOffestPlByClosePt(origin, tmpPlList);
return tmpPlList;
return this.cuttingOffestPlByClosePt(origin, tmpPlList);
}
private getParsByPt(pl: Polyline, pt: Vector3)
{
@ -926,86 +915,58 @@ export class PolyOffestUtil2
}
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);
for (let j = 0; j < pllist.length; j++)
let needCutPls = [pl]
for (let p of [...originPts, ...closePts])
{
let offPl = pllist[j];
let closePt = offPl.GetClosestPointTo(center, false);
if (!closePt) continue;
let dist = closePt.distanceToSquared(center);
if (dist - this.m_OffestDist * this.m_OffestDist < -1e-8)
let tmpPl: Polyline[] = [];
needCutPls.forEach(pl =>
{
let cutedPls = this.cuttingPolyline(offPl, center);
if (cutedPls.length === 2)
{
pllist.splice(j - 1, 0, cutedPls[0]);
j++;
}
}
let cus = this.cuttingPolyline(pl, p);
tmpPl.push(...cus.cus);
})
needCutPls = tmpPl
}
cuttedPlList.push(...needCutPls);
}
return cuttedPlList
}
private cuttingPolyline(pl: Polyline, centerPt: Vector3)
{
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 pts = pl.IntersectWith(circle, IntersectOption.OnBothOperands);
if (pts.length === 1)
{
let par = pl.GetParamAtPoint(pts[0]);
if (isTargetCurInSourceCur(circle, pl))
return { cus: [], isCutted: true }
if (sDist < rad)
{
pl.LineData.splice(0, ~~par);
this.adjustLaterLine(pl.LineData[0], pl.LineData[1], pts[0]);
}
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)
let pars = circle.IntersectWith(pl, IntersectOption.OnBothOperands).map(p => pl.GetParamAtPoint(p));
let cus = pl.GetSplitCurves(pars);
if (cus.length === 1)
return { cus, isCutted: false }
else
{
let par1 = pl.GetParamAtPoint(pts[0]);
let par2 = pl.GetParamAtPoint(pts[1]);
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);
return {
cus: cus.filter(l => !isTargetCurInSourceCur(circle, l)),
isCutted: true
}
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)
{

Loading…
Cancel
Save