示例#1
0
        /// <summary>
        /// Shortest distance between triangle and point
        /// </summary>
        public double DistanceTo(Point3d p)
        {
            Point3d projection_point = p.ProjectionTo(this.ToPlane);

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

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

            int code = _PointLocation(projection_point);

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

            if (code >= 0)
            {
                return(p.DistanceTo(projection_point));
            }

            Segment3d AB = new Segment3d(this._a, this._b);
            Segment3d BC = new Segment3d(this._b, this._c);
            Segment3d AC = new Segment3d(this._a, this._c);

            double dist  = p.DistanceTo(AB);
            double dist2 = p.DistanceTo(BC);
            double dist3 = p.DistanceTo(AC);

            return(Min(dist, Min(dist2, dist3)));
        }
示例#2
0
 /// <summary>
 /// Orthogonal projection of the circle to line
 /// </summary>
 public Segment3d ProjectionTo(Line3d l)
 {
     double s = _r * Cos(l.AngleTo(this));
     Vector3d v = l.Direction.Normalized;
     Point3d p = _point.ProjectionTo(l);
     return new Segment3d(p.Translate(-s * v), p.Translate(s * v));
 }
示例#3
0
        /// <summary>
        /// Point on circle (including interior points) closest to target point "p".
        /// </summary>
        public Point3d ClosestPoint(Point3d p)
        {
            Point3d projection = p.ProjectionTo(this.ToPlane);

            if (projection.BelongsTo(this))
            {
                return(projection);
            }
            else
            {
                return(this.Center.Translate(this.R * new Vector3d(this.Center, projection).Normalized));
            }
        }
示例#4
0
        /// <summary>
        /// Shortest distance from point to circle (including interior points)
        /// </summary>
        public double DistanceTo(Point3d p)
        {
            Point3d projection = p.ProjectionTo(this.ToPlane);

            if (projection.BelongsTo(this))
            {
                return(projection.DistanceTo(p));
            }
            else
            {
                Point3d closest_point = this.Center.Translate(this.R * new Vector3d(this.Center, projection).Normalized);
                return(closest_point.DistanceTo(p));
            }
        }
示例#5
0
        /// <summary>
        /// Orthogonal projection of the ellipse to plane
        /// </summary>
        public Ellipse ProjectionTo(Plane3d s)
        {
            Point3d c = _point.ProjectionTo(s);
            Point3d q = _point.Translate(_v1).ProjectionTo(s);
            Point3d p = _point.Translate(_v2).ProjectionTo(s);

            Vector3d f1 = new Vector3d(c, p);
            Vector3d f2 = new Vector3d(c, q);

            double   t0 = 0.5 * Atan2(2 * f1 * f2, f1 * f1 - f2 * f2);
            Vector3d v1 = f1 * Cos(t0) + f2 * Sin(t0);
            Vector3d v2 = f1 * Cos(t0 + PI / 2) + f2 * Sin(t0 + PI / 2);

            return(new Ellipse(c, v1, v2));
        }
示例#6
0
        internal override int _PointLocation(Point3d p)
        {
            if (GeometRi3D.UseAbsoluteTolerance)
            {
                Plane3d s    = new Plane3d(this.A, this.Normal);
                Point3d proj = p.ProjectionTo(s);
                if (GeometRi3D.AlmostEqual(p.DistanceTo(proj), 0))
                {
                    if (p.BelongsTo(new Segment3d(_a, _b)) || p.BelongsTo(new Segment3d(_a, _c)) || p.BelongsTo(new Segment3d(_c, _b)))
                    {
                        return(0); // Point is on boundary
                    }
                    else
                    {
                        double area = this.Area;

                        double alpha = new Vector3d(proj, _b).Cross(new Vector3d(proj, _c)).Norm / (2 * area);
                        double beta  = new Vector3d(proj, _c).Cross(new Vector3d(proj, _a)).Norm / (2 * area);
                        double gamma = new Vector3d(proj, _a).Cross(new Vector3d(proj, _b)).Norm / (2 * area);

                        if (GeometRi3D.AlmostEqual(((alpha + beta + gamma) - 1.0) * (AB + BC + AC) / 3, 0.0))
                        {
                            return(1); // Point is strictly inside
                        }
                        else
                        {
                            return(-1);
                        }
                    }
                }
                else
                {
                    return(-1); // Point is outside
                }
            }
            else
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance            = tol * (AB + BC + AC) / 3;
                GeometRi3D.UseAbsoluteTolerance = true;
                int result = this._PointLocation(p);
                GeometRi3D.UseAbsoluteTolerance = false;
                GeometRi3D.Tolerance            = tol;
                return(result);
            }
        }
示例#7
0
        /// <summary>
        /// Calculates the point on the triangle closest to given point.
        /// </summary>
        public Point3d ClosestPoint(Point3d p)
        {
            Point3d projection_point = p.ProjectionTo(this.ToPlane);

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

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

            int code = _PointLocation(projection_point);

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

            if (code >= 0)
            {
                return(projection_point);
            }

            Segment3d AB = new Segment3d(this._a, this._b);
            Segment3d BC = new Segment3d(this._b, this._c);
            Segment3d AC = new Segment3d(this._a, this._c);

            double  dist          = p.DistanceTo(AB);
            Point3d closest_point = AB.ClosestPoint(p);
            double  dist2         = p.DistanceTo(BC);

            if (dist2 < dist)
            {
                dist          = dist2;
                closest_point = BC.ClosestPoint(p);
            }
            dist2 = p.DistanceTo(AC);
            if (dist2 < dist)
            {
                dist          = dist2;
                closest_point = AC.ClosestPoint(p);
            }

            return(closest_point);
        }
