Esempio n. 1
0
        private static IEnumerable <HoneycombDef> GetEuclidImageSet()
        {
            for (int p = 3; p <= 8; p++)
            {
                for (int q = 3; q <= 8; q++)
                {
                    for (int r = 3; r <= 8; r++)
                    {
                        if (!(Geometry2D.GetGeometry(p, q) == Geometry.Euclidean ||
                              Geometry2D.GetGeometry(q, r) == Geometry.Euclidean))
                        {
                            continue;
                        }

                        // Do the last as infinity
                        System.Func <int, int> iSafe = input => input == 8 ? -1 : input;
                        yield return(new HoneycombDef()
                        {
                            P = iSafe(p),
                            Q = iSafe(q),
                            R = iSafe(r)
                        });
                    }
                }
            }
        }
Esempio n. 2
0
        public static void DoStuff(Settings settings)
        {
            HoneycombDef imageData = new HoneycombDef(settings.P, settings.Q, settings.R);

            ////////////////////////////////////////////////////////////// Various things we've run over time.
            //Sandbox.CalcSelfSimilarityScale();
            //Sandbox.Check_pq_Distances();
            //HyperidealSquares();
            //S3.Hypercube();
            //R3.Geometry.Euclidean.GenEuclidean();
            //HoneycombGen.OneHoneycombOldCode();
            //AnimateCell( imageData );
            //CreateCellPovRay( imageData, "cell.pov" );
            //CreateSimplex( imageData );
            //HoneycombGen_old.OneHoneycombNew( new HoneycombDef() { P = imageData.P, Q = imageData.Q, R = imageData.R } );
            //SphericalAnimate( imageData );
            OneImage(settings);

            HoneycombDef[] scaleLarger = GetImageSet().Where(h =>
                                                             Geometry2D.GetGeometry(h.P, h.Q) == Geometry.Euclidean ||
                                                             Geometry2D.GetGeometry(h.P, h.Q) == Geometry.Spherical).ToArray();
            int count = scaleLarger.Length;
            //foreach( HoneycombAndView h in scaleLarger )
            //	Trace.WriteLine( h.FormatFilename() );

            //BatchRun( settings );
        }
Esempio n. 3
0
        private static IEnumerable <HoneycombDef> GetCoxeterSet()
        {
            yield return(new HoneycombDef()
            {
                P = 5, Q = 3, R = 4
            });

            yield return(new HoneycombDef()
            {
                P = 4, Q = 3, R = 5
            });

            yield return(new HoneycombDef()
            {
                P = 5, Q = 3, R = 5
            });

            yield return(new HoneycombDef()
            {
                P = 3, Q = 5, R = 3
            });

            for (int p = 3; p <= 6; p++)
            {
                for (int q = 3; q <= 6; q++)
                {
                    for (int r = 3; r <= 6; r++)
                    {
                        if (Geometry2D.GetGeometry(p, q) == Geometry.Spherical &&
                            Geometry2D.GetGeometry(q, r) == Geometry.Spherical)
                        {
                            continue;
                        }

                        if (Geometry2D.GetGeometry(p, q) == Geometry.Hyperbolic ||
                            Geometry2D.GetGeometry(q, r) == Geometry.Hyperbolic)
                        {
                            continue;
                        }

                        yield return(new HoneycombDef()
                        {
                            P = p,
                            Q = q,
                            R = r
                        });
                    }
                }
            }
        }
