예제 #1
0
파일: ShpPolygon.cs 프로젝트: ntj/GravurGIS
        private void vertex_PositionChanged(IShape sender, bool followUpMove)
        {
            if (!followUpMove)
            {
                if (closingPolygon)
                {
                    closingPolygon = false;
                    checkBoundingBox();
                    base.OnChanged(false);
                    return;
                }

                if (tolerance.Equal(sender.RootX, points[0].RootX) &&
                    tolerance.Equal(sender.RootY, points[0].RootY))
                { // the first point was changed
                    closingPolygon = true;
                    points[points.Count - 1].moveTo(sender.RootX, sender.RootY, false, false);
                }
                else if (tolerance.Equal(sender.RootX, points[points.Count - 1].RootX) &&
                         tolerance.Equal(sender.RootY, points[points.Count - 1].RootY)
                         )
                { // the last point was changed
                    closingPolygon = true;
                    points[0].moveTo(sender.RootX, sender.RootY, false, false);
                }
                else
                {
                    checkBoundingBox();
                    base.OnChanged(false);
                }
            }
            //else
            //    closingPolygon = false;
        }
예제 #2
0
        /// <summary>
        /// Returns a stereographically sphere representing us.
        /// </summary>
        public Sphere ToSphere()
        {
            // Equatorial sphere?
            if (Pole == new Vector3D(0, 0, 0, 1))
            {
                return(new Sphere());
            }

            // A plane?
            Vector3D poleR3 = Sterographic.S3toR3(Pole);

            if (Tolerance.Equal(poleR3.Abs(), 1))
            {
                return(Sphere.Plane(poleR3));
            }

            // Get 4 points on the sphere.
            Vector3D e1 = new Vector3D(1, 0, 0, 0);
            Vector3D e2 = new Vector3D(0, 1, 0, 0);
            Vector3D e3 = new Vector3D(0, 0, 1, 0);
            Vector3D e4 = new Vector3D(0, 0, 0, 1);

            System.Func <Vector3D, Vector3D> one = v =>
            {
                v = Euclidean3D.ProjectOntoPlane(Pole, new Vector3D(), v);
                v.Normalize();
                return(Sterographic.S3toR3(v));
            };

            return(Sphere.From4Points(one(e1), one(e2), one(e3), one(e4)));
        }
예제 #3
0
        /// <summary>
        /// Comparator used for ordering point first by ascending X, then by ascending Y.
        /// </summary>
        /// <param name="other">The <see cref="Point"/> to compare.</param>
        /// <returns>
        /// 0 if the points are spatially equal or both empty; 1 if <paramref name="other"/> is empty or
        /// if this point has a greater <see cref="X"/> value or equal X values and a greater <see cref="Y"/> value;
        /// -1 if this point is empty or if <paramref name="other"/> has a greater <see cref="X"/> value or equal X values
        /// and a greater <see cref="Y"/> value.
        /// </returns>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="other"/> is null.</exception>
        public virtual Int32 CompareTo(Point other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }

            if (Equals(other)) // This handles the case where both are empty.
            {
                return(0);
            }
            else if (IsEmpty)
            {
                return(-1);
            }
            else if (other.IsEmpty)
            {
                return(1);
            }
            else if (Tolerance.Less(X, other.X) || Tolerance.Equal(X, other.X) && Tolerance.Less(Y, other.Y))
            {
                return(-1);
            }
            else if (Tolerance.Greater(X, other.X) || Tolerance.Equal(X, other.X) && Tolerance.Greater(Y, other.Y))
            {
                return(1);
            }

            throw new InvalidOperationException("Points cannot be compared.");
        }
