|
|
|
@ -1,33 +1,70 @@
|
|
|
|
|
import { Vector3 } from 'three';
|
|
|
|
|
|
|
|
|
|
import { Arc } from '../DatabaseServices/Arc';
|
|
|
|
|
import { Curve } from '../DatabaseServices/Curve';
|
|
|
|
|
import { Line } from '../DatabaseServices/Line';
|
|
|
|
|
import { equal, equaln } from '../Geometry/GeUtils';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export enum Intersect
|
|
|
|
|
import { Circle } from '../DatabaseServices/Circle';
|
|
|
|
|
import { getClosestPt, Vec3DTo2D } from '../Common/CurveUtils';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 相交延伸选项.
|
|
|
|
|
*
|
|
|
|
|
* @export
|
|
|
|
|
* @enum {number}
|
|
|
|
|
*/
|
|
|
|
|
export enum IntersectOption
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* 两者都不延伸
|
|
|
|
|
*/
|
|
|
|
|
OnBothOperands = 0,
|
|
|
|
|
/**
|
|
|
|
|
* 延伸自身
|
|
|
|
|
*/
|
|
|
|
|
ExtendThis = 1,
|
|
|
|
|
/**
|
|
|
|
|
* 延伸参数
|
|
|
|
|
*/
|
|
|
|
|
ExtendArg = 2,
|
|
|
|
|
/**
|
|
|
|
|
* 延伸两者
|
|
|
|
|
*/
|
|
|
|
|
ExtendBoth = 3,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验相交点是否满足延伸选项
|
|
|
|
|
* 算法会计算无限延伸状态下的曲线交点,调用该方法进行校验返回校验后的点表
|
|
|
|
|
*
|
|
|
|
|
* @param {Vector3[]} intPts 相交点.曲线当作完全状态下的相交点
|
|
|
|
|
* @param {Curve} c1 曲线1
|
|
|
|
|
* @param {Curve} c2 曲线2
|
|
|
|
|
* @param {Intersect} intType 延伸选项.
|
|
|
|
|
* @returns {Array<Vector3>}
|
|
|
|
|
*/
|
|
|
|
|
function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, intType: IntersectOption): Array<Vector3>
|
|
|
|
|
{
|
|
|
|
|
return intPts.filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return (intType & IntersectOption.ExtendThis || c1.PtOnCurve(p)) && (intType & IntersectOption.ExtendArg || c2.PtOnCurve(p))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function IntersectArcAndArc(arc1: Arc, arc2: Arc, intType: Intersect)
|
|
|
|
|
//圆和圆(传入圆心和半径)
|
|
|
|
|
export function IntersectCircleAndCircleOrArc(center1?: Vector3, radius1?: number, center2?: Vector3, radius2?: number)
|
|
|
|
|
{
|
|
|
|
|
let pts: Vector3[] = [];
|
|
|
|
|
let dist = arc2.Center.distanceTo(arc1.Center);
|
|
|
|
|
let dist = center2.distanceTo(center1);
|
|
|
|
|
|
|
|
|
|
if (dist > (arc1.Radius + arc2.Radius + 1e-3))
|
|
|
|
|
if (dist > (radius1 + radius2 + 1e-3))
|
|
|
|
|
{
|
|
|
|
|
return pts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let dstsqr = dist * dist;
|
|
|
|
|
let r1sqr = arc1.Radius * arc1.Radius;
|
|
|
|
|
let r2sqr = arc2.Radius * arc2.Radius;
|
|
|
|
|
let r1sqr = radius1 * radius1;
|
|
|
|
|
let r2sqr = radius2 * radius2;
|
|
|
|
|
|
|
|
|
|
let a = (dstsqr - r2sqr + r1sqr) / (2 * dist);
|
|
|
|
|
let h = Math.sqrt(Math.abs(r1sqr - (a * a)));
|
|
|
|
@ -35,52 +72,115 @@ export function IntersectArcAndArc(arc1: Arc, arc2: Arc, intType: Intersect)
|
|
|
|
|
let ratio_a = a / dist;
|
|
|
|
|
let ratio_h = h / dist;
|
|
|
|
|
|
|
|
|
|
let dx = arc2.Center.x - arc1.Center.x;
|
|
|
|
|
let dy = arc2.Center.y - arc1.Center.y;
|
|
|
|
|
let dx = center2.x - center1.x;
|
|
|
|
|
let dy = center2.y - center1.y;
|
|
|
|
|
|
|
|
|
|
let phix = arc1.Center.x + (ratio_a * dx);
|
|
|
|
|
let phiy = arc1.Center.y + (ratio_a * dy);
|
|
|
|
|
let phix = center1.x + (ratio_a * dx);
|
|
|
|
|
let phiy = center1.y + (ratio_a * dy);
|
|
|
|
|
|
|
|
|
|
dx = dx * ratio_h;
|
|
|
|
|
dy = dy * ratio_h;
|
|
|
|
|
|
|
|
|
|
let pt = new Vector3(phix + dy, phiy - dx);
|
|
|
|
|
let p2 = new Vector3(phix - dy, phiy + dx);
|
|
|
|
|
if (arc1.PtOnCurve(pt) && arc2.PtOnCurve(pt))//点在圆弧上
|
|
|
|
|
{
|
|
|
|
|
pts.push(pt);
|
|
|
|
|
}
|
|
|
|
|
if (arc1.PtOnCurve(p2) && arc2.PtOnCurve(p2) && !equal(pt, p2))//点在圆弧上&&不重复原来的点
|
|
|
|
|
|
|
|
|
|
pts.push(pt);
|
|
|
|
|
if (!equal(pt, p2))//防止点重复
|
|
|
|
|
{
|
|
|
|
|
pts.push(p2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pts;
|
|
|
|
|
}
|
|
|
|
|
export function IntersectLineAndArc(line: Line, arc: Arc, intType: Intersect)
|
|
|
|
|
//圆与圆
|
|
|
|
|
export function IntersectCircleAndCircle(circle1: Circle, circle2: Circle, intType: IntersectOption)
|
|
|
|
|
{
|
|
|
|
|
return this.IntersectCircleAndCircleOrArc(circle1.Center, circle1.Radius, circle2.Center, circle2.Radius);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//圆与圆弧
|
|
|
|
|
export function IntersectCircleAndArc(circle: Circle, arc2: Arc, intType: IntersectOption)
|
|
|
|
|
{
|
|
|
|
|
let ptArr = this.IntersectCircleAndCircleOrArc(circle.Center, circle.Radius, arc2.Center, arc2.Radius);
|
|
|
|
|
return CheckPointOnCurve(ptArr, circle, arc2, intType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//圆弧与圆弧
|
|
|
|
|
export function IntersectArcAndArc(arc1: Arc, arc2: Arc, intType: IntersectOption)
|
|
|
|
|
{
|
|
|
|
|
let ptArr = this.IntersectCircleAndCircleOrArc(arc1.Center, arc1.Radius, arc2.Center, arc2.Radius);
|
|
|
|
|
return CheckPointOnCurve(ptArr, arc1, arc2, intType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//直线和圆(传入圆心和半径)
|
|
|
|
|
export function IntersectLineAndCircleOrArc(line: Line, center?: Vector3, radius?: number)
|
|
|
|
|
{
|
|
|
|
|
let pts: Vector3[] = [];
|
|
|
|
|
let k = (line.EndPoint.y - line.StartPoint.y) / (line.EndPoint.x - line.StartPoint.x);
|
|
|
|
|
let b = line.EndPoint.y - k * line.EndPoint.x;
|
|
|
|
|
//列方程
|
|
|
|
|
let x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
|
|
|
|
let c = Math.pow(arc.Center.x, 2) + Math.pow(b - arc.Center.y, 2) - Math.pow(arc.Radius, 2);
|
|
|
|
|
let a = (1 + Math.pow(k, 2));
|
|
|
|
|
let b1 = (2 * arc.Center.x - 2 * k * (b - arc.Center.y));
|
|
|
|
|
let tmp = Math.sqrt(b1 * b1 - 4 * a * c);
|
|
|
|
|
if (!isNaN(tmp))
|
|
|
|
|
if (equaln(line.EndPoint.x, line.StartPoint.x))
|
|
|
|
|
{
|
|
|
|
|
if (line.PtOnCurve(center))
|
|
|
|
|
{
|
|
|
|
|
let pt1 = new Vector3(0, radius);
|
|
|
|
|
let pt2 = new Vector3(0, -radius);
|
|
|
|
|
pts.push(center.clone().add(pt1));
|
|
|
|
|
pts.push(center.clone().add(pt2));
|
|
|
|
|
return pts;
|
|
|
|
|
}
|
|
|
|
|
let closestArr = getClosestPt(Vec3DTo2D(line.StartPoint), Vec3DTo2D(line.EndPoint), 0, center);
|
|
|
|
|
if (closestArr.closestLen === radius)
|
|
|
|
|
{
|
|
|
|
|
pts.push(center.clone().add(closestArr.closestPt));
|
|
|
|
|
}
|
|
|
|
|
if (closestArr.closestLen < radius)
|
|
|
|
|
{
|
|
|
|
|
let y = Math.sqrt(Math.pow(radius, 2) - Math.pow(closestArr.closestLen, 2));
|
|
|
|
|
let pt1 = new Vector3(closestArr.closestPt.x, y);
|
|
|
|
|
let pt2 = new Vector3(closestArr.closestPt.x, -y);
|
|
|
|
|
pts.push(center.clone().add(pt1));
|
|
|
|
|
pts.push(center.clone().add(pt2));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
x1 = (b1 + tmp) / (2 * a);
|
|
|
|
|
y1 = k * x1 + b;
|
|
|
|
|
x2 = (b1 - tmp) / (2 * a);
|
|
|
|
|
y2 = k * x2 + b;
|
|
|
|
|
let pt1 = new Vector3(x1, y1, 0);
|
|
|
|
|
let pt2 = new Vector3(x2, y2, 0);
|
|
|
|
|
pts.push(pt1);
|
|
|
|
|
pts.push(pt2);
|
|
|
|
|
let k = (line.EndPoint.y - line.StartPoint.y) / (line.EndPoint.x - line.StartPoint.x);
|
|
|
|
|
let b = line.EndPoint.y - k * line.EndPoint.x;
|
|
|
|
|
//列方程
|
|
|
|
|
let x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
|
|
|
|
let c = Math.pow(center.x, 2) + Math.pow(b - center.y, 2) - Math.pow(radius, 2);
|
|
|
|
|
let a = (1 + Math.pow(k, 2));
|
|
|
|
|
let b1 = (2 * center.x - 2 * k * (b - center.y));
|
|
|
|
|
let tmp = Math.sqrt(b1 * b1 - 4 * a * c);
|
|
|
|
|
if (!isNaN(tmp))
|
|
|
|
|
{
|
|
|
|
|
x1 = (b1 + tmp) / (2 * a);
|
|
|
|
|
y1 = k * x1 + b;
|
|
|
|
|
x2 = (b1 - tmp) / (2 * a);
|
|
|
|
|
y2 = k * x2 + b;
|
|
|
|
|
let pt1 = new Vector3(x1, y1, 0);
|
|
|
|
|
let pt2 = new Vector3(x2, y2, 0);
|
|
|
|
|
pts.push(pt1);
|
|
|
|
|
if (!equal(pt1, pt2))//不重复原来的点
|
|
|
|
|
pts.push(pt2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return CheckPointOnCurve(pts, line, arc, intType);
|
|
|
|
|
|
|
|
|
|
return pts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//直线和圆
|
|
|
|
|
export function IntersectLineAndCircle(line: Line, circle: Circle, intType: IntersectOption)
|
|
|
|
|
{
|
|
|
|
|
let ptArr = this.IntersectLineAndCircleOrArc(line, circle.Center, circle.Radius);
|
|
|
|
|
return CheckPointOnCurve(ptArr, line, circle, intType);
|
|
|
|
|
}
|
|
|
|
|
//直线和圆弧
|
|
|
|
|
export function IntersectLineAndArc(line: Line, arc: Arc, intType: IntersectOption)
|
|
|
|
|
{
|
|
|
|
|
let ptArr = this.IntersectLineAndCircleOrArc(line, arc.Center, arc.Radius);
|
|
|
|
|
return CheckPointOnCurve(ptArr, line, arc, intType);
|
|
|
|
|
}
|
|
|
|
|
export function IntersectLineAndLine(l1: Line, l2: Line, intType: Intersect)
|
|
|
|
|
//直线和直线
|
|
|
|
|
export function IntersectLineAndLine(l1: Line, l2: Line, intType: IntersectOption)
|
|
|
|
|
{
|
|
|
|
|
let p1 = l1.StartPoint;
|
|
|
|
|
let p2 = l1.EndPoint;
|
|
|
|
@ -122,11 +222,3 @@ export function IntersectLineAndLine(l1: Line, l2: Line, intType: Intersect)
|
|
|
|
|
return CheckPointOnCurve(res, l1, l2, intType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function CheckPointOnCurve(pts: Vector3[], c1: Curve, c2: Curve, intType: Intersect): Array<Vector3>
|
|
|
|
|
{
|
|
|
|
|
return pts.filter(p =>
|
|
|
|
|
{
|
|
|
|
|
return (intType & 1 || c1.PtOnCurve(p)) && (intType & 2 || c2.PtOnCurve(p))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|