diff --git a/src/Add-on/Extends.ts b/src/Add-on/Extends.ts index f13a15131..ea244976a 100644 --- a/src/Add-on/Extends.ts +++ b/src/Add-on/Extends.ts @@ -1,7 +1,7 @@ import { Command } from "../Editor/CommandMachine"; import { SelectSet } from "../Editor/SelectSet"; import { Curve } from "../DatabaseServices/Curve"; -import { Intersect } from "../GraphicsSystem/IntersectWith"; +import { IntersectOption } from "../GraphicsSystem/IntersectWith"; export class Command_Extend implements Command { @@ -23,7 +23,7 @@ export class Command_Extend implements Command for (let j = i + 1; j < cus.length; j++) { let cu2 = cus[j]; - let pts = cu1.IntersectWith(cu2, Intersect.ExtendBoth); + let pts = cu1.IntersectWith(cu2, IntersectOption.ExtendBoth); for (let p of pts) { cu1.Extend(cu1.GetParamAtPoint(p)); diff --git a/src/Add-on/Fillet.ts b/src/Add-on/Fillet.ts index cde26dfec..e2214ab73 100644 --- a/src/Add-on/Fillet.ts +++ b/src/Add-on/Fillet.ts @@ -8,7 +8,7 @@ import { Line } from '../DatabaseServices/Line'; import { Command } from '../Editor/CommandMachine'; import { PromptEntityResult, PromptStatus } from '../Editor/PromptResult'; import { angle, midPoint } from '../Geometry/GeUtils'; -import { Intersect } from '../GraphicsSystem/IntersectWith'; +import { IntersectOption } from '../GraphicsSystem/IntersectWith'; enum FilletState { Invalid = -1, Normal, Parallel, RadiousInvalid } export class CommandFillet implements Command @@ -36,7 +36,7 @@ export class CommandFillet implements Command let cu2 = enRes2.Entity as Curve; //求交点 - let in_pts = cu1.IntersectWith(cu2, Intersect.ExtendBoth); + let in_pts = cu1.IntersectWith(cu2, IntersectOption.ExtendBoth); if (in_pts.length === 0) return; //裁剪. 尖角化 @@ -55,7 +55,7 @@ export class CommandFillet implements Command let off_cu2 = this.OffsetCurve(new_cu2, new_cu1, this.m_radious); //圆心 - let center = off_cu1.IntersectWith(off_cu2, Intersect.ExtendBoth)[0]; + let center = off_cu1.IntersectWith(off_cu2, IntersectOption.ExtendBoth)[0]; //圆弧点1 let arcP1 = new_cu1.GetClosestPointTo(center, true); if (!new_cu1.PtOnCurve(arcP1)) diff --git a/src/Add-on/Trim.ts b/src/Add-on/Trim.ts index 0a03b7284..03b74a531 100644 --- a/src/Add-on/Trim.ts +++ b/src/Add-on/Trim.ts @@ -1,7 +1,7 @@ import { Command } from "../Editor/CommandMachine"; import { SelectSet, SelectType } from "../Editor/SelectSet"; import { Curve } from "../DatabaseServices/Curve"; -import { Intersect } from "../GraphicsSystem/IntersectWith"; +import { IntersectOption } from "../GraphicsSystem/IntersectWith"; import { app } from "../ApplicationServices/Application"; import { PromptStatus } from "../Editor/PromptResult"; import { SelectPick } from "../Editor/SelectPick"; @@ -78,7 +78,7 @@ export class Command_Trim implements Command for (let icu of cus) { if (icu != cu) - inPts.push(...cu.IntersectWith(icu, Intersect.OnBothOperands)); + inPts.push(...cu.IntersectWith(icu, IntersectOption.OnBothOperands)); } //打断. @@ -114,10 +114,9 @@ export class Command_Trim implements Command let breakCus = lastCu.GetSplitCurves(breakParams); if (breakCus.length === 2) { - if (breakParams[0] == 0) - { + let mindP = breakCu.GetPointAtParam(0.5); + if (breakCus[0].PtOnCurve(mindP)) lastCu = breakCus[1]; - } else lastCu = breakCus[0]; } @@ -133,7 +132,13 @@ export class Command_Trim implements Command continue; } } - cu.CopyFrom(lastCu); + if (cu.constructor.name === lastCu.constructor.name) + cu.CopyFrom(lastCu); + else + { + cu.Erase(); + app.m_Database.ModelSpace.Append(lastCu); + } } } diff --git a/src/Common/CurveUtils.ts b/src/Common/CurveUtils.ts index 5efe6919d..ec0b4ac41 100644 --- a/src/Common/CurveUtils.ts +++ b/src/Common/CurveUtils.ts @@ -154,7 +154,8 @@ export function getCurveLength(startPt: Vector2, endPt: Vector2, bul: number) { let line = endPt.clone().sub(startPt); dist = line.length(); - } else + } + else { let arcData = getArcData(startPt, endPt, bul); // 圆心角 @@ -237,6 +238,12 @@ export function getClosestPt(startPt: Vector2, endPt: Vector2, bul: number, pt: if (bul === 0) { let angle = sToPtLine.angleTo(sToELine); + if (isNaN(angle)) + { + closestPt = pt; + closestLen = closestPt.distanceTo(pt); + return { closestPt, closestLen } + } let len = sToPtLine.length() * Math.cos(angle); segment = len / curveLen; } @@ -253,9 +260,6 @@ export function getClosestPt(startPt: Vector2, endPt: Vector2, bul: number, pt: } closestPt = getPointAtParam(startPt, endPt, bul, segment); closestLen = closestPt.distanceTo(pt); - return { - closestPt, closestLen - } - + return { closestPt, closestLen } } diff --git a/src/DatabaseServices/Arc.ts b/src/DatabaseServices/Arc.ts index e2b35b372..8fc0d4113 100644 --- a/src/DatabaseServices/Arc.ts +++ b/src/DatabaseServices/Arc.ts @@ -1,18 +1,16 @@ -import { Box3, Matrix4, ShapeGeometry, Vector3 } from 'three'; import * as THREE from 'three'; - +import { Box3, Matrix4, ShapeGeometry, Vector3 } from 'three'; import { ColorMaterial } from '../Common/ColorPalette'; -import { getArcAngle, isAtArc, Vec3DTo2D } from '../Common/CurveUtils'; -import { equal, polar, angle } from '../Geometry/GeUtils'; +import { getArcAngle, isAtArc, rotateLine, Vec3DTo2D } from '../Common/CurveUtils'; +import { equal, equaln, polar, angle } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; -import { Intersect, IntersectArcAndArc } from '../GraphicsSystem/IntersectWith'; +import { IntersectOption, IntersectArcAndArc, IntersectCircleAndArc, IntersectLineAndArc } from '../GraphicsSystem/IntersectWith'; import { Factory } from './CADFactory'; import { CADFile } from './CADFile'; +import { Circle } from './Circle'; import { Curve } from './Curve'; import { Line } from './Line'; - - @Factory export class Arc extends Curve { @@ -199,20 +197,17 @@ export class Arc extends Curve return dist; } - // GetFistDeriv(param: number | Vector3) - // { - // if (typeof (param) === "number") - // { - // param = this.GetPointAtParam(param); - // } - // let fistDeriv = -((param.x - this.m_Center.x) / (param.y - this.m_Center.y)) || 0; - // if (equaln(param.x, this.m_Center.x)) - // { - // fistDeriv = 1; - // } - // return fistDeriv; - // } - + GetParamAtPoint(pt: Vector3) + { + if (!this.PtOnCurve(pt)) + { + return NaN; + } + let pmAtPt: number = 0; + let length = this.GetDistAtPoint(pt); + pmAtPt = this.GetParamAtDist(length); + return pmAtPt; + } GetSplitCurves(param: number[] | number) { let anglelist = new Array(); @@ -222,23 +217,21 @@ export class Arc extends Curve { for (let pm of param) { - anglelist.push(this.GetParamAngle(pm)); + anglelist.push(this.GetParamAngle(1 - pm)); } } else { - anglelist.push(this.GetParamAngle(param)); + anglelist.push(this.GetParamAngle(1 - param)); } anglelist.push(this.m_EndAngle); for (let i = 0; i < anglelist.length - 1; i++) { - let arc = new Arc(); - arc.m_Center = this.m_Center; - arc.m_Radius = this.m_Radius; - arc.m_Normal = this.m_Normal; - arc.m_StartAngle = anglelist[i]; - arc.m_EndAngle = anglelist[i + 1]; - curvelist.push(arc); + if (!equaln(anglelist[i], anglelist[i + 1])) + { + let arc = new Arc(this.m_Center, this.m_Radius, anglelist[i], anglelist[i + 1], this.m_Normal); + curvelist.push(arc); + } } return curvelist; } @@ -265,12 +258,7 @@ export class Arc extends Curve let arcArr = new Array(); if ((offsetDist + this.m_Radius) > 0) { - let arc = new Arc(); - arc.m_Center = this.m_Center; - arc.m_Radius = this.m_Radius + offsetDist; - arc.m_Normal = this.m_Normal; - arc.m_StartAngle = this.m_StartAngle; - arc.m_EndAngle = this.m_EndAngle; + let arc = new Arc(this.m_Center, this.m_Radius + offsetDist, this.m_StartAngle, this.m_EndAngle, this.m_Normal); arcArr.push(arc); } return arcArr; @@ -299,12 +287,20 @@ export class Arc extends Curve [this.m_StartAngle, this.m_EndAngle] = [this.m_EndAngle, this.m_StartAngle]; } - IntersectWith(curve: Curve, intType: Intersect): Vector3[] + IntersectWith(curve: Curve, intType: IntersectOption): Vector3[] { if (curve instanceof Arc) { return IntersectArcAndArc(this, curve, intType); } + if (curve instanceof Line) + { + return IntersectLineAndArc(curve, this, intType); + } + if (curve instanceof Circle) + { + return IntersectCircleAndArc(curve, this, intType); + } return []; } @@ -496,13 +492,6 @@ export class Arc extends Curve } } } - GetParamAtPoint(pt: Vector3) - { - let pmAtPt: number = 0; - let length = this.GetDistAtPoint(pt); - pmAtPt = this.GetParamAtDist(length); - return pmAtPt; - } GetParamAtDist(d: number) { @@ -530,12 +519,12 @@ export class Arc extends Curve let l = new Line(this.Center, pt); if (extend) { - let pts = l.IntersectWith(this, Intersect.ExtendBoth); + let pts = l.IntersectWith(this, IntersectOption.ExtendBoth); return pt.distanceTo(pts[0]) < pt.distanceTo(pts[1]) ? pts[0] : pts[1]; } //单向延伸可能有两个,一个,和0个交点 - let pts = l.IntersectWith(this, Intersect.ExtendThis); + let pts = l.IntersectWith(this, IntersectOption.ExtendThis); switch (pts.length) { case 0: diff --git a/src/DatabaseServices/Circle.ts b/src/DatabaseServices/Circle.ts index 93c6a5556..e62116821 100644 --- a/src/DatabaseServices/Circle.ts +++ b/src/DatabaseServices/Circle.ts @@ -1,15 +1,22 @@ -import { EllipseCurve, Geometry, Matrix4, Vector3 } from 'three'; import * as THREE from 'three'; +import { Box3, EllipseCurve, Geometry, Matrix4, Vector3 } from 'three'; import { ColorMaterial } from '../Common/ColorPalette'; +import { rotateLine } from '../Common/CurveUtils'; +import { Arc } from '../DatabaseServices/Arc'; +import { angle, angleTo, equaln, polar } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; +import +{ + IntersectOption, + IntersectCircleAndArc, + IntersectCircleAndCircle, + IntersectLineAndCircle, +} from '../GraphicsSystem/IntersectWith'; import { Factory } from './CADFactory'; import { CADFile } from './CADFile'; import { Curve } from './Curve'; -import { angle, polar } from '../Geometry/GeUtils'; import { Line } from './Line'; -import { Intersect } from '../GraphicsSystem/IntersectWith'; - @Factory export class Circle extends Curve @@ -42,6 +49,166 @@ export class Circle extends Curve this.m_Radius = v <= 0 ? 1e-19 : v; this.Update(); } + //******************** Curve function start*****************// + + get Area() + { + return Math.PI * Math.pow(this.m_Radius, 2); + } + get Length() + { + return Math.PI * 2 * this.m_Radius; + } + + GetPointAtParam(param: number) + { + let ptAtPm = new Vector3(); + polar(ptAtPm, param * 2 * Math.PI, this.m_Radius); + ptAtPm = this.m_Center.clone().add(ptAtPm); + return ptAtPm; + } + + GetPointAtDistance(distance: number) + { + let ptAtDist = new Vector3(); + let param = distance / (Math.PI * 2 * this.m_Radius); + ptAtDist = this.GetPointAtParam(param); + return ptAtDist; + } + + GetDistAtParam(param: number) + { + let distAtPm: number = 0; + distAtPm = Math.PI * 2 * this.m_Radius * param; + return distAtPm; + } + + GetDistAtPoint(pt: Vector3) + { + let distAtPt: number = 0; + let param = this.GetParamAtPoint(pt); + distAtPt = this.GetDistAtParam(param); + return distAtPt; + } + + GetParamAtDist(d: number) + { + let pmAtDist: number = 0; + pmAtDist = d / (Math.PI * 2 * this.m_Radius); + return pmAtDist; + } + + GetSplitCurves(param: number[] | number) + { + let anglelist = new Array(); + let curvelist = new Array(); + if (param instanceof Array) + { + for (let pm of param) + { + anglelist.push(2 * Math.PI * pm); + } + } + else + { + anglelist.push(2 * Math.PI * param); + } + for (let i = 0; i < anglelist.length - 1; i++) + { + let arc = new Arc(this.m_Center, this.m_Radius, anglelist[i], anglelist[i + 1]); + curvelist.push(arc); + } + + let arc = new Arc(this.m_Center, this.m_Radius, anglelist[anglelist.length - 1], anglelist[0]); + curvelist.push(arc); + + return curvelist; + } + + GetParamAtPoint(pt?: Vector3) + { + if (!pt) + { + return; + } + let pmAtPt: number = 0; + let startPt = new Vector3(0, 0, 0); + polar(startPt, 0, this.m_Radius); + startPt = this.m_Center.clone().add(startPt); + //求出向量 + let p1 = new Vector3(0, 0, 0); + p1.x = pt.x - this.m_Center.x; + p1.y = pt.y - this.m_Center.y; + let p2 = new Vector3(0, 0, 0); + p2.x = startPt.x - this.m_Center.x; + p2.y = startPt.y - this.m_Center.y; + + pmAtPt = angleTo(p2, p1); + if (pmAtPt < 0) + { + pmAtPt = 2 * Math.PI + pmAtPt; + } + pmAtPt = pmAtPt / (2 * Math.PI); + return pmAtPt; + } + + PtOnCurve(pt: Vector3) + { + let isOnCircle = false; + let dist = pt.distanceTo(this.m_Center); + if (equaln(dist, this.m_Radius)) + { + isOnCircle = true; + } + return isOnCircle; + } + GetOffsetCurves(offsetDist: number) + { + let arcArr = new Array(); + if ((offsetDist + this.m_Radius) > 0) + { + let circle = new Circle(this.m_Center, this.m_Radius + offsetDist); + arcArr.push(circle); + } + return arcArr; + } + + getangle(pt1: Vector3, pt2: Vector3) + { + let x = pt1.x - pt2.x; + let y = pt1.y - pt2.y; + return Math.atan2(y, x); + } + IntersectWith(curve: Curve, intType: IntersectOption): Vector3[] + { + if (curve instanceof Arc) + { + return IntersectCircleAndArc(this, curve, intType); + } + if (curve instanceof Line) + { + return IntersectLineAndCircle(curve, this, intType); + } + if (curve instanceof Circle) + { + return IntersectCircleAndCircle(this, curve, intType); + } + return []; + } + + //******************** Curve function end*****************// + + get BoundingBox(): Box3 + { + let pts = [ + this.Center.add(new Vector3(this.m_Radius, 0)), + this.Center.add(new Vector3(0, this.m_Radius)), + this.Center.add(new Vector3(-this.m_Radius, 0)), + this.Center.add(new Vector3(0, -this.m_Radius)), + ]; + return new Box3().setFromPoints(pts); + } + Draw(renderType: RenderType): THREE.Object3D { let obj = super.Draw(renderType); @@ -144,7 +311,7 @@ export class Circle extends Curve GetClosestPointTo(pt: Vector3, extend: boolean): Vector3 { let l = new Line(this.Center, pt); - let pts = l.IntersectWith(this, Intersect.ExtendBoth); + let pts = l.IntersectWith(this, IntersectOption.ExtendBoth); let ptIns = pt.distanceTo(pts[0]) < pt.distanceTo(pts[1]) ? pts[0] : pts[1]; return ptIns; diff --git a/src/DatabaseServices/Curve.ts b/src/DatabaseServices/Curve.ts index 73f7b2807..2bbae02dc 100644 --- a/src/DatabaseServices/Curve.ts +++ b/src/DatabaseServices/Curve.ts @@ -1,6 +1,6 @@ import { Vector3 } from 'three'; -import { Intersect } from '../GraphicsSystem/IntersectWith'; +import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { Factory } from './CADFactory'; import { Entity } from './Entity'; @@ -85,6 +85,6 @@ export abstract class Curve extends Entity * @returns {Vector3[]} * @memberof Curve */ - IntersectWith(curve: Curve, intType: Intersect): Vector3[] { return; } + IntersectWith(curve: Curve, intType: IntersectOption): Vector3[] { return; } } diff --git a/src/DatabaseServices/Entity.ts b/src/DatabaseServices/Entity.ts index 388ca9304..7e4c1659a 100644 --- a/src/DatabaseServices/Entity.ts +++ b/src/DatabaseServices/Entity.ts @@ -2,7 +2,7 @@ import * as THREE from 'three'; import { Matrix4, Vector3, Mesh, Box3 } from 'three'; import { RenderType } from '../GraphicsSystem/Enum'; -import { Intersect } from '../GraphicsSystem/IntersectWith'; +import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { Factory } from './CADFactory'; import { CADFile } from './CADFile'; import { CADObject } from './CADObject'; @@ -130,7 +130,7 @@ export class Entity extends CADObject { } - IntersectWith(curve: Entity, intType: Intersect): Vector3[] { return; } + IntersectWith(curve: Entity, intType: IntersectOption): Vector3[] { return; } //#region -------------------------File------------------------- diff --git a/src/DatabaseServices/Line.ts b/src/DatabaseServices/Line.ts index 983164571..135c9202a 100644 --- a/src/DatabaseServices/Line.ts +++ b/src/DatabaseServices/Line.ts @@ -5,11 +5,12 @@ import * as THREE from 'three'; import { ColorMaterial } from '../Common/ColorPalette'; import { equal, polar } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; -import { Intersect, IntersectLineAndArc, IntersectLineAndLine } from '../GraphicsSystem/IntersectWith'; +import { IntersectOption, IntersectLineAndArc, IntersectLineAndLine, IntersectLineAndCircle } from '../GraphicsSystem/IntersectWith'; import { Arc } from './Arc'; import { Factory } from './CADFactory'; import { CADFile } from './CADFile'; import { Curve } from './Curve'; +import { Circle } from './Circle'; @Factory export class Line extends Curve @@ -88,7 +89,7 @@ export class Line extends Curve this.Update(); } - IntersectWith(curve: Curve, intType: Intersect): Vector3[] + IntersectWith(curve: Curve, intType: IntersectOption): Vector3[] { if (curve instanceof Line) { @@ -98,6 +99,10 @@ export class Line extends Curve { return IntersectLineAndArc(this, curve, intType); } + if (curve instanceof Circle) + { + return IntersectLineAndCircle(this, curve, intType); + } //其他的尚未实现. return []; } @@ -196,7 +201,7 @@ export class Line extends Curve let an = this.GetFistDerivAngle(0) + Math.PI * 0.5; let line = new Line(pt, polar(pt.clone(), an, 1)); //交点 - let pt_int = this.IntersectWith(line, Intersect.ExtendBoth)[0]; + let pt_int = this.IntersectWith(line, IntersectOption.ExtendBoth)[0]; if (extend) return pt_int; //参数 let param = this.GetParamAtPoint(pt_int); diff --git a/src/GraphicsSystem/IntersectWith.ts b/src/GraphicsSystem/IntersectWith.ts index e0816c82e..ba4c357b9 100644 --- a/src/GraphicsSystem/IntersectWith.ts +++ b/src/GraphicsSystem/IntersectWith.ts @@ -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} + */ +function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, intType: IntersectOption): Array +{ + 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 -{ - return pts.filter(p => - { - return (intType & 1 || c1.PtOnCurve(p)) && (intType & 2 || c2.PtOnCurve(p)) - }) -}