예제 #4
0
        /// <summary>
        /// Calculates the point of our simplex that is at a vertex.
        /// </summary>
        public static Vector3D VertexPointBall(int p, int q, int r)
        {
            Geometry vertexGeometry = Geometry2D.GetGeometry(q, r);

            if (vertexGeometry == Geometry.Hyperbolic)
            {
                // Outside the ball, and not in a good way.  Use the Klein version.
                //throw new System.NotImplementedException();
                return(new Vector3D(0, 0, -1));
            }

            // Get in UHS first.
            Sphere cellFacet = Mirrors(p, q, r, moveToBall: false).First();
            double rSquared  = Math.Pow(cellFacet.Radius, 2);
            double cSquared  = Math.Pow(cellFacet.Center.Abs(), 2);

            Vector3D uhs;

            if (Tolerance.Equal(rSquared, cSquared))                    // e.g. 363
            {
                uhs = new Vector3D();
            }
            else
            {
                double height = Math.Sqrt(rSquared - cSquared);
                uhs = new Vector3D(0, 0, height);
            }
            return(H3Models.UHSToBall(uhs));
        }
예제 #5
0
        // XXX - Do we only want to compare the surface, or also the orientation?
        // This just does the surface.
        public override bool Equals(object obj)
        {
            Sphere s = (Sphere)obj;

            if (IsPlane)
            {
                if (!s.IsPlane)
                {
                    return(false);
                }

                Vector3D n1 = this.Normal;
                n1.Normalize();
                Vector3D n2 = s.Normal;
                n2.Normalize();
                return
                    ((n1 == n2 || n1 == -n2) &&
                     Offset == s.Offset);
            }

            if (s.IsPlane)
            {
                return(false);
            }

            return
                (Tolerance.Equal(Radius, s.Radius) &&
                 Center == s.Center /*&&
                                     * Offset == s.Offset &&
                                     * Invert == s.Invert*/);
        }
