private double _distance_cicle_to_sphere(Circle3d c1, Sphere c2, out Point3d p1, out Point3d p2) // Use quadratic interpolation to find closest point on circle // p1 and p2 - closest points on circle and sphere respectively { double d1 = 1e20; double t1 = 0; Point3d p; for (int i = 0; i < 16; i++) { double t = i * Math.PI / 8; p = c1.ParametricForm(t); double dist = p.DistanceTo(c2); if (dist < d1) { d1 = dist; t1 = t; } } double t2 = t1 - Math.PI / 8; p = c1.ParametricForm(t2); double d2 = p.DistanceTo(c2); double t3 = t1 + Math.PI / 8; p = c1.ParametricForm(t3); double d3 = p.DistanceTo(c2); int iter = 0; while (d2 - d1 > 0.2 * GeometRi3D.DefaultTolerance && d1 > GeometRi3D.DefaultTolerance) { if (++iter > 100) { break; } double ax = 2.0 * d1 / (t1 - t2) / (t1 - t3); double aa = 0.5 * ax * (t2 + t3); double bx = 2.0 * d2 / (t2 - t1) / (t2 - t3); double bb = 0.5 * bx * (t1 + t3); double cx = 2.0 * d3 / (t3 - t1) / (t3 - t2); double cc = 0.5 * cx * (t1 + t2); double t = (aa + bb + cc) / (ax + bx + cx); p = c1.ParametricForm(t); double d = p.DistanceTo(c2); if (d < d1) { if (t > t2 & t < t1) { t3 = t1; d3 = d1; } else { t2 = t1; d2 = d1; } t1 = t; d1 = d; } else { if (t < t1) { t2 = t; d2 = d; } else { t3 = t; d3 = d; } } } p1 = c1.ParametricForm(t1); p2 = c2.ClosestPoint(p1); return(d1); }
/// <summary> /// Get intersection of ray with sphere. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Segment3d'. /// </summary> public object IntersectionWith(Sphere s) { return(s.IntersectionWith(this)); }
/// <summary> /// Get intersection of two spheres. /// Returns 'null' (no intersection) or object of type 'Point3d' or 'Circle3d'. /// </summary> public object IntersectionWith(Sphere s) { // Relative tolerance ================================ if (!GeometRi3D.UseAbsoluteTolerance) { double tol = GeometRi3D.Tolerance; GeometRi3D.Tolerance = tol * Max(this.R, s.R); GeometRi3D.UseAbsoluteTolerance = true; object result = this.IntersectionWith(s); GeometRi3D.UseAbsoluteTolerance = false; GeometRi3D.Tolerance = tol; return(result); } //==================================================== Point3d p = s.Center.ConvertTo(this.Center.Coord); double Dist = Sqrt(Math.Pow((this.X - p.X), 2) + Math.Pow((this.Y - p.Y), 2) + Math.Pow((this.Z - p.Z), 2)); // Separated spheres if (Dist > this.R + s.R + GeometRi3D.Tolerance) { return(null); } // One sphere inside the other if (Dist < Abs(this.R - s.R) - GeometRi3D.Tolerance) { return(null); } // Intersection plane double A = 2 * (p.X - this.X); double B = 2 * (p.Y - this.Y); double C = 2 * (p.Z - this.Z); double D = Math.Pow(this.X, 2) - Math.Pow(p.X, 2) + Math.Pow(this.Y, 2) - Math.Pow(p.Y, 2) + Math.Pow(this.Z, 2) - Math.Pow(p.Z, 2) - Math.Pow(this.R, 2) + Math.Pow(s.R, 2); // Intersection center double t = (this.X * A + this.Y * B + this.Z * C + D) / (A * (this.X - p.X) + B * (this.Y - p.Y) + C * (this.Z - p.Z)); double x = this.X + t * (p.X - this.X); double y = this.Y + t * (p.Y - this.Y); double z = this.Z + t * (p.Z - this.Z); // Outer tangency if (Abs(this.R + s.R - D) < GeometRi3D.Tolerance) { return(new Point3d(x, y, z, this.Center.Coord)); } // Inner tangency if (Abs(Abs(this.R - s.R) - D) < GeometRi3D.Tolerance) { return(new Point3d(x, y, z, this.Center.Coord)); } // Intersection double alpha = Acos((Math.Pow(this.R, 2) + Math.Pow(Dist, 2) - Math.Pow(s.R, 2)) / (2 * this.R * Dist)); double R = this.R * Sin(alpha); Vector3d v = new Vector3d(this.Center, s.Center); return(new Circle3d(new Point3d(x, y, z, this.Center.Coord), R, v)); }