/// <summary> /// Get intersection of plane with sphere. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Circle3d'. /// </summary> public object IntersectionWith(Plane3d s) { s.SetCoord(this.Center.Coord); double d1 = s.A * this.X + s.B * this.Y + s.C * this.Z + s.D; double d2 = Math.Pow(s.A, 2) + Math.Pow(s.B, 2) + Math.Pow(s.C, 2); double d = Abs(d1) / Sqrt(d2); if (d > this.R + GeometRi3D.Tolerance) { return(null); } else { double Xc = this.X - s.A * d1 / d2; double Yc = this.Y - s.B * d1 / d2; double Zc = this.Z - s.C * d1 / d2; if (Abs(d - this.R) < GeometRi3D.Tolerance) { return(new Point3d(Xc, Yc, Zc, this.Center.Coord)); } else { double R = Sqrt(Math.Pow(this.R, 2) - Math.Pow(d, 2)); return(new Circle3d(new Point3d(Xc, Yc, Zc, this.Center.Coord), R, s.Normal)); } } }
/// <summary> /// Get intersection of line with plane. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Line3d'. /// </summary> public virtual object IntersectionWith(Plane3d s) { Vector3d r1 = this.Point.ToVector; Vector3d s1 = this.Direction; Vector3d n2 = s.Normal; if (Abs(s1 * n2) < GeometRi3D.Tolerance) { // Line and plane are parallel if (this.Point.BelongsTo(s)) { // Line lies in the plane return(this); } else { return(null); } } else { // Intersection point s.SetCoord(r1.Coord); r1 = r1 - ((r1 * n2) + s.D) / (s1 * n2) * s1; return(r1.ToPoint); } }
/// <summary> /// Returns orthogonal projection of the point to the plane /// </summary> public Point3d ProjectionTo(Plane3d s) { Vector3d r0 = new Vector3d(this, _coord); s.SetCoord(this.Coord); Vector3d n = new Vector3d(s.A, s.B, s.C, _coord); r0 = r0 - (r0 * n + s.D) / (n * n) * n; return(r0.ToPoint); }
/// <summary> /// Finds the common intersection of three planes. /// Return 'null' (no common intersection) or object of type 'Point3d', 'Line3d' or 'Plane3d' /// </summary> public object IntersectionWith(Plane3d s2, Plane3d s3) { // Set all planes to global CS this.SetCoord(Coord3d.GlobalCS); s2.SetCoord(Coord3d.GlobalCS); s3.SetCoord(Coord3d.GlobalCS); double det = new Matrix3d(new[] { A, B, C }, new[] { s2.A, s2.B, s2.C }, new [] { s3.A, s3.B, s3.C }).Det; if (Abs(det) < GeometRi3D.Tolerance) { if (this.Normal.IsParallelTo(s2.Normal) && this.Normal.IsParallelTo(s3.Normal)) { // Planes are coplanar if (this.Point.BelongsTo(s2) && this.Point.BelongsTo(s3)) { return(this); } else { return(null); } } if (this.Normal.IsNotParallelTo(s2.Normal) && this.Normal.IsNotParallelTo(s3.Normal)) { // Planes are not parallel // Find the intersection (Me,s2) and (Me,s3) and check if it is the same line Line3d l1 = (Line3d)this.IntersectionWith(s2); Line3d l2 = (Line3d)this.IntersectionWith(s3); if (l1 == l2) { return(l1); } else { return(null); } } // Two planes are parallel, third plane is not return(null); } else { double x = -new Matrix3d(new[] { D, B, C }, new[] { s2.D, s2.B, s2.C }, new[] { s3.D, s3.B, s3.C }).Det / det; double y = -new Matrix3d(new[] { A, D, C }, new[] { s2.A, s2.D, s2.C }, new[] { s3.A, s3.D, s3.C }).Det / det; double z = -new Matrix3d(new[] { A, B, D }, new[] { s2.A, s2.B, s2.D }, new[] { s3.A, s3.B, s3.D }).Det / det; return(new Point3d(x, y, z)); } }
/// <summary> /// <para>Test if point is located in the epsilon neighborhood of the plane.</para> /// <para>Epsilon neighborhood is defined by a GeometRi3D.Tolerance property.</para> /// </summary> public bool BelongsTo(Plane3d s) { s.SetCoord(this.Coord); if (GeometRi3D.UseAbsoluteTolerance) { return(Abs(s.A * X + s.B * Y + s.C * Z + s.D) / Sqrt(s.A * s.A + s.B * s.B + s.C * s.C) < GeometRi3D.Tolerance); } else { double d = this.DistanceTo(this._coord.Origin); if (d > 0.0) { return(Abs(s.A * X + s.B * Y + s.C * Z + s.D) / Sqrt(s.A * s.A + s.B * s.B + s.C * s.C) / d < GeometRi3D.Tolerance); } else { return(Abs(s.A * X + s.B * Y + s.C * Z + s.D) / Sqrt(s.A * s.A + s.B * s.B + s.C * s.C) < GeometRi3D.Tolerance); } } }
/// <summary> /// Intersection of ellipsoid with plane. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Ellipse'. /// </summary> public object IntersectionWith(Plane3d plane) { // Solution 1: // Peter Paul Klein // On the Ellipsoid and Plane Intersection Equation // Applied Mathematics, 2012, 3, 1634-1640 (DOI:10.4236/am.2012.311226) // Solution 2: // Sebahattin Bektas // Intersection of an Ellipsoid and a Plane // International Journal of Research in Engineering and Applied Sciences, VOLUME 6, ISSUE 6 (June, 2016) Coord3d lc = new Coord3d(_point, _v1, _v2, "LC1"); plane.SetCoord(lc); double Ax, Ay, Az, Ad; double a, b, c; if (Abs(plane.C) >= Abs(plane.A) && Abs(plane.C) >= Abs(plane.B)) { a = this.A; b = this.B; c = this.C; } else { lc = new Coord3d(_point, _v2, _v3, "LC2"); plane.SetCoord(lc); if (Abs(plane.C) >= Abs(plane.A) && Abs(plane.C) >= Abs(plane.B)) { a = this.B; b = this.C; c = this.A; } else { lc = new Coord3d(_point, _v3, _v1, "LC3"); plane.SetCoord(lc); a = this.C; b = this.A; c = this.B; } } Ax = plane.A; Ay = plane.B; Az = plane.C; Ad = plane.D; double tmp = (Az * Az * c * c); double AA = 1.0 / (a * a) + Ax * Ax / tmp; double BB = 2.0 * Ax * Ay / tmp; double CC = 1.0 / (b * b) + Ay * Ay / tmp; double DD = 2.0 * Ax * Ad / tmp; double EE = 2.0 * Ay * Ad / tmp; double FF = Ad * Ad / tmp - 1.0; double det = 4.0 * AA * CC - BB * BB; if (GeometRi3D.AlmostEqual(det, 0)) { return(null); } double X0 = (BB * EE - 2 * CC * DD) / det; double Y0 = (BB * DD - 2 * AA * EE) / det; double Z0 = -(Ax * X0 + Ay * Y0 + Ad) / Az; Point3d P0 = new Point3d(X0, Y0, Z0, lc); if (P0.IsOnBoundary(this)) { // the plane is tangent to ellipsoid return(P0); } else if (P0.IsInside(this)) { Vector3d q = P0.ToVector.ConvertTo(lc); Matrix3d D1 = Matrix3d.DiagonalMatrix(1 / a, 1 / b, 1 / c); Vector3d r = plane.Normal.ConvertTo(lc).OrthogonalVector.Normalized; Vector3d s = plane.Normal.ConvertTo(lc).Cross(r).Normalized; double omega = 0; double qq, qr, qs, rr, ss, rs; if (!GeometRi3D.AlmostEqual((D1 * r) * (D1 * s), 0)) { rr = (D1 * r) * (D1 * r); rs = (D1 * r) * (D1 * s); ss = (D1 * s) * (D1 * s); if (GeometRi3D.AlmostEqual(rr - ss, 0)) { omega = PI / 4; } else { omega = 0.5 * Atan(2.0 * rs / (rr - ss)); } Vector3d rprim = Cos(omega) * r + Sin(omega) * s; Vector3d sprim = -Sin(omega) * r + Cos(omega) * s; r = rprim; s = sprim; } qq = (D1 * q) * (D1 * q); qr = (D1 * q) * (D1 * r); qs = (D1 * q) * (D1 * s); rr = (D1 * r) * (D1 * r); ss = (D1 * s) * (D1 * s); double d = qq - qr * qr / rr - qs * qs / ss; AA = Sqrt((1 - d) / rr); BB = Sqrt((1 - d) / ss); return(new Ellipse(P0, AA * r, BB * s)); } else { return(null); } }
/// <summary> /// Returns shortest distance from point to the plane /// </summary> public double DistanceTo(Plane3d s) { s.SetCoord(this.Coord); return(Abs(X * s.A + Y * s.B + Z * s.C + s.D) / Sqrt(s.A * s.A + s.B * s.B + s.C * s.C)); }