예제 #6
0
        private static H3.Cell.Edge CalcFiber(Vector3D boundaryPointBall)
        {
            bool parallel = false;

            if (parallel)
            {
                Vector3D v2 = new Vector3D(0, 0, -1);                   // Really we can pick any boundary point.
                return(new H3.Cell.Edge(boundaryPointBall, v2));
            }
            else
            {
                // If the point is above the real line, it will have been connected to z.
                // If below the real line, it will have been connected to -i
                // If on the real line, it's degenerate.
                Vector3D pUHS = H3Models.BallToUHS(boundaryPointBall);
                if (Tolerance.Equal(pUHS.Y, 0))
                {
                    return(null);
                }

                Vector3D z      = Vector3D.FromComplex(ZParam);
                Vector3D minusi = new Vector3D(0, -1);

                double dilation    = double.NaN;
                double translation = double.NaN;
                if (pUHS.Y > 0)
                {
                    dilation    = pUHS.Y / z.Y;
                    z          *= dilation;
                    translation = pUHS.X - z.X;
                    z.X        += translation;
                    if (H3Models.UHSToBall(z) != boundaryPointBall)
                    {
                        throw new System.Exception();
                    }

                    minusi   *= dilation;
                    minusi.X += translation;
                    return(new H3.Cell.Edge(H3Models.UHSToBall(minusi), boundaryPointBall));
                    //return null;
                }
                else
                {
                    dilation    = pUHS.Y / -1;
                    minusi     *= dilation;
                    translation = pUHS.X - minusi.X;
                    minusi.X   += translation;
                    if (H3Models.UHSToBall(minusi) != boundaryPointBall)
                    {
                        throw new System.Exception();
                    }

                    z   *= dilation;
                    z.X += translation;
                    return(new H3.Cell.Edge(boundaryPointBall, H3Models.UHSToBall(z)));
                    //return null;
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Construct a circle from 3 points
        /// </summary>
        /// <returns>false if the construction failed (if we are a line).</returns>
        public bool From3Points(Vector3D p1, Vector3D p2, Vector3D p3)
        {
            Reset();

            // Check for any infinite points, in which case we are a line.
            // I'm not sure these checks are smart, since our IsInfinite check is so inclusive,
            // but Big Chop puzzle doesn't work if we don't do this.
            // ZZZ - Still, I need to think on this more.
            if (Infinity.IsInfinite(p1))
            {
                this.From2Points(p2, p3);
                return(false);
            }
            else if (Infinity.IsInfinite(p2))
            {
                this.From2Points(p1, p3);
                return(false);
            }
            else if (Infinity.IsInfinite(p3))
            {
                this.From2Points(p1, p2);
                return(false);
            }

            /* Some links
             * http://mathforum.org/library/drmath/view/54323.html
             * http://delphiforfun.org/Programs/Math_Topics/circle_from_3_points.htm
             * There is lots of info out there about solving via equations,
             * but as with other code in this project, I wanted to use geometrical constructions. */

            // Midpoints.
            Vector3D m1 = (p1 + p2) / 2;
            Vector3D m2 = (p1 + p3) / 2;

            // Perpendicular bisectors.
            Vector3D b1 = (p2 - p1) / 2;
            Vector3D b2 = (p3 - p1) / 2;

            b1.Normalize();
            b2.Normalize();
            b1.Rotate90();
            b2.Rotate90();

            Vector3D newCenter;
            int      found = Euclidean2D.IntersectionLineLine(m1, m1 + b1, m2, m2 + b2, out newCenter);

            Center = newCenter;
            if (0 == found)
            {
                // The points are collinear, so we are a line.
                From2Points(p1, p2);
                return(false);
            }

            Radius = (p1 - Center).Abs();
            Debug.Assert(Tolerance.Equal(Radius, (p2 - Center).Abs()));
            Debug.Assert(Tolerance.Equal(Radius, (p3 - Center).Abs()));
            return(true);
        }
예제 #8
0
        private static void HopfFibration(Tiling tiling)
        {
            int       segDivisions    = 10;
            int       circleDivisions = 125;
            Shapeways mesh            = new Shapeways();

            HashSet <Vector3D> done = new HashSet <Vector3D>();

            foreach (Tile tile in tiling.Tiles)
            {
                foreach (Segment seg in tile.Boundary.Segments)
                {
                    if (done.Contains(seg.Midpoint))
                    {
                        continue;
                    }

                    // Subdivide the segment, and project points to S2.
                    Vector3D[] points = seg.Subdivide(segDivisions).Select(v => Spherical2D.PlaneToSphere(v)).ToArray();
                    foreach (Vector3D point in points)
                    {
                        // Get the hopf circle and add to mesh.
                        // http://en.wikipedia.org/wiki/Hopf_fibration#Explicit_formulae
                        double a      = point.X;
                        double b      = point.Y;
                        double c      = point.Z;
                        double factor = 1 / (Math.Sqrt(1 + c));
                        if (Tolerance.Equal(c, -1))
                        {
                            continue;
                        }

                        List <Vector3D> circlePoints = new List <Vector3D>();
                        double          angleInc     = 2 * Math.PI / circleDivisions;
                        double          angle        = 0;
                        for (int i = 0; i <= circleDivisions; i++)
                        {
                            double sinTheta = Math.Sin(angle);
                            double cosTheta = Math.Cos(angle);
                            circlePoints.Add(new Vector3D(
                                                 (1 + c) * cosTheta,
                                                 a * sinTheta - b * cosTheta,
                                                 a * cosTheta + b * sinTheta,
                                                 (1 + c) * sinTheta));

                            angle += angleInc;
                        }

                        bool shrink = false;
                        ProjectAndAddS3Points(mesh, circlePoints.ToArray(), shrink);
                    }

                    done.Add(seg.Midpoint);
                }
            }

            STL.SaveMeshToSTL(mesh.Mesh, @"D:\p4\R3\sample\out1.stl");
        }
예제 #9
0
        public static int IntersectionLineCircle(Vector3D lineP1, Vector3D lineP2, Circle circle,
                                                 out Vector3D p1, out Vector3D p2)
        {
            p1 = new Vector3D();
            p2 = new Vector3D();

            // Distance from the circle center to the closest point on the line.
            double d = DistancePointLine(circle.Center, lineP1, lineP2);

            // No intersection points.
            double r = circle.Radius;

            if (d > r)
            {
                return(0);
            }

            // One intersection point.
            p1 = ProjectOntoLine(circle.Center, lineP1, lineP2);
            if (Tolerance.Equal(d, r))
            {
                return(1);
            }

            // Two intersection points.
            // Special case when the line goes through the circle center,
            // because we can see numerical issues otherwise.
            //
            // I had further issues where my default tolerance was too strict for this check.
            // The line was close to going through the center and the second block was used,
            // so I had to loosen the tolerance used by my comparison macros.
            if (Tolerance.Zero(d))
            {
                Vector3D line = lineP2 - lineP1;
                line.Normalize();
                line *= r;
                p1    = circle.Center + line;
                p2    = circle.Center - line;
            }
            else
            {
                // To origin.
                p1 -= circle.Center;

                p1.Normalize();
                p1 *= r;
                p2  = p1;
                double angle = Math.Acos(d / r);
                p1.RotateXY(angle);
                p2.RotateXY(-angle);

                // Back out.
                p1 += circle.Center;
                p2 += circle.Center;
            }
            return(2);
        }
예제 #10
0
        /// <summary>
        /// Checks if a point is anywhere on a segment.
        /// </summary>
        public static bool PointOnSegment(Vector3D s1, Vector3D s2, Vector3D point)
        {
            // Look for a degenerate triangle.
            double d1 = (point - s1).MagSquared();
            double d2 = (s2 - point).MagSquared();
            double d3 = (s2 - s1).MagSquared();

            return(Tolerance.Equal(d1 + d2, d3));
        }
예제 #11
0
        public bool IsPointOn(Vector3D test)
        {
            if (this.IsLine)
            {
                return(Tolerance.Zero(Euclidean2D.DistancePointLine(test, P1, P2)));
            }

            return(Tolerance.Equal((test - Center).Abs(), Radius));
        }
예제 #12
0
        private static bool PointOnLineSegment(Vector3D p, Segment seg)
        {
            // This will be so if the point and the segment ends represent
            // the vertices of a degenerate triangle.
            double d1 = (seg.P2 - seg.P1).Abs();
            double d2 = (p - seg.P1).Abs();
            double d3 = (seg.P2 - p).Abs();

            return(Tolerance.Equal(d1, d2 + d3));
        }
예제 #13
0
        public bool IsPointOn(Vector3D test)
        {
            if (IsPlane)
            {
                double dist = Euclidean3D.DistancePointPlane(this.Normal, this.Offset, test);
                return(Tolerance.Zero(dist));
            }

            return(Tolerance.Equal((test - Center).Abs(), Radius));
        }
예제 #14
0
        /// <summary>
        /// Outputs edges to an stl file.
        /// </summary>
        public void Output()
        {
            System.Func <Vector3D, Vector3D> p2s       = v => Spherical2D.PlaneToSphere(v);
            System.Func <Vector3D, Vector3D> transform = v => H3Models.Ball.ApplyMobius(Mobius.Scale(3), v);

            double min  = double.MaxValue;
            Cell   cell = m_cells.First();

            foreach (Vector3D v1 in cell.Tiles[0].Boundary.Vertices)
            {
                foreach (Vector3D v2 in cell.Tiles[1].Boundary.Vertices)
                {
                    min = Math.Min(min, p2s(v1).Dist(p2s(v2)));
                }
            }

            // XXX - code below so ugly to read!

            Dictionary <TileVertex, TileVertex> vMap = new Dictionary <TileVertex, TileVertex>();

            for (int tile_i = 0; tile_i < cell.Tiles.Length; tile_i++)
            {
                for (int tile_j = tile_i + 1; tile_j < cell.Tiles.Length; tile_j++)
                {
                    for (int vertex_i = 0; vertex_i < cell.Tiles[tile_i].Boundary.Vertices.Length; vertex_i++)
                    {
                        for (int vertex_j = 0; vertex_j < cell.Tiles[tile_j].Boundary.Vertices.Length; vertex_j++)
                        {
                            Vector3D v1 = cell.Tiles[tile_i].Boundary.Vertices[vertex_i];
                            Vector3D v2 = cell.Tiles[tile_j].Boundary.Vertices[vertex_j];

                            if (Tolerance.Equal(p2s(v1).Dist(p2s(v2)), min))
                            {
                                vMap[new TileVertex(tile_i, vertex_i)] = new TileVertex(tile_j, vertex_j);
                            }
                        }
                    }
                }
            }

            HashSet <H3.Cell.Edge> edges = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer());

            foreach (Cell c in m_cells)
            {
                foreach (KeyValuePair <TileVertex, TileVertex> kvp in vMap)
                {
                    Vector3D v1 = transform(p2s(c.Tiles[kvp.Key.Item1].Boundary.Vertices[kvp.Key.Item2]));
                    Vector3D v2 = transform(p2s(c.Tiles[kvp.Value.Item1].Boundary.Vertices[kvp.Value.Item2]));
                    edges.Add(new H3.Cell.Edge(v1, v2));
                }
            }

            //H3.m_settings.ThinEdges = true;
            H3.SaveToFile("ultrainf", edges.ToArray(), finite: false);
        }
예제 #15
0
        private int PolyWithAngle(double angle)
        {
            for (int i = 3; i < m_max; i++)
            {
                if (Tolerance.Equal(angle, Polygon.InteriorAngle(i)))
                {
                    return(i);
                }
            }

            return(0);
        }
예제 #16
0
        /// <summary>
        /// Calculates the two poles of a great circle defined by two points.
        /// </summary>
        public static void GreatCirclePole(Vector3D sphereCenter, Vector3D p1, Vector3D p2,
                                           out Vector3D pole1, out Vector3D pole2)
        {
            double sphereRadius = p1.Dist(sphereCenter);

            Debug.Assert(Tolerance.Equal(sphereRadius, p2.Dist(sphereCenter)));

            Vector3D v1 = p1 - sphereCenter;
            Vector3D v2 = p2 - sphereCenter;

            pole1 = v1.Cross(v2) + sphereCenter;
            pole2 = v2.Cross(v1) + sphereCenter;
        }
예제 #17
0
        private static bool PointOnArcSegment(Vector3D p, Segment seg)
        {
            double   maxAngle = seg.Angle;
            Vector3D v1       = seg.P1 - seg.Center;
            Vector3D v2       = p - seg.Center;

            Debug.Assert(Tolerance.Equal(v1.Abs(), v2.Abs()));
            double angle = seg.Clockwise ?
                           Euclidean2D.AngleToClock(v1, v2) :
                           Euclidean2D.AngleToCounterClock(v1, v2);

            return(Tolerance.LessThanOrEqual(angle, maxAngle));
        }
예제 #18
0
        public static Vector3D S3toR3(Vector3D p)
        {
            double w = p.W;

            if (Tolerance.Equal(w, 1))
            {
                return(Vector3D.DneVector());
            }

            return(new Vector3D(
                       p.X / (1 - w),
                       p.Y / (1 - w),
                       p.Z / (1 - w)));
        }
예제 #19
0
        // Returns the geometry induced by a polygon with p points, q meeting at a vertex.
        public static Geometry GetGeometry(double p, double q)
        {
            double test = 1.0 / p + 1.0 / q;

            if (test > 0.5)
            {
                return(Geometry.Spherical);
            }
            else if (Tolerance.Equal(test, 0.5))
            {
                return(Geometry.Euclidean);
            }

            return(Geometry.Hyperbolic);
        }
예제 #20
0
        private static void AvoidNorthPole(ref Vector3D v, Vector3D direction)
        {
            if (!Tolerance.Equal(v.W, 1))
            {
                return;
            }

            Vector3D cutEnd = v - direction;
            double   abs    = cutEnd.Abs();

            abs -= 0.35;
            cutEnd.Normalize();
            cutEnd *= abs;
            v       = direction + cutEnd;
            v.Normalize();
        }
예제 #21
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);
        }
