|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
import { Matrix4, Vector3 } from "three";
|
|
|
|
|
import { curveLinkGroup, GetPointAtCurveDir } from "../Common/CurveUtils";
|
|
|
|
|
import { GetPointAtCurveDir } from "../Common/CurveUtils";
|
|
|
|
|
import { Arc } from "../DatabaseServices/Entity/Arc";
|
|
|
|
|
import { Board } from "../DatabaseServices/Entity/Board";
|
|
|
|
|
import { Circle } from "../DatabaseServices/Entity/Circle";
|
|
|
|
@ -8,9 +8,9 @@ import { Ellipse } from "../DatabaseServices/Entity/Ellipse";
|
|
|
|
|
import { Line } from "../DatabaseServices/Entity/Line";
|
|
|
|
|
import { Polyline } from "../DatabaseServices/Entity/Polyline";
|
|
|
|
|
import { Spline } from "../DatabaseServices/Spline";
|
|
|
|
|
import { JigUtils } from "../Editor/JigUtils";
|
|
|
|
|
import { PromptEntityResult, PromptPointResult } from "../Editor/PromptResult";
|
|
|
|
|
import { angle, AsVector2, equalv3, isParallelTo, midPoint } from "../Geometry/GeUtils";
|
|
|
|
|
import { angle, AsVector2, equalv3, isIntersect2, isParallelTo, midPoint } from "../Geometry/GeUtils";
|
|
|
|
|
import { Orbit } from "../Geometry/Orbit";
|
|
|
|
|
import { IntersectOption } from "../GraphicsSystem/IntersectWith";
|
|
|
|
|
|
|
|
|
|
function Encode(res: PromptEntityResult, enMap: (PromptEntityResult[])[])
|
|
|
|
@ -57,7 +57,7 @@ function CircleEnResToArc(enRes: PromptEntityResult)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function GetFilletCurve(enRes: PromptEntityResult): any[]
|
|
|
|
|
function GetFilletCurve(enRes: PromptEntityResult): [Curve, number]
|
|
|
|
|
{
|
|
|
|
|
if (enRes.Entity instanceof Polyline)
|
|
|
|
|
{
|
|
|
|
@ -67,7 +67,7 @@ function GetFilletCurve(enRes: PromptEntityResult): any[]
|
|
|
|
|
return [pl.GetCurveAtParam(param), paramF];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return [enRes.Entity, NaN];
|
|
|
|
|
return [enRes.Entity as Curve, NaN];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ExtendType
|
|
|
|
@ -79,7 +79,9 @@ enum ExtendType
|
|
|
|
|
export interface FilletRes
|
|
|
|
|
{
|
|
|
|
|
cu1?: Curve;
|
|
|
|
|
cu1Extend?: ExtendType;
|
|
|
|
|
cu2?: Curve;
|
|
|
|
|
cu2Extend?: ExtendType;
|
|
|
|
|
arc?: Arc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -193,6 +195,10 @@ export class FilletUtils
|
|
|
|
|
this.ExtendPt(splitedCu1, arcP1);
|
|
|
|
|
this.ExtendPt(splitedCu2, arcP2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.cu1Extend = splitedCu1.ExtType;
|
|
|
|
|
res.cu2Extend = splitedCu2.ExtType;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
FilletPolyLineSelf(enRes1: PromptEntityResult, enRes2: PromptEntityResult): FilletRes
|
|
|
|
@ -241,14 +247,14 @@ export class FilletUtils
|
|
|
|
|
if (fres.cu2 instanceof Arc)
|
|
|
|
|
pln.SetBulgeAt(parF2, fres.cu2.Bul);
|
|
|
|
|
|
|
|
|
|
let splitType1 = equalv3(c1.StartPoint, fres.cu1.StartPoint);
|
|
|
|
|
let splitType2 = equalv3(c2.StartPoint, fres.cu2.StartPoint);
|
|
|
|
|
let splitType1 = fres.cu1Extend;
|
|
|
|
|
let splitType2 = fres.cu2Extend;
|
|
|
|
|
|
|
|
|
|
if (splitType1 === splitType2)
|
|
|
|
|
return;
|
|
|
|
|
if (!fres.arc)
|
|
|
|
|
{
|
|
|
|
|
if (splitType1)
|
|
|
|
|
if (splitType1 === ExtendType.End)
|
|
|
|
|
{
|
|
|
|
|
let ep = AsVector2(fres.cu1.EndPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
pln.SetPointAt(parF1 + 1, ep);
|
|
|
|
@ -275,7 +281,7 @@ export class FilletUtils
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (splitType1)//没有经过起点
|
|
|
|
|
if (splitType1 === ExtendType.End)//没有经过起点
|
|
|
|
|
{
|
|
|
|
|
let sp = AsVector2(fres.cu1.EndPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
if (parF2 - parF1 === 1)
|
|
|
|
@ -334,24 +340,42 @@ export class FilletUtils
|
|
|
|
|
let fres = this.Fillet(es1, es2);
|
|
|
|
|
if (fres)
|
|
|
|
|
{
|
|
|
|
|
let pln: Polyline;
|
|
|
|
|
let isFirst = false;
|
|
|
|
|
let cus: Curve[] = [];
|
|
|
|
|
|
|
|
|
|
let isFirst = false;
|
|
|
|
|
|
|
|
|
|
if (fres.cu1)
|
|
|
|
|
{
|
|
|
|
|
if (enRes1.Entity instanceof Polyline)
|
|
|
|
|
{
|
|
|
|
|
isFirst = true;
|
|
|
|
|
pln = enRes1.Entity.Clone();
|
|
|
|
|
let pln = enRes1.Entity.Clone();
|
|
|
|
|
pln.DigestionCloseMark();
|
|
|
|
|
|
|
|
|
|
let xcus = enRes1.Entity.Explode();
|
|
|
|
|
xcus[paramF1] = fres.cu1;
|
|
|
|
|
cus.push(...xcus);
|
|
|
|
|
if (fres.cu1 instanceof Arc)
|
|
|
|
|
pln.SetBulgeAt(paramF1, fres.cu1.Bul);
|
|
|
|
|
|
|
|
|
|
if (fres.cu1Extend === ExtendType.End)
|
|
|
|
|
{
|
|
|
|
|
pln.LineData.splice(paramF1 + 2);
|
|
|
|
|
|
|
|
|
|
let ep = AsVector2(fres.cu1.EndPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
pln.SetPointAt(paramF1 + 1, ep);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pln.LineData.splice(0, paramF1);
|
|
|
|
|
let sp = AsVector2(fres.cu1.StartPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
pln.SetPointAt(0, sp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cus.push(pln);
|
|
|
|
|
}
|
|
|
|
|
//@ts-ignore
|
|
|
|
|
else if (!enRes1.IsCircle)
|
|
|
|
|
cus.push(fres.cu1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fres.arc)
|
|
|
|
|
cus.push(fres.arc);
|
|
|
|
|
|
|
|
|
@ -359,34 +383,49 @@ export class FilletUtils
|
|
|
|
|
{
|
|
|
|
|
if (enRes2.Entity instanceof Polyline)
|
|
|
|
|
{
|
|
|
|
|
if (!pln)
|
|
|
|
|
pln = enRes2.Entity.Clone();
|
|
|
|
|
let pln = enRes2.Entity.Clone();
|
|
|
|
|
pln.DigestionCloseMark();
|
|
|
|
|
|
|
|
|
|
if (fres.cu2 instanceof Arc)
|
|
|
|
|
pln.SetBulgeAt(paramF2, fres.cu2.Bul);
|
|
|
|
|
|
|
|
|
|
let xcus = enRes2.Entity.Explode();
|
|
|
|
|
xcus[paramF2] = fres.cu2;
|
|
|
|
|
cus.push(...xcus);
|
|
|
|
|
if (fres.cu2Extend === ExtendType.End)
|
|
|
|
|
{
|
|
|
|
|
pln.LineData.splice(paramF2 + 2);
|
|
|
|
|
|
|
|
|
|
let ep = AsVector2(fres.cu2.EndPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
pln.SetPointAt(paramF2 + 1, ep);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pln.LineData.splice(0, paramF2);
|
|
|
|
|
let sp = AsVector2(fres.cu2.StartPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
pln.SetPointAt(0, sp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cus.push(pln);
|
|
|
|
|
cus.reverse();
|
|
|
|
|
}
|
|
|
|
|
//@ts-ignore
|
|
|
|
|
else if (!enRes2.IsCircle)
|
|
|
|
|
cus.push(fres.cu2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let groups = curveLinkGroup(cus);
|
|
|
|
|
for (let g of groups)
|
|
|
|
|
if (cus.length > 0)
|
|
|
|
|
{
|
|
|
|
|
if (g.includes(fres.cu1) || g.includes(fres.cu2))
|
|
|
|
|
{
|
|
|
|
|
pln.LineData = [];
|
|
|
|
|
pln.ApplyMatrix(pln.OCSInv);
|
|
|
|
|
pln.CloseMark = false;
|
|
|
|
|
for (let cu of g)
|
|
|
|
|
pln.Join(cu);
|
|
|
|
|
if (isFirst)
|
|
|
|
|
return { cu1: pln, cu2: undefined, arc: undefined };
|
|
|
|
|
else
|
|
|
|
|
return { cu1: undefined, cu2: pln, arc: undefined };
|
|
|
|
|
}
|
|
|
|
|
let pl = cus[0] as Polyline;
|
|
|
|
|
if (!(pl instanceof Polyline))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (let i = 1; i < cus.length; i++)
|
|
|
|
|
pl.Join(cus[i]);
|
|
|
|
|
|
|
|
|
|
if (isFirst)
|
|
|
|
|
return { cu1: pl };
|
|
|
|
|
else
|
|
|
|
|
return { cu2: pl };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
@ -501,9 +540,6 @@ export class FilletUtils
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 平行线倒角
|
|
|
|
|
* @param enRes1
|
|
|
|
|
* @param enRes2
|
|
|
|
|
* @returns parallel line
|
|
|
|
|
*/
|
|
|
|
|
private FilletParallelLine(enRes1: PromptEntityResult, enRes2: PromptEntityResult): FilletRes
|
|
|
|
|
{
|
|
|
|
@ -514,9 +550,15 @@ export class FilletUtils
|
|
|
|
|
if (!isParallelTo(l1Derv, l2.GetFistDeriv(0)))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
let vec = l2.StartPoint.sub(l1.StartPoint);
|
|
|
|
|
if (isParallelTo(vec, l1Derv))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
let planeNormal = vec.cross(l1Derv).normalize();
|
|
|
|
|
|
|
|
|
|
let par1 = l2.GetClosestAtPoint(l1.StartPoint, true).param;
|
|
|
|
|
let par2 = l2.GetClosestAtPoint(l1.EndPoint, true).param;
|
|
|
|
|
if (!l1.ParamOnCurve(par1) && !l1.ParamOnCurve(par2))
|
|
|
|
|
if (!isIntersect2(0, 1, par1, par2))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
let lineClone1 = l1.Clone();
|
|
|
|
@ -527,27 +569,56 @@ export class FilletUtils
|
|
|
|
|
let parFix = Math.round(par);
|
|
|
|
|
let ptFix = lineClone1.GetPointAtParam(parFix);
|
|
|
|
|
let ptL2Fix = lineClone2.GetClosestAtPoint(ptFix, true).closestPt;
|
|
|
|
|
|
|
|
|
|
let cu1Extend = parFix === 0 ? ExtendType.Start : ExtendType.End;
|
|
|
|
|
let cu2Extend: ExtendType;
|
|
|
|
|
if ((par1 > par2) === (parFix === 1))
|
|
|
|
|
{
|
|
|
|
|
lineClone2.StartPoint = ptL2Fix;
|
|
|
|
|
cu2Extend = ExtendType.Start;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lineClone2.EndPoint = ptL2Fix;
|
|
|
|
|
cu2Extend = ExtendType.End;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let radius = ptFix.distanceTo(ptL2Fix) / 2;
|
|
|
|
|
if (radius < 1e-3)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
let arcCenter = midPoint(ptFix, ptL2Fix);
|
|
|
|
|
|
|
|
|
|
let sv = ptFix.sub(arcCenter).applyMatrix4(l1.OCSInv);
|
|
|
|
|
let ev = ptL2Fix.sub(arcCenter).applyMatrix4(l2.OCSInv);
|
|
|
|
|
let sv = ptFix.sub(arcCenter);
|
|
|
|
|
let ev = ptL2Fix.sub(arcCenter);
|
|
|
|
|
|
|
|
|
|
if (parFix === 0)
|
|
|
|
|
l1Derv.negate();
|
|
|
|
|
|
|
|
|
|
let arc = new Arc(new Vector3(), ptFix.distanceTo(ptL2Fix) / 2, angle(sv), angle(ev), ev.cross(l1Derv.applyMatrix4(l1.OCSInv)).z > 0);
|
|
|
|
|
arc.ApplyMatrix(l1.OCS);
|
|
|
|
|
//平面矩阵
|
|
|
|
|
let xVec = new Vector3();
|
|
|
|
|
let yVec = new Vector3();
|
|
|
|
|
Orbit.ComputUpDirection(planeNormal, yVec, xVec);
|
|
|
|
|
let mtx = new Matrix4().makeBasis(xVec, yVec, planeNormal.negate());
|
|
|
|
|
let mtxInv = new Matrix4().getInverse(mtx);
|
|
|
|
|
//变换
|
|
|
|
|
sv.applyMatrix4(mtxInv);
|
|
|
|
|
ev.applyMatrix4(mtxInv);
|
|
|
|
|
l1Derv.applyMatrix4(mtxInv);
|
|
|
|
|
|
|
|
|
|
let sa = angle(sv);
|
|
|
|
|
let ea = angle(ev);
|
|
|
|
|
let clockwise = ev.cross(l1Derv).z > 0;
|
|
|
|
|
let arc = new Arc(new Vector3(), radius, sa, ea, clockwise);
|
|
|
|
|
arc.ApplyMatrix(mtx);
|
|
|
|
|
arc.Center = arcCenter;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
cu1: lineClone1,
|
|
|
|
|
cu1Extend,
|
|
|
|
|
cu2: lineClone2,
|
|
|
|
|
arc
|
|
|
|
|
cu2Extend,
|
|
|
|
|
arc,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|