Esempio n. 1
0
 private void Init()
 {
     m_tiles          = new List <Tile>();
     m_equator        = new CircleNE();
     m_neighborCircle = new CircleNE();
     m_cells          = new List <Cell>();
 }
Esempio n. 2
0
        /// <summary>
        /// Setup a circle we'll use to color neighbors.
        /// </summary>
        private void SetupNeighborCircle(Tile templateTriangle)
        {
            Polygon  poly = m_tiles.First().Boundary;                   // Tetrahedral tiling.
            CircleNE circ = new CircleNE();

            circ.Radius = m_shrink;

            circ.Reflect(poly.Segments[2]);
            circ.Reflect(templateTriangle.Boundary.Segments[1]);

            Mobius m = new Mobius();

            m.Isometry(Geometry.Spherical, 0, -circ.CenterNE);
            circ.Transform(m);
            m_neighborCircle         = new CircleNE();
            m_neighborCircle.Radius  = 1.0 / circ.Radius;
            m_originalNeighborCircle = m_neighborCircle.Clone();

            System.Func <Vector3D, Vector3D> pointTransform = v =>
            {
                v *= m_neighborCircle.Radius;
                v  = new Vector3D(v.Y, v.X);
                v.RotateXY(-Math.PI / 2);
                return(v);
            };
            m_neighborToStandardDisk = CalcMobius(pointTransform);
        }
