Пример #1
0
        /// <summary>
        /// Check if two objects are orthogonal
        /// </summary>
        public bool IsOrthogonalTo(ILinearObject obj)
        {
            Vector3d v = obj.Direction;

            if ((this._coord != v._coord))
            {
                v = v.ConvertTo(this._coord);
            }

            double this_norm = this.Norm;
            double v_norm    = v.Norm;

            if (GeometRi3D.UseAbsoluteTolerance)
            {
                if (GeometRi3D.Greater(this_norm, 0.0) && GeometRi3D.Greater(v_norm, 0.0))
                {
                    return(GeometRi3D.AlmostEqual(Abs(this * v), 0.0));
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                if (this_norm > 0.0 && v_norm > 0.0)
                {
                    return(GeometRi3D.AlmostEqual(Abs(this * v) / (this_norm * v_norm), 0.0));
                }
                else
                {
                    return(false);
                }
            }
        }
Пример #2
0
 internal int _AxialPointLocation(Point3d p)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         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(p, this._p1).Normalized.AngleTo(new Vector3d(p, this._p2).Normalized)) < PI / 2)
         {
             return(-1); // Point is outside
         }
         else
         {
             return(1); // // Point is strictly inside
         }
     }
     else
     {
         double tol = GeometRi3D.Tolerance;
         GeometRi3D.Tolerance            = tol * this.Length;
         GeometRi3D.UseAbsoluteTolerance = true;
         int result = this._AxialPointLocation(p);
         GeometRi3D.UseAbsoluteTolerance = false;
         GeometRi3D.Tolerance            = tol;
         return(result);
     }
 }
Пример #3
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);
            }
            Box3d b = (Box3d)obj;

            if (GeometRi3D.UseAbsoluteTolerance)
            {
                return(this.Center == b.Center && _r == b.Orientation &&
                       GeometRi3D.AlmostEqual(L1, b.L1) &&
                       GeometRi3D.AlmostEqual(L2, b.L2) &&
                       GeometRi3D.AlmostEqual(L3, b.L3));
            }
            else
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance            = tol * this.Diagonal;
                GeometRi3D.UseAbsoluteTolerance = true;
                bool result = this.Equals(b);
                GeometRi3D.UseAbsoluteTolerance = false;
                GeometRi3D.Tolerance            = tol;
                return(result);
            }
        }
Пример #4
0
        internal override int _PointLocation(Point3d p)
        {
            Coord3d lc = new Coord3d(this.Center, this.SemiaxisA, this.SemiaxisB);

            p = p.ConvertTo(lc);

            if (GeometRi3D.UseAbsoluteTolerance)
            {
                double dist = this.ClosestPoint(p).DistanceTo(p);
                if (GeometRi3D.AlmostEqual(dist, 0))
                {
                    return(0); // Point is on boundary
                }
                if (GeometRi3D.Smaller(p.X * p.X / (A * A) + p.Y * p.Y / (B * B) + p.Z * p.Z / (C * C), 1.0))
                {
                    return(1); // Point is strictly inside box
                }

                return(-1); // Point is outside
            }
            else
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance            = tol * this.A;
                GeometRi3D.UseAbsoluteTolerance = true;
                int result = this._PointLocation(p);
                GeometRi3D.UseAbsoluteTolerance = false;
                GeometRi3D.Tolerance            = tol;
                return(result);
            }
        }
Пример #5
0
        /// <summary>
        /// Point on axis aligned box (including interior points) closest to target point "p".
        /// </summary>
        public Point3d AABBClosestPoint(Point3d p)
        {
            p = p.ConvertToGlobal();
            double x = GeometRi3D.Clamp(p.X, this._center.X - _lx / 2, this._center.X + _lx / 2);
            double y = GeometRi3D.Clamp(p.Y, this._center.Y - _ly / 2, this._center.Y + _ly / 2);
            double z = GeometRi3D.Clamp(p.Z, this._center.Z - _lz / 2, this._center.Z + _lz / 2);

            return(new Point3d(x, y, z));
        }