示例#8
0
        /// <summary>
        /// Point on segment closest to target point "p".
        /// </summary>
        public Point3d ClosestPoint(Point3d p)
        {
            Point3d projection_point = p.ProjectionTo(this.ToLine);

            if (projection_point.BelongsTo(this))
            {
                return(projection_point);
            }
            else
            {
                double dist1 = p.DistanceTo(this.P1);
                double dist2 = p.DistanceTo(this.P2);

                if (dist1 <= dist2)
                {
                    return(this.P1);
                }
                else
                {
                    return(this.P2);
                }
            }
        }
示例#9
0
 internal override int _PointLocation(Point3d p)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         Plane3d s    = new Plane3d(this.Center, this.Normal);
         Point3d proj = p.ProjectionTo(s);
         if (GeometRi3D.AlmostEqual(p.DistanceTo(proj), 0))
         {
             if (GeometRi3D.Smaller(p.DistanceTo(this.Center), this.R))
             {
                 return(1); // Point is strictly inside
             }
             else if (GeometRi3D.AlmostEqual(p.DistanceTo(this.Center), this.R))
             {
                 return(0); // Point is on boundary
             }
             else
             {
                 return(-1); // Point is outside
             }
         }
         else
         {
             return(-1); // Point is outside
         }
     }
     else
     {
         double tol = GeometRi3D.Tolerance;
         GeometRi3D.Tolerance            = tol * this.R;
         GeometRi3D.UseAbsoluteTolerance = true;
         int result = this._PointLocation(p);
         GeometRi3D.UseAbsoluteTolerance = false;
         GeometRi3D.Tolerance            = tol;
         return(result);
     }
 }
示例#10
0
 internal override int _PointLocation(Point3d p)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         Point3d proj = p.ProjectionTo(this.ToLine);
         if (GeometRi3D.AlmostEqual(p.DistanceTo(proj), 0))
         {
             if (GeometRi3D.AlmostEqual(p.DistanceTo(this.P1), 0) || GeometRi3D.AlmostEqual(p.DistanceTo(this.P2), 0))
             {
                 return(0); // Point is on boundary
             }
             else if (Abs(new Vector3d(proj, this.P1).AngleTo(new Vector3d(proj, this.P2))) < 2e-8)
             // Need to decrease accuracy due to Acos calculations
             {
                 return(-1); // Point is outside
             }
             else
             {
                 return(1); // // Point is strictly inside
             }
         }
         else
         {
             return(-1); // Point is outside
         }
     }
     else
     {
         double tol = GeometRi3D.Tolerance;
         GeometRi3D.Tolerance            = tol * this.Length;
         GeometRi3D.UseAbsoluteTolerance = true;
         int result = this._PointLocation(p);
         GeometRi3D.UseAbsoluteTolerance = false;
         GeometRi3D.Tolerance            = tol;
         return(result);
     }
 }
示例#11
0
        /// <summary>
        /// Orthogonal projection of the triangle to line
        /// </summary>
        public Segment3d ProjectionTo(Line3d l)
        {
            double  d12, d23, d13;
            Point3d p1, p2, p3;

            p1  = _a.ProjectionTo(l);
            p2  = _b.ProjectionTo(l);
            p3  = _c.ProjectionTo(l);
            d12 = p1.DistanceTo(p2);
            d13 = p1.DistanceTo(p3);
            d23 = p2.DistanceTo(p3);
            if (d12 >= d13 && d12 >= d23)
            {
                return(new Segment3d(p1, p2));
            }
            else if (d13 >= d23)
            {
                return(new Segment3d(p1, p3));
            }
            else
            {
                return(new Segment3d(p2, p3));
            }
        }
示例#12
0
 internal override int _PointLocation(Point3d p)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         Point3d proj = p.ProjectionTo(this.ToLine);
         if (GeometRi3D.AlmostEqual(p.DistanceTo(proj), 0))
         {
             if (GeometRi3D.AlmostEqual(p.DistanceTo(this._p1), 0) || GeometRi3D.AlmostEqual(p.DistanceTo(this._p2), 0))
             {
                 return(0); // Point is on boundary
             }
             else if (Abs(new Vector3d(proj, this._p1).Normalized.AngleTo(new Vector3d(proj, this._p2).Normalized)) < PI / 2)
             {
                 return(-1); // Point is outside
             }
             else
             {
                 return(1); // // Point is strictly inside
             }
         }
         else
         {
             return(-1); // Point is outside
         }
     }
     else
     {
         double tol = GeometRi3D.Tolerance;
         GeometRi3D.Tolerance            = tol * this.Length;
         GeometRi3D.UseAbsoluteTolerance = true;
         int result = this._PointLocation(p);
         GeometRi3D.UseAbsoluteTolerance = false;
         GeometRi3D.Tolerance            = tol;
         return(result);
     }
 }
示例#13
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));
        }