Exemple #1
0
 /// <summary>
 /// Check if point belongs to the circle
 /// </summary>
 /// <returns>True, if the point belongs to the circle</returns>
 public bool BelongsTo(Circle3d c)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         return(GeometRi3D.AlmostEqual(this.DistanceTo(c.Center), c.R) && c.Normal.Normalized.IsOrthogonalTo(new Vector3d(c.Center, this)));
     }
     else
     {
         return(GeometRi3D.AlmostEqual((this.DistanceTo(c.Center) - c.R) / c.R, 0.0) &&
                c.Normal.Normalized.IsOrthogonalTo(new Vector3d(c.Center, this)));
     }
 }
Exemple #2
0
        /// <summary>
        /// Shortest distance from box to circle
        /// </summary>
        public double DistanceTo(Circle3d c)
        {
            if (c.Center.IsInside(this))
            {
                return(0);
            }
            double min_dist = Double.PositiveInfinity;

            foreach (Triangle triangle in ListOfTriangles)
            {
                double dist = c.DistanceTo(triangle);
                if (dist < min_dist)
                {
                    min_dist = dist;
                }
            }
            return(min_dist);
        }
        /// <summary>
        /// Shortest distance between two circles (including interior points) (approximate solution)
        /// </summary>
        public double DistanceTo(Circle3d c)
        {
            if (this.Normal.IsParallelTo(c.Normal))
            {
                Point3d projection = c.Center.ProjectionTo(this.ToPlane);
                double  dist       = projection.DistanceTo(this.Center);
                double  vdist      = projection.DistanceTo(c.Center);
                if (dist < this.R + c.R)
                {
                    return(vdist);
                }
                else
                {
                    return(Sqrt((dist - this.R - c.R) * (dist - this.R - c.R) + vdist * vdist));
                }
            }

            double tol  = GeometRi3D.Tolerance;
            bool   mode = GeometRi3D.UseAbsoluteTolerance;

            GeometRi3D.Tolerance            = GeometRi3D.DefaultTolerance;
            GeometRi3D.UseAbsoluteTolerance = true;

            object obj = this.IntersectionWith(c);

            if (obj != null)
            {
                // Restore initial state
                GeometRi3D.UseAbsoluteTolerance = mode;
                GeometRi3D.Tolerance            = tol;

                return(0);
            }

            Point3d p1_1, p1_2, p2_1, p2_2;
            double  dist1 = _distance_cicle_to_circle(this, c, out p1_1, out p1_2);
            double  dist2 = _distance_cicle_to_circle(c, this, out p2_1, out p2_2);

            // Restore initial state
            GeometRi3D.UseAbsoluteTolerance = mode;
            GeometRi3D.Tolerance            = tol;

            return(Min(dist1, dist2));
        }
Exemple #4
0
        /// <summary>
        /// Determines whether two objects are equal.
        /// </summary>
        public override bool Equals(object obj)
        {
            if (obj == null || (!object.ReferenceEquals(this.GetType(), obj.GetType())))
            {
                return(false);
            }
            Circle3d c = (Circle3d)obj;

            if (GeometRi3D.UseAbsoluteTolerance)
            {
                return(c.Center == this.Center && Abs(c.R - this.R) <= GeometRi3D.Tolerance && c.Normal.IsParallelTo(this.Normal));
            }
            else
            {
                return(Abs(c.Center.DistanceTo(this.Center)) / this.R <= GeometRi3D.Tolerance &&
                       Abs(c.R - this.R) / this.R <= GeometRi3D.Tolerance &&
                       c.Normal.IsParallelTo(this.Normal));
            }
        }
