예제 #1
0
        private static bool EdgeOkUHS(H3.Cell.Edge edge, Circle region)
        {
            if (Tolerance.GreaterThan(edge.Start.Abs(), region.Radius) ||
                Tolerance.GreaterThan(edge.End.Abs(), region.Radius))
            {
                return(false);
            }

            return(EdgeOk(edge, m_params.UhsCutoff));
        }
예제 #2
0
        private static bool TetOk(Tet tet)
        {
            double cutoff = 0.95;

            foreach (Vector3D v in tet.Verts)
            {
                if (Tolerance.GreaterThan(v.Z, 0) ||
                    v.Abs() > cutoff)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #3
0
        /// <summary>
        /// Checks to see if two segments intersect.
        /// This does not actually calculate the intersection point.
        /// It uses information from the following paper:
        /// http://www.geometrictools.com/Documentation/DistanceLine3Line3.pdf
        /// </summary>
        public static bool DoSegmentsIntersect(Vector3D a1, Vector3D a2, Vector3D b1, Vector3D b2)
        {
            /* Our approach.
             * (1) Check if endpoints are on other segment.  Note that this also checks if A endpoints equal B endpoints.
             * (2) Calc line-line distance.  If > 0, we don't intersect.
             * (3) At this point, we only have to deal with non-parallel case in the paper, and only
             *      need to determine if we are in "region 0" (we intersect) or not (we don't)
             */

            // (1)
            if (PointOnSegment(a1, a2, b1) ||
                PointOnSegment(a1, a2, b2) ||
                PointOnSegment(b1, b2, a1) ||
                PointOnSegment(b1, b2, a2))
            {
                return(true);
            }

            // (2)
            Vector3D ma = a2 - a1;
            Vector3D mb = b2 - b1;

            if (Tolerance.GreaterThan(DistanceLineLine(ma, a1, mb, b1), 0))
            {
                return(false);
            }

            // (3)
            Vector3D D = a1 - b1;
            double   a = ma.Dot(ma);
            double   b = -ma.Dot(mb);
            double   c = mb.Dot(mb);
            double   d = ma.Dot(D);
            double   e = -mb.Dot(D);

            double det = a * c - b * b;
            double s   = b * e - c * d;
            double t   = b * d - a * e;

            if (s >= 0 && s <= det &&
                t >= 0 && t <= det)
            {
                return(true);
            }

            return(false);
        }
예제 #4
0
        public static Geometry GetGeometry(int p, int q, int r)
        {
            double t1 = Math.Sin(PiOverNSafe(p)) * Math.Sin(PiOverNSafe(r));
            double t2 = Math.Cos(PiOverNSafe(q));

            if (Tolerance.Equal(t1, t2))
            {
                return(Geometry.Euclidean);
            }

            if (Tolerance.GreaterThan(t1, t2))
            {
                return(Geometry.Spherical);
            }

            return(Geometry.Hyperbolic);
        }
예제 #5
0
        public int Compare(Vector3D v1, Vector3D v2)
        {
            const int less    = -1;
            const int greater = 1;

            if (Tolerance.LessThan(v1.X, v2.X))
            {
                return(less);
            }
            if (Tolerance.GreaterThan(v1.X, v2.X))
            {
                return(greater);
            }

            if (Tolerance.LessThan(v1.Y, v2.Y))
            {
                return(less);
            }
            if (Tolerance.GreaterThan(v1.Y, v2.Y))
            {
                return(greater);
            }

            if (Tolerance.LessThan(v1.Z, v2.Z))
            {
                return(less);
            }
            if (Tolerance.GreaterThan(v1.Z, v2.Z))
            {
                return(greater);
            }

            if (Tolerance.LessThan(v1.W, v2.W))
            {
                return(less);
            }
            if (Tolerance.GreaterThan(v1.W, v2.W))
            {
                return(greater);
            }

            // Making it here means we are equal.
            return(0);
        }
예제 #6
0
        public static int IntersectionCircleCircle(Circle c1, Circle c2, out Vector3D p1, out Vector3D p2)
        {
            p1 = new Vector3D();
            p2 = new Vector3D();

            // A useful page describing the cases in this function is:
            // http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/2circle/

            p1.Empty();
            p2.Empty();

            // Vector and distance between the centers.
            Vector3D v  = c2.Center - c1.Center;
            double   d  = v.Abs();
            double   r1 = c1.Radius;
            double   r2 = c2.Radius;

            // Circle centers coincident.
            if (Tolerance.Zero(d))
            {
                if (Tolerance.Equal(r1, r2))
                {
                    return(-1);
                }
                else
                {
                    return(0);
                }
            }

            // We should be able to normalize at this point.
            if (!v.Normalize())
            {
                Debug.Assert(false);
                return(0);
            }

            // No intersection points.
            // First case is disjoint circles.
            // Second case is where one circle contains the other.
            if (Tolerance.GreaterThan(d, r1 + r2) ||
                Tolerance.LessThan(d, Math.Abs(r1 - r2)))
            {
                return(0);
            }

            // One intersection point.
            if (Tolerance.Equal(d, r1 + r2) ||
                Tolerance.Equal(d, Math.Abs(r1 - r2)))
            {
                p1 = c1.Center + v * r1;
                return(1);
            }

            // There must be two intersection points.
            p1 = p2 = v * r1;
            double temp  = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
            double angle = Math.Acos(temp / r1);

            Debug.Assert(!Tolerance.Zero(angle) && !Tolerance.Equal(angle, Math.PI));
            p1.RotateXY(angle);
            p2.RotateXY(-angle);
            p1 += c1.Center;
            p2 += c1.Center;
            return(2);
        }
예제 #7
0
        /// <summary>
        /// Returns intersection points between a circle and a great circle.
        /// There may be 0, 1, or 2 intersection points.
        /// Returns false if the circle is the same as gc.
        /// </summary>
        static bool IntersectionCircleGC(Circle3D c, Vector3D gc, List <Vector3D> iPoints)
        {
            double radiusCosAngle = CosAngle(c.Normal, c.PointOnCircle);
            double radiusAngle    = Math.Acos(radiusCosAngle);
            double radius         = radiusAngle;        // Since sphere radius is 1.

            // Find the great circle perpendicular to gc, and through the circle center.
            Vector3D gcPerp = c.Normal.Cross(gc);

            if (!gcPerp.Normalize())
            {
                // Circles are parallel => Zero or infinity intersections.
                if (Tolerance.Equal(radius, Math.PI / 2))
                {
                    return(false);
                }

                return(true);
            }

            // Calculate the offset angle from the circle normal to the gc normal.
            double offsetAngle = c.Normal.AngleTo(gc);

            if (Tolerance.GreaterThan(offsetAngle, Math.PI / 2))
            {
                gc         *= -1;
                offsetAngle = c.Normal.AngleTo(gc);
            }
            double coAngle = Math.PI / 2 - offsetAngle;

            // No intersections.
            if (radiusAngle < coAngle)
            {
                return(true);
            }

            // Here is the perpendicular point on the great circle.
            Vector3D pointOnGC = c.Normal;

            pointOnGC.RotateAboutAxis(gcPerp, coAngle);

            // 1 intersection.
            if (Tolerance.Equal(radiusAngle, coAngle))
            {
                iPoints.Add(pointOnGC);
                return(true);
            }

            // 2 intersections.

            // Spherical pythagorean theorem
            // http://en.wikipedia.org/wiki/Pythagorean_theorem#Spherical_geometry
            // We know the hypotenuse and one side.  We need the third leg.
            // We do this calculation on a unit sphere, to get the result as a normalized cosine of an angle.
            double sideCosA = radiusCosAngle / Math.Cos(coAngle);
            double rot      = Math.Acos(sideCosA);

            Vector3D i1 = pointOnGC, i2 = pointOnGC;

            i1.RotateAboutAxis(gc, rot);
            i2.RotateAboutAxis(gc, -rot);
            iPoints.Add(i1);
            iPoints.Add(i2);

            Circle3D test = new Circle3D {
                Normal = gc, Center = new Vector3D(), Radius = 1
            };


            return(true);
        }