Пример #6
0
        /// <summary>
        /// Intersection of circle with plane.
        /// Returns 'null' (no intersection) or object of type 'Circle3d', 'Point3d' or 'Segment3d'.
        /// </summary>
        public object IntersectionWith(Plane3d s)
        {

            // Relative tolerance ================================
            if (!GeometRi3D.UseAbsoluteTolerance)
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance = tol * this.R;
                GeometRi3D.UseAbsoluteTolerance = true;
                object result = this.IntersectionWith(s);
                GeometRi3D.UseAbsoluteTolerance = false;
                GeometRi3D.Tolerance = tol;
                return result;
            }
            //====================================================

            if (this.Normal.IsParallelTo(s.Normal))
            {
                if (this.Center.BelongsTo(s))
                {
                    // coplanar objects
                    return this.Copy();
                }
                else
                {
                    // parallel objects
                    return null;
                }
            }
            else
            {
                Line3d l = (Line3d)s.IntersectionWith(new Plane3d(this.Center, this.Normal));
                Coord3d local_coord = new Coord3d(this.Center, l.Direction, this.Normal.Cross(l.Direction));
                Point3d p = l.Point.ConvertTo(local_coord);

                if (GeometRi3D.Greater(Abs(p.Y), this.R))
                {
                    return null;
                }
                else if (GeometRi3D.AlmostEqual(p.Y, this.R))
                {
                    return new Point3d(0, this.R, 0, local_coord);
                }
                else if (GeometRi3D.AlmostEqual(p.Y, -this.R))
                {
                    return new Point3d(0, -this.R, 0, local_coord);
                }
                else
                {
                    double d = Sqrt(Math.Pow(this.R, 2) - Math.Pow(p.Y, 2));
                    Point3d p1 = new Point3d(-d, p.Y, 0, local_coord);
                    Point3d p2 = new Point3d(d, p.Y, 0, local_coord);
                    return new Segment3d(p1, p2);
                }
            }

        }
Пример #7
0
        //////////////////////////////////////////

        #region "ParallelMethods"
        /// <summary>
        /// Check if two objects are parallel
        /// </summary>
        public bool IsParallelTo(ILinearObject obj)
        {
            Vector3d v = obj.Direction;

            if ((this._coord != v._coord))
            {
                v = v.ConvertTo(this._coord);
            }

            return(GeometRi3D.AlmostEqual(this.Normalized.Cross(v.Normalized).Norm, 0.0));
        }
Пример #8
0
        /// <summary>
        /// Point on box (including interior points) closest to target point "p".
        /// </summary>
        public Point3d ClosestPoint(Point3d p)
        {
            Coord3d local_coord = this.LocalCoord();

            p = p.ConvertTo(local_coord);
            double x = GeometRi3D.Clamp(p.X, -_lx / 2, _lx / 2);
            double y = GeometRi3D.Clamp(p.Y, -_ly / 2, _ly / 2);
            double z = GeometRi3D.Clamp(p.Z, -_lz / 2, _lz / 2);

            return(new Point3d(x, y, z, local_coord));
        }
Пример #9
0
 /// <summary>
 /// Check if point belongs to the sphere surface
 /// </summary>
 /// <returns>True, if the point belongs to the sphere surface</returns>
 public bool BelongsTo(Sphere s)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         return(GeometRi3D.AlmostEqual(this.DistanceTo(s.Center), s.R));
     }
     else
     {
         return(GeometRi3D.AlmostEqual((this.DistanceTo(s.Center) - s.R) / s.R, 0.0));
     }
 }
Пример #10
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)));
     }
 }
Пример #11
0
        /// <summary>
        /// Check if two objects are orthogonal
        /// </summary>
        public bool IsOrthogonalTo(ILinearObject obj)
        {
            Vector3d v = obj.Direction;

            if ((this._coord != v._coord))
            {
                v = v.ConvertTo(this._coord);
            }

            double this_norm = this.Norm;
            double v_norm    = v.Norm;

            return(GeometRi3D.AlmostEqual(Abs(this * v) / (this_norm * v_norm), 0.0));
        }
Пример #12
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);
            }
        }