Exemple #5
0
        /// <summary>
        /// Intersection check between circle and box
        /// </summary>
        public bool Intersects(Circle3d c)
        {
            if (c.Center.IsInside(this))
            {
                return(true);
            }
            if (c.Center.DistanceTo(this) > c.R)
            {
                return(false);
            }

            foreach (Triangle triangle in ListOfTriangles)
            {
                if (c.Intersects(triangle))
                {
                    return(true);
                }
            }
            return(false);
        }
        /// <summary>
        /// Shortest distance between two circles (including interior points) (approximate solution)
        /// <para> The output points may be not unique in case of intersecting objects.</para>
        /// </summary>
        /// <param name="s">Target sphere</param>
        /// <param name="p1">Closest point on circle</param>
        /// <param name="p2">Closest point on sphere</param>
        public double DistanceTo(Sphere s, out Point3d p1, out Point3d p2)
        {
            Plane3d p = this.ToPlane;

            if (s.Center.ProjectionTo(p).BelongsTo(this))
            {
                p1 = s.Center.ProjectionTo(p);
                if (s.Center == p1)
                {
                    p2 = s.Center.Translate(s.R * this.Normal.Normalized);
                }
                else
                {
                    p2 = s.Center.Translate(s.R * new Vector3d(s.Center, p1).Normalized);
                }
                return(s.DistanceTo(p));
            }

            if (this.Intersects(s))
            {
                Object obj = s.IntersectionWith(p);
                if (obj.GetType() == typeof(Point3d))
                {
                    p1 = (Point3d)obj;
                    p2 = p1;
                }
                else
                {
                    Circle3d c = (Circle3d)obj;
                    p1 = this.Center.Translate(this.R * new Vector3d(this.Center, c.Center).Normalized);
                    p2 = c.Center.Translate(c.R * new Vector3d(c.Center, this.Center).Normalized);
                }
                return(0);
            }

            double dist = _distance_cicle_to_sphere(this, s, out p1, out p2);

            return(dist);
        }
Exemple #7
0
        /// <summary>
        /// Intersection check between circle and box
        /// </summary>
        public bool Intersects(Circle3d c)
        {
            //if (c.Center.IsInside(this)) return true;
            double dist = c._point.DistanceTo(this);

            if (dist > c.R)
            {
                return(false);
            }
            if (dist < GeometRi3D.Tolerance)
            {
                return(true);
            }

            foreach (Triangle triangle in ListOfTriangles)
            {
                if (c.Intersects(triangle))
                {
                    return(true);
                }
            }
            return(false);
        }
Exemple #8
0
 /// <summary>
 /// Check if point is inside circle
 /// </summary>
 /// <returns>True, if the point is inside circle</returns>
 public bool IsInside(Circle3d c)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         if (this.BelongsTo(new Plane3d(c.Center, c.Normal)))
         {
             return(GeometRi3D.Smaller(this.DistanceTo(c.Center), c.R));
         }
         else
         {
             return(false);
         }
     }
     else
     {
         double tol = GeometRi3D.Tolerance;
         GeometRi3D.Tolerance            = tol * c.R;
         GeometRi3D.UseAbsoluteTolerance = true;
         bool result = this.IsInside(c);
         GeometRi3D.UseAbsoluteTolerance = false;
         GeometRi3D.Tolerance            = tol;
         return(result);
     }
 }
Exemple #9
0
 /// <summary>
 /// Closest point on circle (including interior points).
 /// </summary>
 public Point3d ClosestPoint(Circle3d c)
 {
     return(c.ClosestPoint(this));
 }
Exemple #10
0
        private double _distance_cicle_to_circle(Circle3d c1, Circle3d c2, out Point3d p1, out Point3d p2)
        // Use quadratic interpolation to find closest point on one circle to other
        // p1 and p2 - closest points on both circles
        {
            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;
            bool flag = false;

            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)
                // Possible special case, non-smooth function ( f(t)=|t| )
                {
                    flag = true;
                    break;
                }

                if (t > t2 & t < t1)
                {
                    t3 = t1; d3 = d1;
                }
                else
                {
                    t2 = t1; d2 = d1;
                }
                t1 = t; d1 = d;
            }

            if (flag)
            // Possible special case, non-smooth function ( f(t)=|t| )
            {
                while (d2 - d1 > 0.2 * GeometRi3D.DefaultTolerance && d1 > GeometRi3D.DefaultTolerance)
                {
                    if (++iter > 100)
                    {
                        break;
                    }

                    double t = (t2 + t1) / 2;
                    p = c1.ParametricForm(t);
                    double d = p.DistanceTo(c2);
                    if (d < d1)
                    {
                        t3 = t1; d3 = d1;
                        t1 = t;  d1 = d;
                    }
                    else
                    {
                        t2 = t; d2 = d;
                    }

                    t = (t3 + t1) / 2;
                    p = c1.ParametricForm(t);
                    d = p.DistanceTo(c2);
                    if (d < d1)
                    {
                        t2 = t1; d2 = d1;
                        t1 = t; d1 = d;
                    }
                    else
                    {
                        t3 = t; d3 = d;
                    }
                }
            }

            p1 = c1.ParametricForm(t1);
            p2 = c2.ClosestPoint(p1);
            return(d1);
        }