예제 #22
0
        public static Circle3D FromCenterAnd2Points(Vector3D cen, Vector3D p1, Vector3D p2)
        {
            Circle3D circle = new Circle3D();

            circle.Center = cen;
            circle.Radius = (p1 - cen).Abs();

            if (!Tolerance.Equal(circle.Radius, (p2 - cen).Abs()))
            {
                throw new System.ArgumentException("Points are not on the same circle.");
            }

            Vector3D normal = (p2 - cen).Cross(p1 - cen);

            normal.Normalize();
            circle.Normal = normal;
            return(circle);
        }
예제 #23
0
        /// <summary>
        /// Finds the intersection (a circle) between us and another sphere.
        /// Returns null if sphere centers are coincident or no intersection exists.
        /// Does not currently work for planes.
        /// </summary>
        public Circle3D Intersection(Sphere s)
        {
            if (this.IsPlane || s.IsPlane)
            {
                throw new System.NotImplementedException();
            }

            double r = s.Radius;
            double R = this.Radius;

            Vector3D diff = this.Center - s.Center;
            double   d    = diff.Abs();

            if (Tolerance.Equal(d, r + R))
            {
                diff.Normalize();
                return(new Circle3D()
                {
                    Center = s.Center + diff * s.Radius,
                    Radius = 0
                });
            }

            if (Tolerance.Zero(d) || d > r + R)
            {
                return(null);
            }

            // Sphere's inside spheres and not touching.
            //if( d < Math.Abs( R - r ) )
            //	return null;

            double x = (d * d + r * r - R * R) / (2 * d);
            double y = Math.Sqrt(r * r - x * x);

            Circle3D result = new Circle3D();

            diff.Normalize();
            result.Normal = diff;
            result.Center = s.Center + diff * x;
            result.Radius = y;
            return(result);
        }