Esempio n. 4
0
        // CHEAT! (would be better to do a geometrical construction)
        // We are going to iterate to the starting point that will make all edge lengths the same.
        public static Vector3D IterateToStartingPoint(HoneycombDef?def, int[] activeMirrors, Simplex simplex)
        {
            if (activeMirrors.Length == 1)
            {
                return(simplex.Verts[activeMirrors[0]]);
            }

            // We are minimizing the output of this function,
            // because we want all edge lengths to be as close as possible.
            // Input vector should be in the Ball Model.
            Func <Vector3D, double> diffFunc = v =>
            {
                List <double> lengths = new List <double>();
                for (int i = 0; i < activeMirrors.Length; i++)
                {
                    Vector3D reflected = simplex.ReflectInFacet(v, activeMirrors[i]);
                    lengths.Add(H3Models.Ball.HDist(v, reflected));
                }

                double result  = 0;
                double average = lengths.Average();
                foreach (double length in lengths)
                {
                    result += Math.Abs(length - average);
                }
                if (Infinity.IsInfinite(result))
                {
                    result = double.PositiveInfinity;
                }
                return(result);
            };

            // So that we can leverage Euclidean barycentric coordinates, we will first convert our simplex to the Klein model.
            // We will need to take care to properly convert back to the Ball as needed.
            Vector3D[] kleinVerts = simplex.Verts.Select(v => HyperbolicModels.PoincareToKlein(v)).ToArray();
            if (def != null)
            {
                HoneycombDef d = def.Value;
                Geometry     vertexGeometry = Geometry2D.GetGeometry(d.Q, d.R);
                if (vertexGeometry == Geometry.Hyperbolic)
                {
                    kleinVerts[3] = SimplexCalcs.VertexPointKlein(d.P, d.Q, d.R);
                }
            }

            // Normalizing barycentric coords amounts to making sure the 4 coords add to 1.
            Func <Vector3D, Vector3D> baryNormalize = b =>
            {
                return(b / (b.X + b.Y + b.Z + b.W));
            };

            // Bary Coords to Euclidean
            Func <Vector3D[], Vector3D, Vector3D> baryToEuclidean = (kv, b) =>
            {
                Vector3D result =
                    kv[0] * b.X + kv[1] * b.Y + kv[2] * b.Z + kv[3] * b.W;
                return(result);
            };

            // Our starting barycentric coords (halfway between all active mirrors).
            Vector3D bary = new Vector3D();

            foreach (int a in activeMirrors)
            {
                bary[a] = 0.5;
            }
            bary = baryNormalize(bary);

            // For each iteration, we'll shrink this search offset.
            // NOTE: The starting offset and decrease factor I'm using don't guarantee convergence,
            // but it seems to be working pretty well (even when varying these parameters).
            //double searchOffset = 1.0 - bary[activeMirrors[0]];
            //double searchOffset = bary[activeMirrors[0]];
            double factor       = 1.5;          // Adjusting this helps get some to converge, e.g. 4353-1111
            double searchOffset = bary[activeMirrors[0]] / factor;

            double min        = double.MaxValue;
            int    iterations = 1000;

            for (int i = 0; i < iterations; i++)
            {
                min = diffFunc(HyperbolicModels.KleinToPoincare(baryToEuclidean(kleinVerts, bary)));
                foreach (int a in activeMirrors)
                {
                    Vector3D baryTest1 = bary, baryTest2 = bary;
                    baryTest1[a] += searchOffset;
                    baryTest2[a] -= searchOffset;
                    baryTest1     = baryNormalize(baryTest1);
                    baryTest2     = baryNormalize(baryTest2);

                    double t1 = diffFunc(HyperbolicModels.KleinToPoincare(baryToEuclidean(kleinVerts, baryTest1)));
                    double t2 = diffFunc(HyperbolicModels.KleinToPoincare(baryToEuclidean(kleinVerts, baryTest2)));
                    if (t1 < min)
                    {
                        min  = t1;
                        bary = baryTest1;
                    }
                    if (t2 < min)
                    {
                        min  = t2;
                        bary = baryTest2;
                    }
                }

                if (Tolerance.Equal(min, 0.0, 1e-14))
                {
                    System.Console.WriteLine(string.Format("Converged in {0} iterations.", i));
                    break;
                }

                searchOffset /= factor;
            }

            if (!Tolerance.Equal(min, 0.0, 1e-14))
            {
                System.Console.WriteLine("Did not converge: " + min);

                // Be a little looser before thrown an exception.
                if (!Tolerance.Equal(min, 0.0, 1e-12))
                {
                    System.Console.ReadKey(true);
                    //throw new System.Exception( "Boo. We did not converge." );
                    return(Vector3D.DneVector());
                }
            }

            Vector3D euclidean = baryToEuclidean(kleinVerts, bary);

            return(HyperbolicModels.KleinToPoincare(euclidean));
        }