Пример #13
0
        /// <summary>
        /// Intersection of circle with plane.
        /// Returns 'null' (no intersection) or object of type 'Circle3d', 'Point3d' or 'Segment3d'.
        /// </summary>
        public object IntersectionWith(Plane3d s)
        {
            if (this.Normal.IsParallelTo(s.Normal))
            {
                if (this.Center.BelongsTo(s))
                {
                    // coplanar objects
                    return(this.Copy());
                }
                else
                {
                    // parallel objects
                    return(null);
                }
            }
            else
            {
                Line3d  l           = (Line3d)s.IntersectionWith(new Plane3d(this.Center, this.Normal));
                Coord3d local_coord = new Coord3d(this.Center, l.Direction, this.Normal.Cross(l.Direction));
                Point3d p           = l.Point.ConvertTo(local_coord);

                if (GeometRi3D.Greater(Abs(p.Y), this.R))
                {
                    return(null);
                }
                else if (GeometRi3D.AlmostEqual(p.Y, this.R))
                {
                    return(new Point3d(0, this.R, 0, local_coord));
                }
                else if (GeometRi3D.AlmostEqual(p.Y, -this.R))
                {
                    return(new Point3d(0, -this.R, 0, local_coord));
                }
                else
                {
                    double  d  = Sqrt(Math.Pow(this.R, 2) - Math.Pow(p.Y, 2));
                    Point3d p1 = new Point3d(-d, p.Y, 0, local_coord);
                    Point3d p2 = new Point3d(d, p.Y, 0, local_coord);
                    return(new Segment3d(p1, p2));
                }
            }
        }
Пример #14
0
        /// <summary>
        /// Check if point is inside ellipsoid
        /// </summary>
        public bool IsInside(Ellipsoid e)
        {
            Coord3d lc = new Coord3d(e.Center, e.SemiaxisA, e.SemiaxisB);
            Point3d p  = this.ConvertTo(lc);

            if (GeometRi3D.UseAbsoluteTolerance)
            {
                return(GeometRi3D.Smaller(p.X * p.X / e.A / e.A + p.Y * p.Y / e.B / e.B + p.Z * p.Z / e.C / e.C, 1.0));
            }
            else
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance            = tol * e.SemiaxisA.Norm;
                GeometRi3D.UseAbsoluteTolerance = true;
                bool result = this.IsInside(e);
                GeometRi3D.UseAbsoluteTolerance = false;
                GeometRi3D.Tolerance            = tol;
                return(result);
            }
        }
Пример #15
0
        //////////////////////////////////////////

        #region "ParallelMethods"
        /// <summary>
        /// Check if two objects are parallel
        /// </summary>
        public bool IsParallelTo(ILinearObject obj)
        {
            Vector3d v = obj.Direction;

            if ((this._coord != v._coord))
            {
                v = v.ConvertTo(this._coord);
            }

            double this_norm = this.Norm;
            double v_norm    = v.Norm;

            if (GeometRi3D.Greater(this_norm, 0.0) && GeometRi3D.Greater(v_norm, 0.0))
            {
                return(GeometRi3D.AlmostEqual(this.Normalized.Cross(v.Normalized).Norm, 0.0));
            }
            else
            {
                return(false);
            }
        }
Пример #16
0
        /// <summary>
        /// Calculates the point on the ellipse's boundary closest to given point.
        /// </summary>
        public Point3d ClosestPoint(Point3d p)
        {
            // Algorithm by Dr. Robert Nurnberg
            // http://wwwf.imperial.ac.uk/~rn/distance2ellipse.pdf
            // Does not work for interior points

            Coord3d local_coord = new Coord3d(this.Center, this._v1, this._v2);

            p = p.ConvertTo(local_coord);

            if (GeometRi3D.AlmostEqual(p.X, 0) && GeometRi3D.AlmostEqual(p.Y, 0))
            {
                // Center point, choose any minor-axis
                return(new Point3d(0, this.B, 0, local_coord));
            }

            double  theta    = Atan2(this.A * p.Y, this.B * p.X);
            int     iter     = 0;
            int     max_iter = 100;
            Point3d n0       = p.Copy();

            while (iter < max_iter)
            {
                iter += 1;
                double f      = (A * A - B * B) * Cos(theta) * Sin(theta) - p.X * A * Sin(theta) + p.Y * B * Cos(theta);
                double f_prim = (A * A - B * B) * (Cos(theta) * Cos(theta) - Sin(theta) * Sin(theta))
                                - p.X * A * Cos(theta) - p.Y * B * Sin(theta);
                theta = theta - f / f_prim;
                Point3d n = new Point3d(A * Cos(theta), B * Sin(theta), 0, local_coord);

                if (n0.DistanceTo(n) < GeometRi3D.Tolerance)
                {
                    return(n);
                }
                n0 = n.Copy();
            }

            return(n0);
        }
