重构算法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()); 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) // if (cu instanceof Polyline && cu.EndParam > 1 && cu.Area > 0)
{ // {
let pls1 = cu.GetOffsetCurves(dist); // let pls1 = cu.GetOffsetCurves(dist);
let pls2 = cu.GetOffsetCurves(-dist); // let pls2 = cu.GetOffsetCurves(-dist);
let dis1 = Math.min.apply(undefined, pls1.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.apply(undefined, pls2.map(c => p.distanceTo(c.GetClosestPointTo(p, false)))); // let dis2 = Math.min(...pls2.map(c => p.distanceTo(c.GetClosestPointTo(p, false))));
if (dis1 < dis2) // if (dis1 < dis2)
lastpls = pls1; // lastpls = pls1;
else // else
lastpls = pls2; // lastpls = pls2;
} // }
else // 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 par = cu.GetParamAtPoint(ptClose);
let toPtVec = p.clone().sub(ptClose); //点击处向量 if (par === Math.floor(par) && par)
let d = cu.GetFistDeriv(cu.GetParamAtPoint(ptClose));//切线。 {
let c = toPtVec.cross(d); let fd = cu.GetFistDeriv(par - 0.1);
lastpls = cu.GetOffsetCurves(p.distanceTo(cu.GetClosestPointTo(p, !cu.IsClose)) * Math.sign(c.z)); 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) => lastpls.forEach((offCur) =>
{ {
app.m_Database.ModelSpace.Append(offCur); app.m_Database.ModelSpace.Append(offCur);

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

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

Loading…
Cancel
Save