Exemple #11
0
        /// <summary>
        /// Intersection of two circles.
        /// Returns 'null' (no intersection) or object of type 'Circle3d', 'Point3d' or 'Segment3d'.
        /// In 2D (coplanar circles) the segment will define two intersection points.
        /// </summary>
        public object IntersectionWith(Circle3d c)
        {
            // Relative tolerance ================================
            if (!GeometRi3D.UseAbsoluteTolerance)
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance            = tol * Max(this.R, c.R);
                GeometRi3D.UseAbsoluteTolerance = true;
                object result = this.IntersectionWith(c);
                GeometRi3D.UseAbsoluteTolerance = false;
                GeometRi3D.Tolerance            = tol;
                return(result);
            }
            //====================================================

            if (this.Normal.IsParallelTo(c.Normal))
            {
                if (this.Center.BelongsTo(new Plane3d(c.Center, c.Normal)))
                {
                    // Coplanar objects
                    // Search 2D intersection of two circles

                    // Equal circles
                    if (this.Center == c.Center && GeometRi3D.AlmostEqual(this.R, c.R))
                    {
                        return(this.Copy());
                    }

                    double d = this.Center.DistanceTo(c.Center);

                    // Separated circles
                    if (GeometRi3D.Greater(d, this.R + c.R))
                    {
                        return(null);
                    }

                    // One circle inside the other
                    if (d < Abs(this.R - c.R) - GeometRi3D.Tolerance)
                    {
                        return(null);
                    }

                    // Outer tangency
                    if (GeometRi3D.AlmostEqual(d, this.R + c.R))
                    {
                        Vector3d vec = new Vector3d(this.Center, c.Center);
                        return(this.Center.Translate(this.R * vec.Normalized));
                    }

                    // Inner tangency
                    if (Abs(Abs(this.R - c.R) - d) < GeometRi3D.Tolerance)
                    {
                        Vector3d vec = new Vector3d(this.Center, c.Center);
                        if (this.R > c.R)
                        {
                            return(this.Center.Translate(this.R * vec.Normalized));
                        }
                        else
                        {
                            return(this.Center.Translate(-this.R * vec.Normalized));
                        }
                    }

                    // intersecting circles
                    // Create local CS with origin in circle's center
                    Vector3d vec1     = new Vector3d(this.Center, c.Center);
                    Vector3d vec2     = vec1.Cross(this.Normal);
                    Coord3d  local_cs = new Coord3d(this.Center, vec1, vec2);

                    double  x  = 0.5 * (d * d - c.R * c.R + this.R * this.R) / d;
                    double  y  = 0.5 * Sqrt((-d + c.R - this.R) * (-d - c.R + this.R) * (-d + c.R + this.R) * (d + c.R + this.R)) / d;
                    Point3d p1 = new Point3d(x, y, 0, local_cs);
                    Point3d p2 = new Point3d(x, -y, 0, local_cs);
                    return(new Segment3d(p1, p2));
                }
                else
                {
                    // parallel objects
                    return(null);
                }
            }
            else
            {
                // Check 3D intersection
                Plane3d plane = new Plane3d(this.Center, this.Normal);
                object  obj   = plane.IntersectionWith(c);

                if (obj == null)
                {
                    return(null);
                }
                else if (obj.GetType() == typeof(Point3d))
                {
                    Point3d p = (Point3d)obj;
                    if (p.BelongsTo(c))
                    {
                        return(p);
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    Segment3d s = (Segment3d)obj;
                    return(s.IntersectionWith(this));
                }
            }
        }
 /// <summary>
 /// Intersection of circle with plane.
 /// Returns 'null' (no intersection) or object of type 'Circle3d', 'Point3d' or 'Segment3d'.
 /// </summary>
 public object IntersectionWith(Circle3d c)
 {
     return(c.IntersectionWith(this));
 }
 /// <summary>
 /// Shortest distance between plane and circle (including interior points)
 /// </summary>
 /// <param name="c">Target circle</param>
 /// <param name="point_on_plane">Closest point on plane</param>
 /// <param name="point_on_circle">Closest point on circle</param>
 public double DistanceTo(Circle3d c, out Point3d point_on_plane, out Point3d point_on_circle)
 {
     return(c.DistanceTo(this, out point_on_circle, out point_on_plane));
 }
 /// <summary>
 /// Distance from plane to circle
 /// </summary>
 public double DistanceTo(Circle3d c)
 {
     return(c.DistanceTo(this));
 }