Пример #17
0
        /// <summary>
        /// Check if two objects are orthogonal
        /// </summary>
        public bool IsOrthogonalTo(ILinearObject obj)
        {
            Vector3d v = obj.Direction;

            if ((this._coord != v._coord))
            {
                v = v.ConvertTo(this._coord);
            }

            double this_norm = this.Norm;
            double v_norm    = v.Norm;

            return(GeometRi3D.AlmostEqual(Abs(this * v) / (this_norm * v_norm), 0.0));

            //if (GeometRi3D.Greater(this_norm, 0.0) && GeometRi3D.Greater(v_norm, 0.0))
            //{
            //    return GeometRi3D.AlmostEqual(Abs(this * v) / (this_norm * v_norm), 0.0);
            //}
            //else
            //{
            //    return false;
            //}
        }
Пример #18
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);
     }
 }
Пример #19
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);
     }
 }
Пример #20
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);
     }
 }
Пример #21
0
 /// <summary>
 /// Check if point is inside ellipse
 /// </summary>
 /// <returns>True, if the point is inside ellipse</returns>
 public bool IsInside(Ellipse e)
 {
     if (GeometRi3D.UseAbsoluteTolerance)
     {
         if (this.BelongsTo(new Plane3d(e.Center, e.MajorSemiaxis, e.MinorSemiaxis)))
         {
             return(GeometRi3D.Smaller(this.DistanceTo(e.F1) + this.DistanceTo(e.F2), 2 * e.A));
         }
         else
         {
             return(false);
         }
     }
     else
     {
         double tol = GeometRi3D.Tolerance;
         GeometRi3D.Tolerance            = tol * e.MajorSemiaxis.Norm;
         GeometRi3D.UseAbsoluteTolerance = true;
         bool result = this.IsInside(e);
         GeometRi3D.UseAbsoluteTolerance = false;
         GeometRi3D.Tolerance            = tol;
         return(result);
     }
 }
Пример #22
0
        private object _line_intersection(Line3d l, double t0, double t1)
        {
            // Smith's algorithm:
            // "An Efficient and Robust Ray–Box Intersection Algorithm"
            // Amy Williams, Steve Barrus, R. Keith Morley, Peter Shirley
            // http://www.cs.utah.edu/~awilliam/box/box.pdf

            // Modified to allow tolerance based checks

            // Relative tolerance ================================
            if (!GeometRi3D.UseAbsoluteTolerance)
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance            = tol * this.Diagonal;
                GeometRi3D.UseAbsoluteTolerance = true;
                object result = _line_intersection(l, t0, t1);
                GeometRi3D.UseAbsoluteTolerance = false;
                GeometRi3D.Tolerance            = tol;
                return(result);
            }
            //====================================================

            // Define local CS aligned with box
            Coord3d local_CS = new Coord3d(this.Center, this.Orientation.ConvertToGlobal().ToRotationMatrix, "local_CS");

            Point3d Pmin = this.P1.ConvertTo(local_CS);
            Point3d Pmax = this.P7.ConvertTo(local_CS);

            l = new Line3d(l.Point.ConvertTo(local_CS), l.Direction.ConvertTo(local_CS).Normalized);

            double tmin, tmax, tymin, tymax, tzmin, tzmax;
            double divx = 1 / l.Direction.X;

            if (divx >= 0)
            {
                tmin = (Pmin.X - l.Point.X) * divx;
                tmax = (Pmax.X - l.Point.X) * divx;
            }
            else
            {
                tmin = (Pmax.X - l.Point.X) * divx;
                tmax = (Pmin.X - l.Point.X) * divx;
            }

            double divy = 1 / l.Direction.Y;

            if (divy >= 0)
            {
                tymin = (Pmin.Y - l.Point.Y) * divy;
                tymax = (Pmax.Y - l.Point.Y) * divy;
            }
            else
            {
                tymin = (Pmax.Y - l.Point.Y) * divy;
                tymax = (Pmin.Y - l.Point.Y) * divy;
            }

            if (GeometRi3D.Greater(tmin, tymax) || GeometRi3D.Greater(tymin, tmax))
            {
                return(null);
            }
            if (GeometRi3D.Greater(tymin, tmin))
            {
                tmin = tymin;
            }
            if (GeometRi3D.Smaller(tymax, tmax))
            {
                tmax = tymax;
            }

            double divz = 1 / l.Direction.Z;

            if (divz >= 0)
            {
                tzmin = (Pmin.Z - l.Point.Z) * divz;
                tzmax = (Pmax.Z - l.Point.Z) * divz;
            }
            else
            {
                tzmin = (Pmax.Z - l.Point.Z) * divz;
                tzmax = (Pmin.Z - l.Point.Z) * divz;
            }

            if (GeometRi3D.Greater(tmin, tzmax) || GeometRi3D.Greater(tzmin, tmax))
            {
                return(null);
            }
            if (GeometRi3D.Greater(tzmin, tmin))
            {
                tmin = tzmin;
            }
            if (GeometRi3D.Smaller(tzmax, tmax))
            {
                tmax = tzmax;
            }

            // Now check the overlapping portion of the segments
            // This part is missing in the original algorithm
            if (GeometRi3D.Greater(tmin, t1))
            {
                return(null);
            }
            if (GeometRi3D.Smaller(tmax, t0))
            {
                return(null);
            }

            if (GeometRi3D.Smaller(tmin, t0))
            {
                tmin = t0;
            }
            if (GeometRi3D.Greater(tmax, t1))
            {
                tmax = t1;
            }

            if (GeometRi3D.AlmostEqual(tmin, tmax))
            {
                return(l.Point.Translate(tmin * l.Direction));
            }
            else
            {
                return(new Segment3d(l.Point.Translate(tmin * l.Direction), l.Point.Translate(tmax * l.Direction)));
            }
        }