Esempio n. 3
0
        private static void SlicePolygonHelper(Polygon p, CircleNE c1, CircleNE c2, out List <Polygon> output)
        {
            output = new List <Polygon>();

            // ZZZ - alter Clip method to work on Polygons and use that.

            // Slice it up.
            List <Polygon> sliced1, sliced2;

            Slicer.SlicePolygon(p, c1, out sliced1);
            Slicer.SlicePolygon(p, c2, out sliced2);

            // Keep the ones we want.
            foreach (Polygon newPoly in sliced1)
            {
                bool outside = !c1.IsPointInsideNE(newPoly.CentroidApprox);
                if (outside)
                {
                    output.Add(newPoly);
                }
            }

            foreach (Polygon newPoly in sliced2)
            {
                bool inside = c2.IsPointInsideNE(newPoly.CentroidApprox);
                if (inside)
                {
                    output.Add(newPoly);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Slicing function used for earthquake puzzles.
        /// c should be geodesic (orthogonal to the disk boundary).
        /// </summary>
        public static void SlicePolygonWithHyperbolicGeodesic(Polygon p, CircleNE c, double thickness, out List <Polygon> output)
        {
            Geometry g = Geometry.Hyperbolic;

            Segment seg = null;

            if (c.IsLine)
            {
                Vector3D p1, p2;
                Euclidean2D.IntersectionLineCircle(c.P1, c.P2, new Circle(), out p1, out p2);
                seg = Segment.Line(p1, p2);
            }
            else
            {
                // Setup the two slicing circles.
                // These are cuts equidistant from the passed in geodesic.
                Vector3D closestToOrigin = H3Models.Ball.ClosestToOrigin(new Circle3D()
                {
                    Center = c.Center, Radius = c.Radius, Normal = new Vector3D(0, 0, 1)
                });

                Vector3D p1, p2;
                Euclidean2D.IntersectionCircleCircle(c, new Circle(), out p1, out p2);
                seg = Segment.Arc(p1, closestToOrigin, p2);
            }

            Circle c1 = H3Models.Ball.EquidistantOffset(g, seg, thickness / 2);
            Circle c2 = H3Models.Ball.EquidistantOffset(g, seg, -thickness / 2);

            CircleNE c1NE = c.Clone(), c2NE = c.Clone();

            c1NE.Center = c1.Center; c2NE.Center = c2.Center;
            c1NE.Radius = c1.Radius; c2NE.Radius = c2.Radius;
            SlicePolygonHelper(p, c1NE, c2NE, out output);
        }
Esempio n. 5
0
        /// <summary>
        /// Slices a polygon by a circle with some thickness.
        /// Input circle may be a line.
        /// </summary>
        /// <remarks>The input polygon might get reversed</remarks>
        public static void SlicePolygon(Polygon p, CircleNE c, Geometry g, double thickness, out List <Polygon> output)
        {
            // Setup the two slicing circles.
            CircleNE c1 = c.Clone(), c2 = c.Clone();
            Mobius   m             = new Mobius();
            Vector3D pointOnCircle = c.IsLine ? c.P1 : c.Center + new Vector3D(c.Radius, 0);

            m.Hyperbolic2(g, c1.CenterNE, pointOnCircle, thickness / 2);
            c1.Transform(m);
            m.Hyperbolic2(g, c2.CenterNE, pointOnCircle, -thickness / 2);
            c2.Transform(m);

            SlicePolygonHelper(p, c1, c2, out output);
        }
Esempio n. 6
0
        /// <summary>
        /// This will return whether we'll be a new tile after reflecting through a segment.
        /// This allows us to do the check without having to do all the work of reflecting the entire tile.
        /// </summary>
        public bool NewTileAfterReflect(Tile t, Segment s, Dictionary <Vector3D, bool> completed)
        {
            /* This was too slow!
             * Polygon newPolyBoundary = t.Boundary.Clone();
             * newPolyBoundary.Reflect( s );
             * Vector3D testCenter = this.TilingConfig.M.Apply( newPolyBoundary.Center );*/

            CircleNE newVertexCircle = t.VertexCircle.Clone();

            newVertexCircle.Reflect(s);
            Vector3D testCenter = this.TilingConfig.M.Apply(newVertexCircle.CenterNE);

            return(!completed.ContainsKey(testCenter));
        }
Esempio n. 7
0
        private bool NewTetAfterReflect(Cell cell, Segment s, HashSet <Vector3D> completed)
        {
            foreach (Tile tile in cell.Tiles)
            {
                CircleNE newVertexCircle = tile.VertexCircle.Clone();
                newVertexCircle.Reflect(s);

                if (completed.Contains(Infinity.InfinitySafe(newVertexCircle.CenterNE)))
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 8
0
        /// <summary>
        /// Slices a polygon by a circle with some thickness.
        /// Input circle may be a line.
        /// </summary>
        /// <remarks>The input polygon might get reversed</remarks>
        public static void SlicePolygon(Polygon p, CircleNE c, Geometry g, double thickness, out List <Polygon> output)
        {
            output = new List <Polygon>();

            // Setup the two slicing circles.
            CircleNE c1 = c.Clone(), c2 = c.Clone();
            Mobius   m             = new Mobius();
            Vector3D pointOnCircle = c.IsLine ? c.P1 : c.Center + new Vector3D(c.Radius, 0);

            m.Hyperbolic2(g, c1.CenterNE, pointOnCircle, thickness / 2);
            c1.Transform(m);
            m.Hyperbolic2(g, c2.CenterNE, pointOnCircle, -thickness / 2);
            c2.Transform(m);

            // ZZZ - alter Clip method to work on Polygons and use that.

            // Slice it up.
            List <Polygon> sliced1, sliced2;

            Slicer.SlicePolygon(p, c1, out sliced1);
            Slicer.SlicePolygon(p, c2, out sliced2);

            // Keep the ones we want.
            foreach (Polygon newPoly in sliced1)
            {
                bool outside = !c1.IsPointInsideNE(newPoly.CentroidApprox);
                if (outside)
                {
                    output.Add(newPoly);
                }
            }

            foreach (Polygon newPoly in sliced2)
            {
                bool inside = c2.IsPointInsideNE(newPoly.CentroidApprox);
                if (inside)
                {
                    output.Add(newPoly);
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// ZZZ - needs to be part of performance setting?
        /// Returns true if the tile should be included after a Mobius transformation will be applied.
        /// If the tile is not be included, this method avoids applying the mobious transform to the entire tile.
        /// </summary>
        public bool IncludeAfterMobius(Mobius m)
        {
            switch (this.Geometry)
            {
            // Spherical tilings are finite, so we can always include everything.
            case Geometry.Spherical:
                return(true);

            case Geometry.Euclidean:
                return(true);                           // We'll let the number of tiles specified in the tiling control this..

            case Geometry.Hyperbolic:
            {
                //Polygon poly = Boundary.Clone();
                //poly.Transform( m );

                //bool use = (poly.Length > 0.01);

                // ZZZ - DANGER! Some transforms can cause this to lead to stackoverflow (the ones that scale the tiling up).
                //bool use = ( poly.Length > 0.01 ) && ( poly.Center.Abs() < 10 );
                //bool use = ( poly.Center.Abs() < 0.9 );	// Only disk

                CircleNE c   = VertexCircle;
                bool     use = c.CenterNE.Abs() < 0.9999;

                /*List<Vector3D> points = poly.GetEdgePoints();
                 * double maxdist = points.Max( point => point.Abs() );
                 * bool use = maxdist < 0.97;*/

                return(use);
            }
            }

            Debug.Assert(false);
            return(false);
        }
Esempio n. 10
0
 public static bool IsPointInsideFast(CircleNE c, Vector3D testPoint)
 {
     return(c.IsPointInsideFast(testPoint));
 }