diff --git a/__test__/Geometry/__snapshots__/arc.test.ts.snap b/__test__/Geometry/__snapshots__/arc.test.ts.snap index 3643cd4e5..8ab969e41 100644 --- a/__test__/Geometry/__snapshots__/arc.test.ts.snap +++ b/__test__/Geometry/__snapshots__/arc.test.ts.snap @@ -2,25 +2,33 @@ exports[`三点共线 1`] = ` Vector3 { - "x": 0, - "y": 0, + "x": -49999.99999499999, + "y": 1.0000000000015987, "z": 0, } `; -exports[`三点共线 2`] = `0`; +exports[`三点共线 2`] = `6.283165307179587`; -exports[`三点共线 3`] = `1.5707963267948966`; +exports[`三点共线 3`] = `0.000019999999999301362`; -exports[`三点共线 4`] = `0`; +exports[`三点共线 4`] = `50000.000004999994`; exports[`三点同一位置 1`] = `0`; exports[`三点同一位置 2`] = `0`; -exports[`三点圆心 1`] = `3.141592653589793`; +exports[`三点圆心 1`] = ` +Array [ + 5, + 0, + 0, +] +`; + +exports[`三点圆心 2`] = `3.141592653589793`; -exports[`三点圆心 2`] = `0`; +exports[`三点圆心 3`] = `0`; exports[`圆弧偏移 1`] = ` Vector3 { diff --git a/__test__/Geometry/arc.test.ts b/__test__/Geometry/arc.test.ts index 2975a04d2..e5f6895ec 100644 --- a/__test__/Geometry/arc.test.ts +++ b/__test__/Geometry/arc.test.ts @@ -27,7 +27,7 @@ test("三点圆心", () => new Vector3(5, 5, 0), new Vector3(10, 0, 0) ); - expect(arc.Center.toArray()).toMatchObject([5, 0, 0]); + expect(arc.Center.toArray()).toMatchSnapshot(); expect(arc.StartAngle).toMatchSnapshot(); expect(arc.EndAngle).toMatchSnapshot(); }); diff --git a/src/Common/CurveUtils.ts b/src/Common/CurveUtils.ts index e1d08de6b..0d94fe472 100644 --- a/src/Common/CurveUtils.ts +++ b/src/Common/CurveUtils.ts @@ -34,11 +34,9 @@ export function getCircleCenter(pt1: Vector3, pt2: Vector3, pt3: Vector3) let temp = A1 * B2 - A2 * B1; let center = new Vector3(); //判断三点是否共线 - if (temp === 0) + if (equaln(temp, 0, 1e-5)) { - //共线则将第一个点pt1作为圆心 - center.x = pt1.x; - center.y = pt1.y; + return; } else { diff --git a/src/DatabaseServices/Entity/Arc.ts b/src/DatabaseServices/Entity/Arc.ts index e4310e416..fc020d587 100644 --- a/src/DatabaseServices/Entity/Arc.ts +++ b/src/DatabaseServices/Entity/Arc.ts @@ -1,6 +1,6 @@ import { Box3, Matrix3, Matrix4, Vector2, Vector3 } from 'three'; import { getArcOrCirNearPts, getCircleCenter, GetTanPtsOnArcOrCircle } from '../../Common/CurveUtils'; -import { reviseMirrorMatrix, SetMtxVector } from '../../Common/Matrix4Utils'; +import { reviseMirrorMatrix, SetMtxVector, TransformVector } from '../../Common/Matrix4Utils'; import { Status } from '../../Common/Status'; import { ObjectSnapMode } from '../../Editor/ObjectSnapMode'; import { Box3Ext } from '../../Geometry/Box'; @@ -598,7 +598,7 @@ export class Arc extends Curve FromThreePoint(pt1: Vector3, pt2: Vector3, pt3: Vector3) { if (!(pt1 && pt2 && pt3)) - return; + return this; let ocsInv = this.OCSInv; pt1 = pt1.clone().applyMatrix4(ocsInv).setZ(0); @@ -606,6 +606,12 @@ export class Arc extends Curve pt3 = pt3.clone().applyMatrix4(ocsInv).setZ(0); let center = getCircleCenter(pt1, pt2, pt3); + if (!center) + { + this.ParseFromBul(pt1.applyMatrix4(this.OCSNoClone), pt3.applyMatrix4(this.OCSNoClone), 1e-5);//faker line + return this; + }; + this.Center = center.clone().applyMatrix4(this.OCS); //用圆心和其中一个点求距离得到半径: this._Radius = center.distanceTo(pt1); @@ -672,16 +678,49 @@ export class Arc extends Curve if (indexList.length > 0) { this.WriteAllObjectRecord(); - let ptsArr = this.GetGripPoints(); let index = indexList[0]; - let p = ptsArr[index]; - if (p) + + if (index > 2) + this.Center = this.Center.add(vec); + else { - p.add(vec); - if (index > 2) - this.Center = this.Center.add(vec); - else - this.FromThreePoint(ptsArr[0], ptsArr[1], ptsArr[2]); + let p1 = polar(new Vector3, this._StartAngle, this._Radius); + let p2 = polar(new Vector3, this.GetAngleAtParam(0.5), this._Radius); + let p3 = polar(new Vector3, this._EndAngle, this._Radius); + + vec = TransformVector(vec.clone(), this.OCSInv).setZ(0); + + [p1, p2, p3][index].add(vec); + + let center = getCircleCenter(p1, p2, p3); + if (!center)//三点共线 使用faker arc + { + this.ParseFromBul(p1.applyMatrix4(this.OCSNoClone), p3.applyMatrix4(this.OCSNoClone), 1e-5); + this.Update(); + return; + } + + //起始角度 端点角度 + this._StartAngle = angle(p1.clone().sub(center)); + this._EndAngle = angle(p3.clone().sub(center)); + if (equaln(this._StartAngle, this._EndAngle, 1e-5))//差不多也是三点共线,只不过逃逸了 + { + this.ParseFromBul(p1.applyMatrix4(this.OCSNoClone), p3.applyMatrix4(this.OCSNoClone), 1e-5); + this.Update(); + return; + } + + //用圆心和其中一个点求距离得到半径: + this._Radius = center.distanceTo(p1); + + this.Center = center.clone().applyMatrix4(this.OCS); + + //求出向量p1->p2,p1->p3 + let v1 = p2.clone().sub(p1); + let v2 = p3.clone().sub(p1); + + this._Clockwise = v1.cross(v2).z < 0; + this.Update(); } } diff --git a/src/DatabaseServices/Room/Entity/Wall/RoomWallArc.ts b/src/DatabaseServices/Room/Entity/Wall/RoomWallArc.ts index 2b7db46a6..067254e05 100644 --- a/src/DatabaseServices/Room/Entity/Wall/RoomWallArc.ts +++ b/src/DatabaseServices/Room/Entity/Wall/RoomWallArc.ts @@ -110,23 +110,14 @@ export class RoomWallArc extends RoomWallBase pts.push(pts[i].clone().setZ(pts[i].z + this._Height)); return pts; } + MoveGripPoints(indexList: Array, vec: Vector3) { if (indexList.length > 0) { - this.WriteAllObjectRecord(); - let ptsArr = this.GetGripPoints(); let index = indexList[0]; - let p = ptsArr[index]; - if (p) - { - p.add(vec); - if (index > 2) - this.Center = this.Center.add(vec); - else - this.FromThreePoint(ptsArr[0], ptsArr[1], ptsArr[2]); - this.Update(); - } + if (index >= 4) index -= 4; + Arc.prototype.MoveGripPoints.call(this, [index], vec); } }