Пример #23
0
 /// <summary>
 /// Returns the hashcode for the object.
 /// </summary>
 public override int GetHashCode()
 {
     return(GeometRi3D.HashFunction(_point.GetHashCode(), _r.GetHashCode(), _normal.GetHashCode()));
 }
Пример #24
0
 /// <summary>
 /// Angle between two objects in radians (0 &lt; angle &lt; Pi)
 /// </summary>
 public double AngleTo(IPlanarObject obj)
 {
     return(GeometRi3D.GetAngle(this, obj));
 }
Пример #25
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));
                }
            }
        }
Пример #26
0
 /// <summary>
 /// Check if two objects are coplanar
 /// </summary>
 public bool IsCoplanarTo(ILinearObject obj)
 {
     return(GeometRi3D._coplanar(this, obj));
 }
Пример #27
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);
            }
            Ellipse e = (Ellipse)obj;

            if (GeometRi3D.UseAbsoluteTolerance)
            {
                if (GeometRi3D.AlmostEqual(this.A, this.B))
                {
                    // Ellipse is circle
                    if (GeometRi3D.AlmostEqual(e.A, e.B))
                    {
                        // Second ellipse also circle
                        return(this.Center == e.Center && GeometRi3D.AlmostEqual(this.A, e.A) && e.Normal.IsParallelTo(this.Normal));
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(this.Center == e.Center && GeometRi3D.AlmostEqual(this.A, e.A) && GeometRi3D.AlmostEqual(this.B, e.B) &&
                           e.MajorSemiaxis.IsParallelTo(this.MajorSemiaxis) && e.MinorSemiaxis.IsParallelTo(this.MinorSemiaxis));
                }
            }
            else
            {
                double tol = GeometRi3D.Tolerance;
                GeometRi3D.Tolerance            = tol * e.MajorSemiaxis.Norm;
                GeometRi3D.UseAbsoluteTolerance = true;

                if (GeometRi3D.AlmostEqual(this.A, this.B))
                {
                    // Ellipse is circle
                    if (GeometRi3D.AlmostEqual(e.A, e.B))
                    {
                        // Second ellipse also circle
                        bool res1 = this.Center == e.Center && GeometRi3D.AlmostEqual(this.A, e.A);
                        GeometRi3D.UseAbsoluteTolerance = false;
                        GeometRi3D.Tolerance            = tol;
                        bool res2 = e.Normal.IsParallelTo(this.Normal);
                        return(res1 && res2);
                    }
                    else
                    {
                        GeometRi3D.UseAbsoluteTolerance = false;
                        GeometRi3D.Tolerance            = tol;
                        return(false);
                    }
                }
                else
                {
                    bool res1 = this.Center == e.Center && GeometRi3D.AlmostEqual(this.A, e.A) && GeometRi3D.AlmostEqual(this.B, e.B);
                    GeometRi3D.UseAbsoluteTolerance = false;
                    GeometRi3D.Tolerance            = tol;
                    bool res2 = e.MajorSemiaxis.IsParallelTo(this.MajorSemiaxis) && e.MinorSemiaxis.IsParallelTo(this.MinorSemiaxis);
                    return(res1 && res2);
                }
            }
        }