Esempio n. 5
0
        private static void CreateCellPovRay(HoneycombDef def, string filename, double t = 0)
        {
            int p = def.P;
            int q = def.Q;
            int r = def.R;

            //Vector3D trans = new Vector3D( 1.0/3, 0 ) * (2 + 2 * Math.Sin( Math.PI / 6 )) * t;
            //double scale = 1.8;
            Vector3D trans = new Vector3D();
            double   scale = 1.0;

            Vector3D[] sVerts = null;               // SimplexCalcs.VertsBall( p, q, r );

            Vector3D vUHS = H3Models.BallToUHS(SimplexCalcs.VertexPointBall(p, q, r));

            // Just did this for everything.  Non-general position working better and will make all heads consistent.
            scale = 2.0;

            if (Geometry2D.GetGeometry(q, r) != Geometry.Hyperbolic)                // Vertex-centered if possible
            {
                scale = 1.0 / vUHS.Z;
            }
            //else if( Geometry2D.GetGeometry( p, q ) == Geometry.Hyperbolic ) // Make the biggest head somewhat smaller.
            //	scale = 2.0;

            Vector3D cen = InteriorPointBall;

            /*var kleinVerts = sVerts.Select( v => HyperbolicModels.PoincareToKlein( v ) );
             * Vector3D avg = new Vector3D();
             * foreach( Vector3D v in kleinVerts )
             *      avg += v;
             * avg /= kleinVerts.Count();
             * Vector3D cen = HyperbolicModels.KleinToPoincare( avg );*/
            cen  = H3Models.BallToUHS(cen);
            cen += trans;
            //cen *= scale;
            cen = H3Models.UHSToBall(cen);

            Sphere[] simplex = SimplexCalcs.Mirrors(p, q, r, moveToBall: false);

            // Apply transformations.
            simplex = simplex.Select(s =>
            {
                Sphere.TranslateSphere(s, trans);
                Sphere.ScaleSphere(s, scale);
                return(H3Models.UHSToBall(s));
            }).ToArray();

            for (int i = 0; i < 4; i++)
            {
                if (simplex[i].IsPointInside(cen))
                {
                    simplex[i].Invert = true;
                }
            }

            Sphere[] simplexForColorScale = SimplexCalcs.Mirrors(p, q, r, moveToBall: true);
            CoxeterImages.Settings temp   = AutoCalcScale(def, simplexForColorScale);
            int maxDepth = (int)temp.ColorScaling;
            //Random rand = new Random( p+q+r );
            //int randOffset = rand.Next( maxDepth );

            bool ball = true;
            bool dual = false;

            H3.Cell[] simplicesFinal = GenCell(simplex, null, cen, ball, dual);

            using (StreamWriter sw = File.CreateText(filename))                 // We need to reuse this StreamWriter (vs. calling AppendSimplex) for performance.
            {
                sw.WriteLine("#include \"hyper_ball.pov\"");

                //int[] include = new int[] { 0, 1, 2, 3 };
                int[] include = new int[] { 0 };
                if (dual)
                {
                    include = new int[] { 3 }
                }
                ;

                // Output the facets.
                foreach (H3.Cell cell in simplicesFinal)
                {
                    Sphere[] facets = cell.Facets.Select(f => f.Sphere).ToArray();
                    if (m_toKlein)
                    {
                        facets = facets.Select(s => H3Models.BallToKlein(s)).ToArray();
                    }

                    int   depth = cell.Depths[0] + 1;
                    Color c     = Coloring.ColorAlongHexagon(maxDepth, depth);
                    if (cell.Depths.Sum() % 2 == 0)
                    {
                        c = Coloring.Inverse(c);
                    }
                    PovRay.AddSimplex(sw, facets, cell.Center, include, filename, Coloring.ToVec(c));
                }

                /*include = new int[] { 1, 2, 3 };
                 * foreach( H3.Cell cell in simplicesFinal )
                 * {
                 *      Sphere[] facets = cell.Facets.Select( f => f.Sphere ).ToArray();
                 *      Color c = Color.Red;
                 *      Vector3D cv = Coloring.ToVec( c );
                 *      cv.W = 0.9;
                 *      PovRay.AddSimplex( sw, facets, cell.Center, include, filename, cv );
                 * }*/
            }

            // Output the edges/verts.
            bool includeEdges = false;

            if (includeEdges)
            {
                sVerts = sVerts.Select(v =>
                {
                    v  = H3Models.BallToUHS(v);
                    v += trans;
                    v *= scale;
                    return(H3Models.UHSToBall(v));
                }).ToArray();

                H3.Cell.Edge[] edges = Recurse.CalcEdges(simplex.Skip(1).ToArray(),
                                                         new H3.Cell.Edge[] { new H3.Cell.Edge(sVerts[2], sVerts[3], order: false) },
                                                         new Recurse.Settings()
                {
                    Threshold = 0.01
                });
                PovRay.WriteH3Edges(new PovRay.Parameters {
                    AngularThickness = 0.01
                }, edges, filename, append: true);

                HashSet <Vector3D> verts = new HashSet <Vector3D>();
                foreach (H3.Cell.Edge e in edges)
                {
                    verts.Add(e.End);
                }
                PovRay.WriteVerts(new PovRay.Parameters {
                    AngularThickness = 0.02
                }, Geometry.Hyperbolic, verts.ToArray(), filename, append: true);
            }
        }
