|
|
@ -33,6 +33,14 @@ export enum IntersectOption
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
ExtendBoth = 3,
|
|
|
|
ExtendBoth = 3,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export interface IntersectResult
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pt: Vector3,
|
|
|
|
|
|
|
|
thisParam: number,
|
|
|
|
|
|
|
|
argParam: number,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//延伸自身还是参数反转
|
|
|
|
//延伸自身还是参数反转
|
|
|
|
export function reverseIntersectOption(intType: IntersectOption)
|
|
|
|
export function reverseIntersectOption(intType: IntersectOption)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -46,28 +54,27 @@ export function reverseIntersectOption(intType: IntersectOption)
|
|
|
|
* 校验相交点是否满足延伸选项
|
|
|
|
* 校验相交点是否满足延伸选项
|
|
|
|
* 算法会计算无限延伸状态下的曲线交点,调用该方法进行校验返回校验后的点表
|
|
|
|
* 算法会计算无限延伸状态下的曲线交点,调用该方法进行校验返回校验后的点表
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param {Vector3[]} intPts 相交点.曲线当作完全状态下的相交点
|
|
|
|
* @param {Vector3[]} intRes 相交点.曲线当作完全状态下的相交点
|
|
|
|
* @param {Curve} c1 曲线1 由this参数传入
|
|
|
|
* @param {Curve} c1 曲线1 由this参数传入
|
|
|
|
* @param {Curve} c2 曲线2 由arg 参数传入
|
|
|
|
* @param {Curve} c2 曲线2 由arg 参数传入
|
|
|
|
* @param {Intersect} extType 延伸选项.
|
|
|
|
* @param {Intersect} extType 延伸选项.
|
|
|
|
* @returns {Array<Vector3>} 校验完成后的点表
|
|
|
|
* @returns {Array<Vector3>} 校验完成后的点表
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, extType: IntersectOption, tolerance = 1e-6): Array<Vector3>
|
|
|
|
function CheckPointOnCurve(intRes: IntersectResult[], c1: Curve, c2: Curve, extType: IntersectOption, tolerance = 1e-6): Array<IntersectResult>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return intPts.filter(p =>
|
|
|
|
return intRes.filter(r =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!(extType & IntersectOption.ExtendThis))
|
|
|
|
if (!(extType & IntersectOption.ExtendThis))
|
|
|
|
if (!c1.PtOnCurve3(p, tolerance))
|
|
|
|
if (!c1.PtOnCurve3(r.pt, tolerance))
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (!(extType & IntersectOption.ExtendArg))
|
|
|
|
if (!(extType & IntersectOption.ExtendArg))
|
|
|
|
if (!c2.PtOnCurve3(p, tolerance))
|
|
|
|
if (!c2.PtOnCurve3(r.pt, tolerance))
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc): IntersectResult[]
|
|
|
|
export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!cu1.IsCoplaneTo(cu2)) return [];
|
|
|
|
if (!cu1.IsCoplaneTo(cu2)) return [];
|
|
|
|
|
|
|
|
|
|
|
@ -79,7 +86,7 @@ export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
|
|
|
|
let radius1 = cu1.Radius;
|
|
|
|
let radius1 = cu1.Radius;
|
|
|
|
let radius2 = cu2.Radius;
|
|
|
|
let radius2 = cu2.Radius;
|
|
|
|
|
|
|
|
|
|
|
|
let pts: Vector3[] = [];
|
|
|
|
let pts: IntersectResult[] = [];
|
|
|
|
let dist = center2.distanceTo(center1);
|
|
|
|
let dist = center2.distanceTo(center1);
|
|
|
|
|
|
|
|
|
|
|
|
if (dist < Math.abs(radius1 - radius2)
|
|
|
|
if (dist < Math.abs(radius1 - radius2)
|
|
|
@ -111,9 +118,17 @@ export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
|
|
|
|
p1.applyMatrix4(c1Ocs);
|
|
|
|
p1.applyMatrix4(c1Ocs);
|
|
|
|
p2.applyMatrix4(c1Ocs);
|
|
|
|
p2.applyMatrix4(c1Ocs);
|
|
|
|
|
|
|
|
|
|
|
|
pts.push(p1);
|
|
|
|
pts.push({
|
|
|
|
|
|
|
|
pt: p1,
|
|
|
|
|
|
|
|
thisParam: cu1.GetParamAtPoint(p1),
|
|
|
|
|
|
|
|
argParam: cu2.GetParamAtPoint(p1),
|
|
|
|
|
|
|
|
});
|
|
|
|
if (!equalv3(p1, p2))//防止点重复
|
|
|
|
if (!equalv3(p1, p2))//防止点重复
|
|
|
|
pts.push(p2);
|
|
|
|
pts.push({
|
|
|
|
|
|
|
|
pt: p2,
|
|
|
|
|
|
|
|
thisParam: cu1.GetParamAtPoint(p2),
|
|
|
|
|
|
|
|
argParam: cu2.GetParamAtPoint(p2),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return pts;
|
|
|
|
return pts;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -161,12 +176,12 @@ export function IntersectEllipseAndLine(l: Line, el: Ellipse, extType: Intersect
|
|
|
|
* @param {(Circle | Arc)} circle 圆或圆弧
|
|
|
|
* @param {(Circle | Arc)} circle 圆或圆弧
|
|
|
|
* @returns 交点集合
|
|
|
|
* @returns 交点集合
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc)
|
|
|
|
function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc): IntersectResult[]
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let lineOrg = line.StartPoint;
|
|
|
|
let lineOrg = line.StartPoint;
|
|
|
|
let lineDirection = line.EndPoint.sub(lineOrg);
|
|
|
|
let lineDirection = line.EndPoint.sub(lineOrg);
|
|
|
|
let dirLen = lineDirection.length();
|
|
|
|
let dirLen = lineDirection.length();
|
|
|
|
if (dirLen === 0) return [];
|
|
|
|
if (equaln(dirLen, 0)) return [];
|
|
|
|
lineDirection.divideScalar(dirLen);
|
|
|
|
lineDirection.divideScalar(dirLen);
|
|
|
|
|
|
|
|
|
|
|
|
let diff = lineOrg.clone().sub(circle.Center);
|
|
|
|
let diff = lineOrg.clone().sub(circle.Center);
|
|
|
@ -176,14 +191,30 @@ function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc)
|
|
|
|
|
|
|
|
|
|
|
|
if (equaln(discr, 0, 1e-7))
|
|
|
|
if (equaln(discr, 0, 1e-7))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return [lineOrg.add(lineDirection.multiplyScalar(-a1))];
|
|
|
|
let pt = lineOrg.add(lineDirection.multiplyScalar(-a1));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return [{
|
|
|
|
|
|
|
|
pt,
|
|
|
|
|
|
|
|
thisParam: -a1 / dirLen,
|
|
|
|
|
|
|
|
argParam: circle.GetParamAtPoint(pt)
|
|
|
|
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (discr > 0)
|
|
|
|
else if (discr > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let root = Math.sqrt(discr);
|
|
|
|
let root = Math.sqrt(discr);
|
|
|
|
|
|
|
|
let p1 = lineOrg.clone().add(lineDirection.clone().multiplyScalar(-a1 + root));
|
|
|
|
|
|
|
|
let p2 = lineOrg.add(lineDirection.multiplyScalar(-a1 - root));
|
|
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
return [
|
|
|
|
lineOrg.clone().add(lineDirection.clone().multiplyScalar(-a1 + root)),
|
|
|
|
{
|
|
|
|
lineOrg.add(lineDirection.multiplyScalar(-a1 - root))
|
|
|
|
pt: p1,
|
|
|
|
|
|
|
|
thisParam: (-a1 + root) / dirLen,
|
|
|
|
|
|
|
|
argParam: circle.GetParamAtPoint(p1)
|
|
|
|
|
|
|
|
}, {
|
|
|
|
|
|
|
|
pt: p2,
|
|
|
|
|
|
|
|
thisParam: (-a1 - root) / dirLen,
|
|
|
|
|
|
|
|
argParam: circle.GetParamAtPoint(p2)
|
|
|
|
|
|
|
|
}
|
|
|
|
];
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [];
|
|
|
|
return [];
|
|
|
@ -287,7 +318,7 @@ function ShortestLine3AndLine3(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//直线和直线
|
|
|
|
//直线和直线
|
|
|
|
export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOption, fuzz = 1e-4): Vector3[]
|
|
|
|
export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOption, fuzz = 1e-4): IntersectResult[]
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// if (l1.Is2D && l2.Is2D)
|
|
|
|
// if (l1.Is2D && l2.Is2D)
|
|
|
|
// {
|
|
|
|
// {
|
|
|
@ -321,20 +352,23 @@ export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOptio
|
|
|
|
))
|
|
|
|
))
|
|
|
|
return [];
|
|
|
|
return [];
|
|
|
|
|
|
|
|
|
|
|
|
return [pt];
|
|
|
|
return [{
|
|
|
|
|
|
|
|
pt,
|
|
|
|
|
|
|
|
thisParam: param1,
|
|
|
|
|
|
|
|
argParam: param2
|
|
|
|
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: IntersectOption, tolerance = 1e-6): Vector3[]
|
|
|
|
export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: IntersectOption, tolerance = 1e-6): IntersectResult[]
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let cus: Curve[] = pl.Explode();
|
|
|
|
let cus: Curve[] = pl.Explode();
|
|
|
|
let cus2: Curve[];
|
|
|
|
let cus2: Curve[];
|
|
|
|
|
|
|
|
|
|
|
|
if (cu instanceof Polyline)
|
|
|
|
if (cu instanceof Polyline)
|
|
|
|
cus2 = cu.Explode();
|
|
|
|
cus2 = cu.Explode();
|
|
|
|
else
|
|
|
|
else
|
|
|
|
cus2 = [cu];
|
|
|
|
cus2 = [cu];
|
|
|
|
|
|
|
|
|
|
|
|
let pts: Vector3[] = [];
|
|
|
|
let intRes: IntersectResult[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < cus.length; i++)
|
|
|
|
for (let i = 0; i < cus.length; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -356,7 +390,7 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte
|
|
|
|
if ((cu instanceof Polyline && cu.CloseMark) || !(isStart2 || isEnd2))
|
|
|
|
if ((cu instanceof Polyline && cu.CloseMark) || !(isStart2 || isEnd2))
|
|
|
|
ext = ext & ~IntersectOption.ExtendArg;
|
|
|
|
ext = ext & ~IntersectOption.ExtendArg;
|
|
|
|
|
|
|
|
|
|
|
|
let ipts = cu1.IntersectWith(cu2, ext, tolerance).filter(p1 => pts.every(p2 => !equalv3(p1, p2)));
|
|
|
|
let ptPars = cu1.IntersectWith2(cu2, ext, tolerance).filter(r1 => intRes.every(r2 => !equalv3(r1.pt, r2.pt)));
|
|
|
|
|
|
|
|
|
|
|
|
//校验延伸
|
|
|
|
//校验延伸
|
|
|
|
if (IntersectOption.ExtendThis & ext)
|
|
|
|
if (IntersectOption.ExtendThis & ext)
|
|
|
@ -367,11 +401,11 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (isStart)
|
|
|
|
else if (isStart)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ipts = ipts.filter(p => cu1.GetParamAtPoint(p) <= 1);
|
|
|
|
ptPars = ptPars.filter(res => res.thisParam <= 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (isEnd)
|
|
|
|
else if (isEnd)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ipts = ipts.filter(p => cu1.GetParamAtPoint(p) >= 0);
|
|
|
|
ptPars = ptPars.filter(res => res.thisParam >= 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IntersectOption.ExtendArg & ext)
|
|
|
|
if (IntersectOption.ExtendArg & ext)
|
|
|
@ -382,20 +416,27 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (isStart2)
|
|
|
|
else if (isStart2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ipts = ipts.filter(p => cu2.GetParamAtPoint(p) <= cu2.EndParam);
|
|
|
|
ptPars = ptPars.filter(res => res.argParam + j <= cu2.EndParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (isEnd2)
|
|
|
|
else if (isEnd2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ipts = ipts.filter(p => cu2.GetParamAtPoint(p) >= 0);
|
|
|
|
ptPars = ptPars.filter(res => res.argParam + j >= 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pts.push(...ipts);
|
|
|
|
intRes.push(...ptPars.map(r =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
pt: r.pt,
|
|
|
|
|
|
|
|
thisParam: pl.GetParamAtPoint(r.pt),
|
|
|
|
|
|
|
|
argParam: cu.GetParamAtPoint(r.pt),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pts.sort(comparePoint("xyz"));
|
|
|
|
intRes.sort((r1, r2) => comparePoint("xyz")(r1.pt, r2.pt));
|
|
|
|
arrayRemoveDuplicateBySort(pts, equalv3);
|
|
|
|
arrayRemoveDuplicateBySort(intRes, (r1, r2) => equalv3(r1.pt, r2.pt));
|
|
|
|
return pts;
|
|
|
|
return intRes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function IntersectLineAndEllipseFor2D(l: Line, el: Ellipse)
|
|
|
|
export function IntersectLineAndEllipseFor2D(l: Line, el: Ellipse)
|
|
|
@ -455,7 +496,15 @@ export function IntersectLineAndEllipseFor2D(l: Line, el: Ellipse)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let matInv = new Matrix4().getInverse(mat);
|
|
|
|
let matInv = new Matrix4().getInverse(mat);
|
|
|
|
return pts.map(p => p.applyMatrix4(matInv));
|
|
|
|
return pts.map(p =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pt = p.applyMatrix4(matInv);
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
pt,
|
|
|
|
|
|
|
|
thisParam: l.GetParamAtPoint(pt),
|
|
|
|
|
|
|
|
argParam: el.GetParamAtPoint(pt)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export function IntersectEllipseAndCircleOrArc(el: Ellipse, cir: Circle | Arc, type: IntersectOption)
|
|
|
|
export function IntersectEllipseAndCircleOrArc(el: Ellipse, cir: Circle | Arc, type: IntersectOption)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -506,8 +555,16 @@ export function IntersectEllipseAndCircleOrArc(el: Ellipse, cir: Circle | Arc, t
|
|
|
|
];
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let ro = new Matrix4().makeRotationZ(el.Rotation);
|
|
|
|
let ro = new Matrix4().makeRotationZ(el.Rotation);
|
|
|
|
pts = pts.map(p => p.applyMatrix4(ro).applyMatrix4(el.OCS));
|
|
|
|
let res = pts.map(p =>
|
|
|
|
return CheckPointOnCurve(pts, el, cir, type);
|
|
|
|
{
|
|
|
|
|
|
|
|
let pt = p.applyMatrix4(ro).applyMatrix4(el.OCS)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
pt,
|
|
|
|
|
|
|
|
thisParam: el.GetParamAtPoint(pt),
|
|
|
|
|
|
|
|
argParam: cir.GetParamAtPoint(pt)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
return CheckPointOnCurve(res, el, cir, type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -525,7 +582,8 @@ export function IntersectEllipseAndCircleOrArc(el: Ellipse, cir: Circle | Arc, t
|
|
|
|
type = IntersectOption.OnBothOperands;
|
|
|
|
type = IntersectOption.OnBothOperands;
|
|
|
|
|
|
|
|
|
|
|
|
let intPts = IntersectPolylineAndCurve(pl, cirClone, type);
|
|
|
|
let intPts = IntersectPolylineAndCurve(pl, cirClone, type);
|
|
|
|
return intPts.map(p => p.applyMatrix4(el.OCS));
|
|
|
|
intPts.forEach(r => r.pt.applyMatrix4(el.OCS));
|
|
|
|
|
|
|
|
return intPts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export function IntersectEllipse(el1: Ellipse, el2: Ellipse, type: IntersectOption)
|
|
|
|
export function IntersectEllipse(el1: Ellipse, el2: Ellipse, type: IntersectOption)
|
|
|
@ -568,6 +626,7 @@ export function IntersectEllipse(el1: Ellipse, el2: Ellipse, type: IntersectOpti
|
|
|
|
let pl1 = new Polyline(lineData1);
|
|
|
|
let pl1 = new Polyline(lineData1);
|
|
|
|
let pl2 = new Polyline(lineData2).ApplyMatrix(diffMat);
|
|
|
|
let pl2 = new Polyline(lineData2).ApplyMatrix(diffMat);
|
|
|
|
|
|
|
|
|
|
|
|
let intPts = pl1.IntersectWith(pl2, 0);
|
|
|
|
let intPts = pl1.IntersectWith2(pl2, 0);
|
|
|
|
return intPts.map(p => p.applyMatrix4(el1.OCS));
|
|
|
|
intPts.forEach(r => r.pt.applyMatrix4(el1.OCS));
|
|
|
|
|
|
|
|
return intPts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|