Exemple #15
0
 /// <summary>
 /// Shortest distance between sphere and circle (including interior points) (approximate solution).
 /// <para> The output points may be not unique in case of intersecting objects.</para>
 /// </summary>
 /// <param name="c">Target circle</param>
 /// <param name="p1">Closest point on sphere</param>
 /// <param name="p2">Closest point on circle</param>
 public double DistanceTo(Circle3d c, out Point3d p1, out Point3d p2)
 {
     return(c.DistanceTo(this, out p2, out p1));
 }
Exemple #16
0
 /// <summary>
 /// Intersection check between circle and triangle
 /// </summary>
 public bool Intersects(Circle3d c)
 {
     return(c.Intersects(this));
 }
Exemple #17
0
        /// <summary>
        /// Shortest distance between triangle and circle (including interior points)
        /// </summary>
        public double DistanceTo(Circle3d c)
        {
            Point3d point_on_circle, point_on_triangle;

            return(c.DistanceTo(this, out point_on_circle, out point_on_triangle));
        }
Exemple #18
0
        /// <summary>
        /// Shortest distance between two circles (including interior points) (approximate solution)
        /// <para> The output points may be not unique in case of parallel or intersecting circles.</para>
        /// </summary>
        /// <param name="c">Target circle</param>
        /// <param name="p1">Closest point on source circle</param>
        /// <param name="p2">Closest point on target circle</param>
        public double DistanceTo(Circle3d c, out Point3d p1, out Point3d p2)
        {
            if (this.Normal.IsParallelTo(c.Normal))
            {
                Point3d projection = c.Center.ProjectionTo(this.ToPlane);
                double  dist       = projection.DistanceTo(this.Center);
                double  vdist      = projection.DistanceTo(c.Center);
                if (dist < this.R + c.R)
                {
                    if (projection.BelongsTo(this))
                    {
                        p1 = projection;
                        p2 = c.Center;
                    }
                    else
                    {
                        p1 = this.Center.Translate(this.R * new Vector3d(this.Center, projection).Normalized);
                        p2 = p1.ProjectionTo(c.ToPlane);
                    }
                    return(vdist);
                }
                else
                {
                    Vector3d v = new Vector3d(this.Center, projection).Normalized;
                    p1 = this.Center.Translate(this.R * v);
                    p2 = c.Center.Translate(-c.R * v);
                    return(Sqrt((dist - this.R - c.R) * (dist - this.R - c.R) + vdist * vdist));
                }
            }

            double tol  = GeometRi3D.Tolerance;
            bool   mode = GeometRi3D.UseAbsoluteTolerance;

            GeometRi3D.Tolerance            = GeometRi3D.DefaultTolerance;
            GeometRi3D.UseAbsoluteTolerance = true;

            object obj = this.IntersectionWith(c);

            if (obj != null)
            {
                // Restore initial state
                GeometRi3D.UseAbsoluteTolerance = mode;
                GeometRi3D.Tolerance            = tol;

                if (obj.GetType() == typeof(Point3d))
                {
                    p1 = (Point3d)obj;
                    p2 = (Point3d)obj;
                }
                else if (obj.GetType() == typeof(Segment3d))
                {
                    p1 = ((Segment3d)obj).P1;
                    p2 = ((Segment3d)obj).P1;
                }
                else
                {
                    p1 = ((Circle3d)obj).Center;
                    p2 = ((Circle3d)obj).Center;
                }

                return(0);
            }

            Point3d p1_1, p1_2, p2_1, p2_2;
            double  dist1 = _distance_cicle_to_circle(this, c, out p1_1, out p1_2);
            double  dist2 = _distance_cicle_to_circle(c, this, out p2_1, out p2_2);

            // Restore initial state
            GeometRi3D.UseAbsoluteTolerance = mode;
            GeometRi3D.Tolerance            = tol;

            if (dist1 < dist2)
            {
                p1 = p1_1;
                p2 = p1_2;
            }
            else
            {
                p1 = p2_2;
                p2 = p2_1;
            }
            return(Min(dist1, dist2));
        }
Exemple #19
0
 /// <summary>
 /// Shortest distance between segment and circle (including interior points)
 /// </summary>
 /// <param name="c">Target circle</param>
 /// <param name="point_on_segment">Closest point on segment</param>
 /// <param name="point_on_circle">Closest point on circle</param>
 public double DistanceTo(Circle3d c, out Point3d point_on_segment, out Point3d point_on_circle)
 {
     return(c.DistanceTo(this, out point_on_circle, out point_on_segment));
 }
Exemple #20
0
 /// <summary>
 /// Intersection check between segment and circle
 /// </summary>
 public bool Intersects(Circle3d c)
 {
     return(this.IntersectionWith(c) != null);
 }
Exemple #21
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);
        }