Пример #28
0
        /// <summary>
        /// Intersection of ellipse with plane.
        /// Returns 'null' (no intersection) or object of type 'Ellipse', 'Point3d' or 'Segment3d'.
        /// </summary>
        public object IntersectionWith(Plane3d s)
        {
            if (this.Normal.IsParallelTo(s.Normal))
            {
                if (this.Center.BelongsTo(s))
                {
                    // coplanar objects
                    return(this.Copy());
                }
                else
                {
                    // parallel objects
                    return(null);
                }
            }
            else
            {
                Line3d   l           = (Line3d)s.IntersectionWith(new Plane3d(this.Center, this.Normal));
                Coord3d  local_coord = new Coord3d(this.Center, this._v1, this._v2);
                Point3d  p           = l.Point.ConvertTo(local_coord);
                Vector3d v           = l.Direction.ConvertTo(local_coord);
                double   a           = this.A;
                double   b           = this.B;

                if (Abs(v.Y / v.X) > 100)
                {
                    // line is almost vertical, rotate local coord
                    local_coord = new Coord3d(this.Center, this._v2, this._v1);
                    p           = l.Point.ConvertTo(local_coord);
                    v           = l.Direction.ConvertTo(local_coord);
                    a           = this.B;
                    b           = this.A;
                }

                // Find intersection of line and ellipse (2D)
                // Solution from: http://www.ambrsoft.com/TrigoCalc/Circles2/Ellipse/EllipseLine.htm

                // Line equation in form: y = mx + c
                double m = v.Y / v.X;
                double c = p.Y - m * p.X;

                double amb = Math.Pow(a, 2) * Math.Pow(m, 2) + Math.Pow(b, 2);
                double det = amb - Math.Pow(c, 2);
                if (det < -GeometRi3D.Tolerance)
                {
                    return(null);
                }
                else if (GeometRi3D.AlmostEqual(det, 0))
                {
                    double x = -Math.Pow(a, 2) * m * c / amb;
                    double y = Math.Pow(b, 2) * c / amb;
                    return(new Point3d(x, y, 0, local_coord));
                }
                else
                {
                    double x1 = (-Math.Pow(a, 2) * m * c + a * b * Sqrt(det)) / amb;
                    double x2 = (-Math.Pow(a, 2) * m * c - a * b * Sqrt(det)) / amb;
                    double y1 = (Math.Pow(b, 2) * c + a * b * m * Sqrt(det)) / amb;
                    double y2 = (Math.Pow(b, 2) * c - a * b * m * Sqrt(det)) / amb;
                    return(new Segment3d(new Point3d(x1, y1, 0, local_coord), new Point3d(x2, y2, 0, local_coord)));
                }
            }
        }
Пример #29
0
        /// <summary>
        /// Returns the hashcode for the object.
        /// </summary>
        public override int GetHashCode()
        {
            int hash_code = GeometRi3D.HashFunction(_lx.GetHashCode(), _ly.GetHashCode(), _lz.GetHashCode());

            return(GeometRi3D.HashFunction(_center.GetHashCode(), _r.GetHashCode(), hash_code));
        }
Пример #30
0
 /// <summary>
 /// Returns the hashcode for the object.
 /// </summary>
 public override int GetHashCode()
 {
     return(GeometRi3D.HashFunction(_a.GetHashCode(), _b.GetHashCode(), _c.GetHashCode()));
 }