예제 #24
0
        /// <summary>
        /// Checks whether this instance is spatially equal to <paramref name="p"/>.
        /// </summary>
        /// <param name="p">Point to compare to</param>
        /// <returns>True if the points are either both empty or have the same coordinates, false otherwise.</returns>
        public virtual Boolean Equals(Point p)
        {
            if (ReferenceEquals(p, null))
            {
                return(false);
            }

            if (IsEmpty && p.IsEmpty)
            {
                return(true);
            }

            if (IsEmpty || p.IsEmpty)
            {
                return(false);
            }

            return(Tolerance.Equal(p.X, X) && Tolerance.Equal(p.Y, Y));
        }
예제 #25
0
        // ZZZ - I wonder if we want to do normalization of lines before comparing.

        public bool Equals(CircleNE c1, CircleNE c2)
        {
            bool radiusEqual =
                Tolerance.Equal(c1.Radius, c2.Radius) ||
                (Infinity.IsInfinite(c1.Radius) && Infinity.IsInfinite(c2.Radius));

            if (c1.IsLine)
            {
                return(c1.P1 == c2.P1 &&
                       c1.P2 == c2.P2 &&
                       radiusEqual);
            }
            else
            {
                return
                    (c1.Center == c2.Center &&
                     c1.CenterNE == c2.CenterNE &&
                     radiusEqual);
            }
        }
