예제 #1
0
        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);
        }
예제 #2
0
 /// <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));
 }
예제 #3
0
        /// <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));
        }