Esempio n. 6
0
        private static void HoneycombFiniteVertexFig(HoneycombDef def, int lod, Dictionary <Vector3D, H3.Cell> complete)
        {
            int p = def.P;
            int q = def.Q;
            int r = def.R;

            double   scale = 1.0;
            Vector3D vUHS  = H3Models.BallToUHS(SimplexCalcs.VertexPointBall(p, q, r));

            if (Geometry2D.GetGeometry(q, r) != Geometry.Hyperbolic)                // Vertex-centered if possible
            {
                scale = 1.0 / vUHS.Z;
            }
            System.Func <Vector3D, Vector3D> trans = v =>
            {
                v  = H3Models.BallToUHS(v);
                v *= scale;
                v  = H3Models.UHSToBall(v);
                return(v);
            };

            bool ball = true;

            Sphere[] simplex = SimplexCalcs.Mirrors(p, q, r, moveToBall: ball);
            simplex = simplex.Select(s =>
            {
                s = H3Models.BallToUHS(s);
                Sphere.ScaleSphere(s, scale);
                s = H3Models.UHSToBall(s);
                return(s);
            }).ToArray();
            H3.Cell.Edge[] edges = SimplexCalcs.SimplexEdgesBall(p, q, r);

            // Two edges of the simplex facet.
            // NOTE: This contruction only works for material triangles, and matches the construction in the TextureHelper.
            m_div = TextureHelper.SetLevels(lod);
            int[]           elementIndices = TextureHelper.TextureElements(1, lod);
            List <Vector3D> points         = new List <Vector3D>();

            H3.Cell.Edge e1 = edges[2];
            H3.Cell.Edge e2 = edges[3];
            Vector3D     p1 = trans(e1.Start), p2 = trans(e1.End), p3 = trans(e2.End);

            Vector3D[] points1 = H3Models.Ball.GeodesicPoints(p2, p1, m_div);
            Vector3D[] points2 = H3Models.Ball.GeodesicPoints(p3, p1, m_div);
            for (int i = 0; i < m_div; i++)
            {
                points.AddRange(H3Models.Ball.GeodesicPoints(points1[i], points2[i], m_div - i));
            }
            points.Add(p1);

            Mesh mesh = new Mesh();

            for (int i = 0; i < elementIndices.Length / 3; i++)
            {
                int      idx1 = i * 3;
                int      idx2 = i * 3 + 1;
                int      idx3 = i * 3 + 2;
                Vector3D v1   = points[elementIndices[idx1]];
                Vector3D v2   = points[elementIndices[idx2]];
                Vector3D v3   = points[elementIndices[idx3]];
                mesh.Triangles.Add(new Mesh.Triangle(v1, v2, v3));
            }

            // AuxPoints will be used for multiple things.
            // - The first is a definition point for a face, so we can check for duplicates.
            // - We'll also store the points for the 3 edges of our fundamental triangle.
            List <Vector3D> auxPoints = new List <Vector3D>();
            {
                auxPoints.Add((p1 + p2 + p3) / 3);
                auxPoints.AddRange(points1);
                auxPoints.AddRange(points2.Reverse());
                auxPoints.AddRange(H3Models.Ball.GeodesicPoints(points2[0], points1[0], m_div));
            }

            Vector3D cen = HoneycombPaper.InteriorPointBall;

            H3.Cell[] simplices = GenCell(simplex, mesh, cen, auxPoints.ToArray(), ball);

            // Existing cells take precedence.
            foreach (H3.Cell c in simplices)
            {
                Vector3D t = c.AuxPoints[0];
                H3.Cell  dummy;
                if (!complete.TryGetValue(t, out dummy))
                {
                    complete[t] = c;
                }
            }
        }