예제 #26
0
        public static Circle3D GeodesicFrom2Points(Vector3D a, Vector3D b)
        {
            if (a == b || a == -b)
            {
                throw new System.Exception("Geodesic not unique");
            }

            System.Func <Vector3D, Circle3D> lineFunc = p =>
            {
                Circle3D circ = new Circle3D();
                circ.Radius = double.PositiveInfinity;
                p.Normalize();
                circ.Normal = p;                    // Hacky representation of a line.
                return(circ);
            };

            if (a.IsOrigin || b.IsOrigin)
            {
                Vector3D p = a.IsOrigin ? b : a;
                return(lineFunc(p));
            }

            double mag1 = a.Abs(), mag2 = b.Abs();

            if (Tolerance.Equal(mag1, 1) && Tolerance.Equal(mag2, 1))
            {
                return(new Circle3D(a, b, a * -1));
            }

            // The antipode in S^3 of a or b will give us a 3rd point.
            Vector3D antipode = Sterographic.S3toR3(Sterographic.R3toS3(a) * -1);

            // If the antipode is also an an antipode in R3, the points are colinear
            // (or they are on the equatorial 2-sphere, but that is checked above).
            if (a == antipode * -1)
            {
                return(lineFunc(a));
            }

            return(new Circle3D(a, b, antipode));
        }
예제 #27
0
        private static H3.Cell.Edge[] Cull120Cell(H3.Cell.Edge[] edges)
        {
            Func <Vector3D, bool> passes = new Func <Vector3D, bool>(v =>
            {
                //return
                //	Math.Pow( v.Z, 2 ) < 0.13 &&
                //	Math.Pow( v.W, 2 ) < 0.13;
                return(Tolerance.Equal(v.W, 0.0));
            });

            H3.Cell.Edge[] result = edges.Where(e =>
            {
                Vector3D start = Sterographic.R3toS3(e.Start);
                Vector3D end   = Sterographic.R3toS3(e.End);
                return(passes(start) && passes(end));
            }).ToArray();

            // Now cull valence-2 edges.
            //result = CullValence2Edges( result );

            return(result);
        }
예제 #28
0
        public static Vector3D[] OneHopfCircle(Vector3D s2Point, bool anti = false)
        {
            int circleDivisions = 125;

            // Get the hopf circle.
            // http://en.wikipedia.org/wiki/Hopf_fibration#Explicit_formulae
            double a      = s2Point.X;
            double b      = s2Point.Y;
            double c      = s2Point.Z;
            double factor = 1 / (Math.Sqrt(1 + c));

            if (Tolerance.Equal(c, -1))
            {
                return new Vector3D[] {}
            }
            ;

            List <Vector3D> circlePoints = new List <Vector3D>();
            double          angleInc     = 2 * Math.PI / circleDivisions;
            double          angle        = 0;

            for (int i = 0; i <= circleDivisions; i++)
            {
                double   sinTheta = Math.Sin(angle);
                double   cosTheta = Math.Cos(angle);
                Vector3D point    = new Vector3D(
                    (1 + c) * cosTheta,
                    anti ? -a * sinTheta - b * cosTheta : a * sinTheta - b * cosTheta,
                    anti ?   a * cosTheta - b * sinTheta : a * cosTheta + b * sinTheta,
                    (1 + c) * sinTheta);
                point.Normalize();
                circlePoints.Add(point);

                angle += angleInc;
            }

            return(circlePoints.ToArray());
        }
예제 #29
0
        public bool Compare(Vector3D other, double threshold)
        {
            // NOTE: This is here because when the vector is infinite, it fails the tolerance checks below.
            if ((X == other.X) && (Y == other.Y) && (Z == other.Z) && W == other.W)
            {
                return(true);
            }

            if (this.DNE && other.DNE)
            {
                return(true);
            }

            if (this.DNE || other.DNE)
            {
                return(false);
            }

            return(Tolerance.Equal(X, other.X, threshold) &&
                   Tolerance.Equal(Y, other.Y, threshold) &&
                   Tolerance.Equal(Z, other.Z, threshold) &&
                   Tolerance.Equal(W, other.W, threshold));
        }
예제 #30
0
        public static Segment Arc(Vector3D start, Vector3D mid, Vector3D end)
        {
            Segment newSeg = new Segment();

            newSeg.Type = SegmentType.Arc;
            newSeg.P1   = start;
            newSeg.P2   = end;

            Circle c = new Circle();

            c.From3Points(start, mid, end);
            newSeg.Center = c.Center;

            // Obtain vectors from center point of circle (as if at the origin)
            Vector3D startOrigin = start - c.Center;
            Vector3D midOrigin   = mid - c.Center;
            Vector3D endOrigin   = end - c.Center;

            // Calculate the normal vector and angle to traverse.
            // ZZZ - worry about failure of cross product here.
            Vector3D normalVector = startOrigin.Cross(endOrigin);

            newSeg.Clockwise = normalVector.Z < 0;
            double angleToTraverse = startOrigin.AngleTo(endOrigin);

            // The normal vector might need to be reversed and the angleToTraverse adjusted.
            // This happens depending on the location of the midpoint relative to the start and end points.
            double compareAngle = startOrigin.AngleTo(midOrigin) + midOrigin.AngleTo(endOrigin);
            bool   reverse      = !Tolerance.Equal(angleToTraverse, compareAngle);

            if (reverse)
            {
                newSeg.Clockwise = !newSeg.Clockwise;
            }

            return(newSeg);
        }