示例#1
0
        public void AnimationSections(Settings config)
        {
            HoneycombDef imageData = new HoneycombDef(config.P, config.Q, config.R);
            int          p = imageData.P, q = imageData.Q, r = imageData.R;

            string filename = imageData.FormatFilename();

            Sphere[] mirrors = SimplexCalcs.Mirrors(p, q, r);
            double   bounds  = 1.0;          //config.UhsBoundary.Bounds;

            bounds = 9.0;

            // Calculate the color scale.
            int size = 200;

            CoxeterImages.Settings settings = new CoxeterImages.Settings()
            {
                Honeycomb = imageData,
                Width     = size,
                Height    = size,
                Bounds    = bounds,
                Mirrors   = mirrors,
                FileName  = imageData.FormatFilename(),
            };

            CoxeterImages imageCalculator = new CoxeterImages();

            //imageCalculator.AutoCalcScale( settings );
            if (settings.ColorScaling < 1)
            {
                settings.ColorScaling = 15;
            }
            settings.ColorScaling = 11;

            Program.Log("\nGenerating sections...");
            size              = 500;
            settings.Width    = size;
            settings.Height   = size;
            settings.FileName = filename;

            double max = Spherical2D.e2sNorm(15);
            double min = Spherical2D.e2sNorm(1.0 / 15);

            DonHatch.e2hNorm(max);
            int    numSteps = 1800;          // 1 minute
            double step     = (max - min) / numSteps;

            for (int i = 0; i < 1; i++)
            {
                Program.Log("\nSection " + i);
                imageCalculator.m_z = 1.0 / 0.5;
                Spherical2D.s2eNorm(min + step * i);
                DonHatch.h2eNorm(step * i);
                settings.FileName = string.Format("533_{0:D4}.png", i);
                imageCalculator.GenImage(settings);
            }
        }
示例#2
0
        public static void Create(HoneycombDef def, string filename)
        {
            int p = def.P;
            int q = def.Q;
            int r = def.R;

            double   scale = 5.0;
            Vector3D cen   = HoneycombPaper.InteriorPointBall;

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

            // Apply transformations.
            simplex = simplex.Select(s =>
            {
                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   = HoneycombPaper.AutoCalcScale(def, simplexForColorScale);
            int maxDepth = (int)temp.ColorScaling;

            bool ball = true;
            bool dual = false;

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

            simplicesFinal = simplicesFinal.Where(s => s.Depths[0] < 1).ToArray();
            //simplicesFinal = simplicesFinal.Where( s => s.)

            // Output the facets.
            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 };
                foreach (H3.Cell cell in simplicesFinal)
                {
                    Sphere[] facets = cell.Facets.Select(f => f.Sphere).ToArray();
                    int      depth  = cell.Depths[0] + 1;
                    Color    c      = Coloring.ColorAlongHexagon(maxDepth, depth);
                    PovRay.AddSimplex(sw, facets, cell.Center, include, filename, Coloring.ToVec(c));
                }
            }
        }
示例#3
0
        private static Sphere[] Simplex(ref Vector3D cen)
        {
            int p = 7;
            int q = 3;
            int r = 3;

            // For vertex-centered.
            //Vector3D v = SimplexCalcs.VertexPointBall( p, q, r );
            //v = H3Models.BallToUHS( v );

            bool ball = true;

            Sphere[] simplex = SimplexCalcs.Mirrors(p, q, r, ref cen, moveToBall: ball /*, scaling: 1.0/v.Abs()*/);
            return(simplex);
        }
示例#4
0
        public static void OneImage(Settings config, double t = 0.0)
        {
            HoneycombDef imageData = new HoneycombDef(config.P, config.Q, config.R);
            int          p = imageData.P, q = imageData.Q, r = imageData.R;

            string filename = imageData.FormatFilename();

            //if( File.Exists( filename ) )
            //	return;

            Sphere[] mirrors = SimplexCalcs.Mirrors(p, q, r);
            double   bounds  = config.UhsBoundary.Bounds;

            // Calculate the color scale.
            int size = 200;

            CoxeterImages.Settings settings = new CoxeterImages.Settings()
            {
                Honeycomb = imageData,
                Width     = size,
                Height    = size,
                Bounds    = bounds,
                Mirrors   = mirrors,
                FileName  = imageData.FormatFilename(),
            };

            CoxeterImages imageCalculator = new CoxeterImages();

            imageCalculator.AutoCalcScale(settings);
            if (settings.ColorScaling < 1)
            {
                settings.ColorScaling = 15;
            }

            Program.Log("\nGenerating full image...");
            size              = 500;
            settings.Width    = config.UhsBoundary.ImageWidth;
            settings.Height   = config.UhsBoundary.ImageHeight;
            settings.FileName = filename;
            imageCalculator.GenImage(settings, t);
        }
示例#5
0
        private static void CreateSimplex(HoneycombDef imageData)
        {
            int p = imageData.P;
            int q = imageData.Q;
            int r = imageData.R;

            Vector3D cen  = InteriorPointBall;
            bool     ball = true;

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

            // Offset as we do for the boundary images.
            //Sphere s = H3Models.UHSToBall( simplex[0] );
            //s = CoxeterImages.GeodesicOffset( s, 0.02, ball: true );

            if (m_toKlein)
            {
                simplex = simplex.Select(s => H3Models.BallToKlein(s)).ToArray();
            }

            int[] include = new int[] { 0, 1, 2, 3 };                   // All facets
            //int[] include = new int[] { 1 };
            File.Delete("simplex.pov");
            PovRay.AppendSimplex(simplex, cen, include, "simplex.pov");

            bool includeEdges = false;

            if (includeEdges)
            {
                H3.Cell.Edge[] edges = SimplexCalcs.SimplexEdgesUHS(p, q, r);
                PovRay.WriteEdges(new PovRay.Parameters {
                    Halfspace = true, AngularThickness = 0.03
                },
                                  Geometry.Hyperbolic, edges, "simplex.pov", append: true);
            }
        }
示例#6
0
        private static void OneAnimationFrame(HoneycombDef imageData, string filename, double colorScaling, double t = 0.0)
        {
            int p = imageData.P, q = imageData.Q, r = imageData.R;

            Sphere[] mirrors = SimplexCalcs.Mirrors(p, q, r);

            int size = 750;

            size = 1024;
            CoxeterImages.Settings settings = new CoxeterImages.Settings()
            {
                Honeycomb = imageData,
                Width     = size * 2,
                Height    = size,
                Bounds    = 1.0,
                Mirrors   = mirrors,
                FileName  = filename,
            };

            CoxeterImages imageCalculator = new CoxeterImages();

            settings.ColorScaling = colorScaling;
            imageCalculator.GenImage(settings, t);
        }
示例#7
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));
        }
示例#8
0
        public static H3.Cell.Edge[] OneHoneycombOrthoscheme(HoneycombDef def, int[] active, int baseHue, Settings settings = null)
        {
            // Setup parameters.
            int numEdges = 250000;

            if (settings != null)
            {
                active   = settings.PovRay.Active;
                def      = new HoneycombDef(settings.P, settings.Q, settings.R);
                numEdges = settings.PovRay.NumEdges;
            }

            CalcThickness(active);
            if (settings != null)
            {
                H3.m_settings.AngularThickness = settings.PovRay.EdgeWidth;                     // ZZZ - should really stop using that settings class.
            }
            string baseName      = BaseName(def);
            string mirrorsString = ActiveMirrorsString(active);
            string suffix        = "-" + mirrorsString;
            string fileName      = baseName + suffix;

            if (ViewPath != null)
            {
                fileName += string.Format("_{0:D4}", ViewPath.Step);
            }

            if (File.Exists(fileName + ".pov"))
            {
                File.Delete(fileName + ".pov");
                //Console.WriteLine( string.Format( "Skipping {0}", fileName ) );
                //return;
            }

            Program.Log(string.Format("Building {0}", fileName));

            // The wiki mirrors are labeled in the reverse of ours.
            Func <int, int> mapMirror = i => 3 - i;

            active = active.Select(i => mapMirror(i)).OrderBy(i => i).ToArray();

            Simplex simplex = new Simplex();

            simplex.Facets = SimplexCalcs.Mirrors(def.P, def.Q, def.R);
            simplex.Verts  = SimplexCalcs.VertsBall(def.P, def.Q, def.R);

            Vector3D startingPoint = IterateToStartingPoint(def, active, simplex);

            if (startingPoint.DNE)
            {
                return(null);
            }
            List <H3.Cell.Edge> startingEdges = new List <H3.Cell.Edge>();

            foreach (int a in active)
            {
                Vector3D reflected = simplex.ReflectInFacet(startingPoint, a);
                startingEdges.Add(new H3.Cell.Edge(startingPoint, reflected));
                //startingEdges.Add( new H3.Cell.Edge( simplex.Verts[0], simplex.Verts[3] ) );	// Used for Borromean Rings complement image.
            }

            if (false)
            {
                Vector3D[] kv = simplex.Verts.Select(v => HyperbolicModels.PoincareToKlein(v)).ToArray();
                kv[3] = SimplexCalcs.VertexPointKlein(def.P, def.Q, def.R);
                Vector3D t       = (kv[3] - kv[0]) * 0.5;
                Sphere   gSphere = H3Models.Ball.OrthogonalSphereInterior(HyperbolicModels.KleinToPoincare(t));
                gSphere = H3Models.BallToKlein(gSphere);
                Vector3D t2 = Euclidean3D.IntersectionPlaneLine(gSphere.Normal, gSphere.Offset, kv[3] - kv[2], kv[2]);
                //t2 = kv[2] + ( kv[3] - kv[2]) * 0.5;

                t  = HyperbolicModels.KleinToPoincare(t);
                t2 = HyperbolicModels.KleinToPoincare(t2);
                startingEdges.Add(new H3.Cell.Edge(t, t2));
                startingEdges.Add(new H3.Cell.Edge(t, simplex.ReflectInFacet(t, 3)));
            }

            // If we are doing a view path, transform our geometry.
            if (ViewPath != null)
            {
                //Vector3D p = new Vector3D( 0, 0, .5 );
                Vector3D p = new Vector3D(0.08, 0.12, 0.07);
                simplex.Facets = simplex.Facets.Select(f => H3Models.Transform_PointToOrigin(f, p)).ToArray();
                simplex.Verts  = simplex.Verts.Select(v => H3Models.Transform_PointToOrigin(v, p)).ToArray();
                startingEdges  = startingEdges.Select(e => new H3.Cell.Edge(
                                                          H3Models.Transform_PointToOrigin(e.Start, p),
                                                          H3Models.Transform_PointToOrigin(e.End, p))).ToList();
            }

            SetupBaseHue(fileName, mirrorsString, baseHue);
            Recurse.m_background = baseHue == -1 ? new Vector3D() : new Vector3D(baseHue, 1, .1);

            H3.Cell.Edge[] edges = Recurse.CalcEdgesSmart2(simplex.Facets, startingEdges.ToArray(), numEdges);
            //H3.Cell.Edge[] edges = Recurse.CalcEdges( simplex.Facets, startingEdges.ToArray(),
            //	new Recurse.Settings() { ThreshType = Recurse.EdgeThreshType.Radial, Threshold = H3Models.Ball.FindLocationForDesiredRadius( settings.PovRay.EdgeWidth, 0.8/100 ) } );
            //edges = edges.Where( e => e.Depths[0] % 2 == 1 ).ToArray();	// Used for Borromean Rings complement image.

            // Shapeways truncated 436.
            if (false)
            {
                if (true)
                {
                    Mobius m = Mobius.Scale(1.0 / H3Models.UHS.ToE(Honeycomb.InRadius(def.P, def.Q, def.R)));
                    double a = -Math.PI / 2 + Math.Asin(1 / Math.Sqrt(3));
                    edges = edges.Select(e =>
                    {
                        Vector3D v1 = e.Start;
                        Vector3D v2 = e.End;
                        v1.RotateAboutAxis(new Vector3D(1, 0, 0), a);
                        v2.RotateAboutAxis(new Vector3D(1, 0, 0), a);
                        v1 = H3Models.Ball.ApplyMobius(m, v1);
                        v2 = H3Models.Ball.ApplyMobius(m, v2);
                        return(new H3.Cell.Edge(v1, v2));
                    }).ToArray();

                    double   thresh  = -.01;
                    Vector3D looking = new Vector3D(0, 0, -1);
                    edges = edges.Where(e => e.Start.Dot(looking) > thresh && e.End.Dot(looking) > thresh).ToArray();

                    Dictionary <H3.Cell.Edge, int> edgeDict = edges.ToDictionary(e => e, e => 1);
                    H3.RemoveDanglingEdgesRecursive(edgeDict);
                    edges = edgeDict.Keys.ToArray();
                }
                else
                {
                    Mobius m = Mobius.Scale(2);
                    edges = edges.Select(e =>
                    {
                        Vector3D v1 = e.Start;
                        Vector3D v2 = e.End;
                        v1          = H3Models.Ball.ApplyMobius(m, v1);
                        v2          = H3Models.Ball.ApplyMobius(m, v2);
                        return(new H3.Cell.Edge(v1, v2));
                    }).ToArray();

                    Dictionary <H3.Cell.Edge, int> edgeDict = edges.ToDictionary(e => e, e => 1);
                    H3.RemoveDanglingEdgesRecursive(edgeDict);
                    edges = edgeDict.Keys.ToArray();
                }
            }

            //H3.m_settings.Output = H3.Output.STL;
            //H3.m_settings.Scale = 50;
            H3.SaveToFile(fileName, edges, finite: true, append: true);

            bool doCells = false;

            H3.Cell[] cellsToHighlight = null;
            if (doCells)
            {
                int[] polyMirrors = new int[] { 1, 2, 3 };
                active = active.Select(i => mapMirror(i)).OrderBy(i => i).ToArray();

                H3.Cell startingCell = PolyhedronToHighlight(Geometry.Hyperbolic, polyMirrors, simplex, startingPoint);
                cellsToHighlight = Recurse.CalcCells(simplex.Facets, new H3.Cell[] { startingCell });
                H3.AppendFacets(fileName, cellsToHighlight);
            }

            return(edges);
        }
示例#9
0
        public static void Test()
        {
            HoneycombDef def     = new HoneycombDef(5, 3, 4);
            Simplex      simplex = new Simplex();

            simplex.Facets = SimplexCalcs.Mirrors(def.P, def.Q, def.R);

            // Simplices will be the "cells"
            H3.Cell.Facet[] simplexFacets = simplex.Facets.Select(m => new H3.Cell.Facet(m)).ToArray();
            H3.Cell         startingCell  = new H3.Cell(simplexFacets);
            startingCell.AuxPoints = SimplexCalcs.VertsBall(def.P, def.Q, def.R);
            startingCell.Center    = HoneycombPaper.InteriorPointBall;

            var cells = CalcCells(simplex.Facets, new H3.Cell[] { startingCell });

            // Get all the cell centers
            HashSet <Vector3D> centers = new HashSet <Vector3D>();

            foreach (var cell in cells)
            {
                Vector3D cellCen = cell.AuxPoints[0];
                centers.Add(cellCen);
            }

            // Colors.
            Dictionary <double, Color> colors = new Dictionary <double, Color>(new DoubleEqualityComparer());

            System.Random rand = new System.Random(0);

            // Get all the in-spheres
            double inRad = startingCell.AuxPoints[1].Abs();
            //inRad *= 1.16;
            List <Sphere> inSpheres = new List <Sphere>();

            foreach (Vector3D c in centers)
            {
                Vector3D p = c;
                //SphericalModels.GnomonicToStereo( c );
                Geometry g = Geometry.Hyperbolic;

                Vector3D cen;
                double   rad;
                H3Models.Ball.DupinCyclideSphere(p, inRad, g, out cen, out rad);
                Sphere i = new Sphere(cen, rad);

                Color color;
                if (!colors.TryGetValue(c.Abs(), out color))
                {
                    Vector3D rgb = ColorUtil.CHSL2RGB(new Vector3D(rand.NextDouble() * 360, .5, .5));
                    rgb            *= 255;
                    color           = Color.FromArgb(255, (int)rgb.X, (int)rgb.Y, (int)rgb.Z);
                    colors[c.Abs()] = color;
                }
                i.Color = color;

                inSpheres.Add(i);
            }

            // Project sphere to unit sphere.
            List <Circle3D> circlesOnUnitSphere = new List <Circle3D>();

            foreach (Sphere i in inSpheres)
            {
                if (i.Center.IsOrigin || i.Center.DNE || Infinity.IsInfinite(i.Center))
                {
                    continue;
                }

                Sphere   orthogonal = new Sphere(new Vector3D(), RadiusOrthogonal(i));
                Circle3D c          = orthogonal.Intersection(i);

                // We need to scale this based on the size of the orthogonal sphere.
                c.Center /= orthogonal.Radius;
                c.Radius /= orthogonal.Radius;
                c.Color   = i.Color;
                circlesOnUnitSphere.Add(c);
            }
            Circle3D unit = new Circle3D();

            //circlesOnUnitSphere.Add( unit );

            ProjectAndSave(circlesOnUnitSphere);
        }
示例#10
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);
            }
        }
示例#11
0
        /// <summary>
        /// This generates a honeycomb by reflecting in 4 mirrors of the fundamental simplex.
        /// This "new" method is now old.
        /// </summary>
        public static void OneHoneycombNew(HoneycombDef imageData)
        {
            int p = imageData.P;
            int q = imageData.Q;
            int r = imageData.R;

            double thickness           = 0.05;
            double thicknessSpherical  = Spherical2D.s2eNorm(thickness);
            double thicknessHyperbolic = R3.Math.DonHatch.h2eNorm(thickness);
            double threshold           = 1;

            H3.Cell.Edge[] edges            = null;
            H3.Cell[]      cellsToHighlight = null;
            Sphere[]       simplex          = null;
            Vector3D       vertex           = new Vector3D();

            Geometry g = Util.GetGeometry(p, q, r);

            if (g == Geometry.Spherical)
            {
                thickness = thicknessSpherical /*.07 for 333*/  /* 0.05for 433*/  /*.025 for 533,335*/;
                threshold = 10000;

                simplex = SimplexCalcs.MirrorsSpherical(p, q, r);
                vertex  = SimplexCalcs.VertexSpherical(p, q, r);

                // Ugly special casing for 333, since it has a vertex project to infinity.
                if (p == 3 && q == 3 && r == 3)
                {
                    SpecialCase333();
                }
            }
            else if (g == Geometry.Euclidean)
            {
                thickness = thickness / 2;
                threshold = 1 /*20*/;

                //SimplexCalcs.CalcEScale();
                simplex = SimplexCalcs.MirrorsEuclidean();
                Vector3D[] verts = SimplexCalcs.VertsEuclidean();
                vertex = verts[2];
            }
            else
            {
                thickness = thicknessHyperbolic;
                threshold = 0.01;

                simplex = SimplexCalcs.Mirrors(p, q, r);
                Vector3D[] verts = SimplexCalcs.VertsBall(p, q, r);
                vertex = verts[2];

                //Vector3D[] simplexVerts = SimplexCalcs.VertsBall( p, q, r );
                //H3.Cell.Edge edge = new H3.Cell.Edge( simplexVerts[2], simplexVerts[3] );
                //H3.Cell.Edge edge = SimplexCalcs.HoneycombEdgeBall( p, q, r );
                //H3.Cell.Edge[] startingEdges = new H3.Cell.Edge[] { edge };

                //H3.Cell.Edge[] edges = Recurse.CalcEdgesSmart2( simplex, startingEdges );

                // Vertex Centered.
                bool vertexCentered = false;
                if (vertexCentered)
                {
                    Vector3D v = SimplexCalcs.VertexPointBall(p, q, r);
                    v = H3Models.BallToUHS(v);
                    double scale = 1.0 / v.Abs();
                    edges = edges.Select(e =>
                    {
                        Vector3D start = H3Models.UHSToBall(H3Models.BallToUHS(e.Start) * scale);
                        Vector3D end   = H3Models.UHSToBall(H3Models.BallToUHS(e.End) * scale);
                        return(new H3.Cell.Edge(start, end));
                    }).ToArray();
                }

                // Code to show endpoints of 535

                /*using( StreamWriter sw = File.CreateText( "535_points.pov" ) )
                 * {
                 *      HashSet<Vector3D> verts = new HashSet<Vector3D>();
                 *      foreach( H3.Cell.Edge e in edges )
                 *      {
                 *              verts.Add( Sterographic.SphereToPlane( e.Start ) );
                 *              verts.Add( Sterographic.SphereToPlane( e.End ) );
                 *      }
                 *
                 *      foreach( Vector3D vert in verts )
                 *              if( !Infinity.IsInfinite( vert ) )
                 *                      sw.WriteLine( PovRay.Sphere( new Sphere() { Center = vert, Radius = 0.01 } ) );
                 * }*/
            }

            // Recurse
            bool dual = false;
            {
                H3.Cell.Edge[] startingEdges = null;
                if (dual)
                {
                    startingEdges = new H3.Cell.Edge[] { SimplexCalcs.DualEdgeBall(simplex) }
                }
                ;
                else
                {
                    //startingEdges = new H3.Cell.Edge[] { SimplexCalcs.HoneycombEdgeBall( simplex, vertex ) };
                    Vector3D[] verts  = SimplexCalcs.VertsEuclidean();
                    Vector3D   v1     = verts[0] + 2 * verts[2];             // adjacent cube center
                    Vector3D   corner = verts[3];

                    startingEdges = new H3.Cell.Edge[] { new H3.Cell.Edge(v1, corner) };
                }

                edges = Recurse.CalcEdges(simplex, startingEdges, new Recurse.Settings()
                {
                    G = g, Threshold = threshold
                });

                edges = edges.Where(e =>
                {
                    int sum = e.Depths.Count(d => d == 0);
                    return(true);
                }).ToArray();

                //CullHalfOfEdges( ref edges );

                // No need to cull edges in spherical case.
                // This was just to generate some images for 350-cell paper.
                //edges = Cull120Cell( edges );

                Simplex tet = new Simplex();
                tet.Facets = simplex;

                if (dual)
                {
                    H3.Cell.Edge[] oneDualCell = edges.Where(e => e.Depths[2] == 0).ToArray();
                    simplex = simplex.Skip(1).ToArray();
                    edges   = Recurse.CalcEdges(simplex, oneDualCell, new Recurse.Settings()
                    {
                        G = g, Threshold = threshold
                    });

                    int[]   polyMirrors  = new int[] { 0, 1, 3 };
                    H3.Cell startingCell = HoneycombGen.PolyhedronToHighlight(g, polyMirrors, tet, new Vector3D());
                    cellsToHighlight = Recurse.CalcCells(simplex, new H3.Cell[] { startingCell });
                    //cellsToHighlight = new H3.Cell[] { startingCell };
                    //cellsToHighlight = cellsToHighlight.Skip( 7 ).ToArray();
                }
                else
                {
                    int[]   polyMirrors  = new int[] { 1, 2, 3 };
                    H3.Cell startingCell = HoneycombGen.PolyhedronToHighlight(g, polyMirrors, tet, vertex);
                    //cellsToHighlight = Recurse.CalcCells( simplex, new H3.Cell[] { startingCell } );
                    cellsToHighlight = new H3.Cell[] { startingCell };
                }

                // Include just one cell?
                bool includeOne = false;
                if (includeOne)
                {
                    edges = edges.Where(e => e.Depths[0] == 0).ToArray();
                    //cellsToHighlight = cellsToHighlight.Where( c => c.Depths[0] == 0 ).ToArray();
                }
            }

            // Rotate
            bool rotate = false;

            if (rotate)
            {
                CompoundOfFive24Cells(ref edges);
            }

            // Write the file
            bool pov = true;

            if (pov)
            {
                string filename = string.Format("{0}{1}{2}.pov", p, q, r);
                PovRay.WriteEdges(new PovRay.Parameters()
                {
                    AngularThickness = thickness
                }, g, edges,
                                  filename, append: false);
                //File.Delete( filename );
                //PovRay.AppendFacets( cellsToHighlight, filename );

                HashSet <Vector3D> verts = new HashSet <Vector3D>();
                foreach (H3.Cell.Edge e in edges)
                {
                    verts.Add(e.Start);
                    verts.Add(e.End);
                }

                /*foreach( Vector3D v in verts )
                 * {
                 *      Vector3D t = v;
                 *      t.Normalize();
                 *      t *= 0.9;
                 *      System.Diagnostics.Trace.WriteLine( string.Format( "light_source {{ <{0},{1},{2}> White*.2 }}", t.X, t.Y, t.Z ) );
                 * }*/


                /*
                 * // Include the standard pov stuff, so we can batch this.
                 * string fileName = imageData.FormatFilename( string.Empty );
                 * using( StreamWriter sw = File.CreateText( fileName + ".pov" ) )
                 * {
                 *      sw.WriteLine( "#include \"C:\\Users\\hrn\\Documents\\roice\\povray\\paper\\H3.pov\"" );
                 * }
                 *
                 * bool dummy = true;	// Doesn't matter for Pov-Ray, just Shapeways meshes.
                 * H3.SaveToFile( fileName, edges, dummy, append: true );
                 */
            }
            else
            {
                if (g == Geometry.Spherical)
                {
                    edges = edges.Where(e => e.Start.Valid() && e.End.Valid() && !Infinity.IsInfinite(e.Start) && !Infinity.IsInfinite(e.End)).ToArray();
                    S3.EdgesToStl(edges);
                }
                else
                {
                    throw new System.NotImplementedException();
                }
            }
        }
示例#12
0
        private static void CompoundOfFive24Cells(ref H3.Cell.Edge[] edges)
        {
            List <H3.Cell.Edge> allEdges = new List <H3.Cell.Edge>();

            Vector3D v600 = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 3, 5));
            Vector3D v24  = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 4, 3));

            Sphere[] mirrors600 = SimplexCalcs.MirrorsSpherical(3, 3, 5);

            double a24  = v24.AngleTo(Sterographic.R3toS3(new Vector3D()));
            double a600 = v600.AngleTo(Sterographic.R3toS3(new Vector3D()));

            Matrix4D m600  = Matrix4D.MatrixToRotateinCoordinatePlane(a600, 2, 3);
            Matrix4D m600_ = Matrix4D.MatrixToRotateinCoordinatePlane(-a600, 2, 3);
            Matrix4D m24   = Matrix4D.MatrixToRotateinCoordinatePlane(a24, 2, 3);
            Matrix4D m24_  = Matrix4D.MatrixToRotateinCoordinatePlane(-a24, 2, 3);

            double eLength = 2 * Math.PI / 10;                  // 600-cell edge length
            double a_id    = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 2));

            eLength = 1.0 / Math.Sin(2 * Math.PI / 5);                  // icosahedron edge length
            double a_i = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 5));

            Func <Vector3D, Vector3D> rot600 = v =>
            {
                v = Sterographic.R3toS3(v);
                v = m600.RotateVector(v);
                v = Sterographic.S3toR3(v);
                return(v);
            };

            Func <Vector3D, int, Vector3D> rotOne = (v, idx) =>
            {
                v = Sterographic.R3toS3(v);
                v = m24.RotateVector(v);
                v = Sterographic.S3toR3(v);
                v.RotateAboutAxis(new Vector3D(1, 0, 0), -a_id);

                // Vertex to cell center.
                v = Sterographic.R3toS3(v);
                v = m600_.RotateVector(v);
                v = Sterographic.S3toR3(v);

                List <int> reflections = new List <int>();
                if (idx == 0)
                {
                    reflections.Add(2);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(1);
                    reflections.Add(2);
                }

                if (idx != 0)
                {
                    reflections.Add(3);
                }
                if (idx == 2)
                {
                    reflections.Add(1);
                    reflections.Add(2);
                }
                if (idx == 3)
                {
                    reflections.Add(2);
                    reflections.Add(1);
                }
                if (idx == 4)
                {
                    reflections.Add(1);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(0);
                    reflections.Add(1);
                }

                foreach (int reflection in reflections)
                {
                    v = mirrors600[reflection].ReflectPoint(v);
                }

                v = Sterographic.R3toS3(v);
                v = m600.RotateVector(v);
                v = Sterographic.S3toR3(v);

                //v.RotateAboutAxis( new Vector3D( 0, 0, 1 ), Math.PI/3 );
                //v.RotateAboutAxis( new Vector3D( 1, 0, 0 ), -a_i*2 );
                v = Sterographic.R3toS3(v);
                //v = m24_.RotateVector( v );
                v = Sterographic.S3toR3(v);


                return(v);
            };

            for (int i = 0; i < 5; i++)
            {
                //if( i == 0 )
                //	continue;

                allEdges.AddRange(edges.Select(e =>
                {
                    H3.Cell.Edge newEdge = new H3.Cell.Edge(rotOne(e.Start, i), rotOne(e.End, i));
                    //H3.Cell.Edge newEdge = new H3.Cell.Edge( rot600( e.Start ), rot600( e.End ) );
                    switch (i)
                    {
                    case 0:
                        newEdge.Color = new Vector3D(1, 0, 0, 1);
                        //newEdge.Color = new Vector3D( 1, 1, 1, 0 );
                        break;

                    case 1:
                        newEdge.Color = new Vector3D(0, 1, 0, 2);
                        break;

                    case 2:
                        newEdge.Color = new Vector3D(0, 0, 1, 3);
                        break;

                    case 3:
                        newEdge.Color = new Vector3D(1, 0, 1, 4);
                        break;

                    case 4:
                        newEdge.Color = new Vector3D(0, 1, 1, 5);
                        break;
                    }
                    return(newEdge);
                }));
            }

            edges = allEdges.ToArray();

            //edges = edges.Where( e => Tolerance.Equal( 1, e.Start.Abs() ) || Tolerance.Equal( 1, e.End.Abs() ) ).ToArray();

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

            foreach (H3.Cell.Edge e in edges)
            {
                uniqueVerts.Add(e.Start);
                uniqueVerts.Add(e.End);
            }
            System.Diagnostics.Trace.WriteLine("Number of verts = " + uniqueVerts.Count);

            /*edges = edges.Where( e =>
             * {
             *      Vector3D v = Tolerance.Equal( 1, e.Start.Abs() ) ? e.End : e.Start;
             *      if( v.Abs() >= 0.8 || v.Abs() <= 0.7 )
             *              return false;
             *
             *      if( Tolerance.LessThanOrEqual( v.X, 0 ) || Tolerance.GreaterThanOrEqual( v.Y, 0 ) || Tolerance.GreaterThanOrEqual( v.Z, 0 ) )
             *              return false;
             *
             *      return true;
             * } ).ToArray();
             *
             * edges = edges.OrderBy( e => Tolerance.Equal( 1, e.Start.Abs() ) ? e.End.Abs() : e.Start.Abs() ).ToArray();*/
        }
示例#13
0
        /// <summary>
        /// Create an STL file for a cell.
        /// Currently only works for cells with both hyperideal vertices and cells.
        /// </summary>
        public static void HoneycombHyperidealLegs(HoneycombDef def, int lod, Dictionary <Vector3D, H3.Cell> complete)
        {
            int p = def.P;
            int q = def.Q;
            int r = def.R;

            m_div = TextureHelper.SetLevels(lod);

            bool ball = false;

            Sphere[]       simplex = SimplexCalcs.Mirrors(p, q, r, moveToBall: ball);
            H3.Cell.Edge[] edges;
            if (ball)
            {
                edges = SimplexCalcs.SimplexEdgesBall(p, q, r);
            }
            else
            {
                edges = SimplexCalcs.SimplexEdgesUHS(p, q, r);
            }

            // Two edges of one simplex facet.
            H3.Cell.Edge e1 = edges[2];
            H3.Cell.Edge e2 = edges[3];
            Vector3D[]   points1, points2;
            if (ball)
            {
                points1 = H3Models.Ball.GeodesicPoints(e1.Start, e1.End, 2 * m_div);
                points2 = H3Models.Ball.GeodesicPoints(e2.Start, e2.End, 2 * m_div);
            }
            else
            {
                points1 = H3Models.UHS.GeodesicPoints(e1.Start, e1.End, 2 * m_div);
                points2 = H3Models.UHS.GeodesicPoints(e2.Start, e2.End, 2 * m_div);
            }

            Sphere cellSphere   = simplex[0];
            Sphere vertexSphere = simplex[3];

            // Because one vertex the facet triangle is hyperideal, it will actually look like a square.
            List <Vector3D[]> allPoints = new List <Vector3D[]>();

            for (int i = 0; i < points1.Length; i++)
            {
                Vector3D p1 = points1[i];
                Vector3D p2 = points2[i];

                Vector3D[] arcPoints;
                if (i == points1.Length - 1)
                //if( false )
                {
                    // NOTE: This arc is not generally geodesic!
                    // Or is it?
                    arcPoints = ball ?
                                H3Models.Ball.GeodesicPoints(p1, p2, m_div) :
                                H3Models.UHS.GeodesicPoints(p1, p2, m_div);

                    /*Circle3D arc = cellSphere.Intersection( vertexSphere );
                     * double angleTot = (p1 - arc.Center).AngleTo( p2 - arc.Center );
                     * arcPoints = Shapeways.CalcArcPoints( arc.Center, arc.Radius, p1, arc.Normal, -angleTot, div );*/
                }
                else
                {
                    Circle3D c        = Circle3D.FromCenterAnd2Points(cellSphere.Center, p1, p2);
                    double   angleTot = (p1 - c.Center).AngleTo(p2 - c.Center);
                    arcPoints = Shapeways.CalcArcPoints(cellSphere.Center, cellSphere.Radius, p1, c.Normal, -angleTot, m_div);
                }
                //Vector3D[] arcPoints = new Vector3D[] { p1, p2 };
                allPoints.Add(arcPoints);
            }

            // Create the triangles for the patch.
            Mesh mesh = new Mesh();

            for (int i = 0; i < allPoints.Count - 1; i++)
            {
                Vector3D[] arc1 = allPoints[i];
                Vector3D[] arc2 = allPoints[i + 1];

                for (int j = 0; j < arc1.Length - 1; j++)
                {
                    // Points of (i,j) box;
                    Vector3D p1 = arc1[j];
                    Vector3D p2 = arc2[j];
                    Vector3D p3 = arc1[j + 1];
                    Vector3D p4 = arc2[j + 1];

                    Mesh.Triangle tri1 = new Mesh.Triangle(p1, p2, p3);
                    Mesh.Triangle tri2 = new Mesh.Triangle(p2, p4, p3);

                    // We need to thicken after reflecting around, otherwise we can't apply a min thickness.

                    /*Sphere normal = cellSphere;
                     * Mesh.Triangle[] thickened1 = Thicken( tri1, normal );
                     * Mesh.Triangle[] thickened2 = Thicken( tri2, normal );
                     * mesh.Triangles.AddRange( thickened1 );
                     * mesh.Triangles.AddRange( thickened2 );*/

                    mesh.Triangles.Add(tri1);
                    mesh.Triangles.Add(tri2);
                }
            }

            // AuxPoints will be used for multiple things.
            // - The first two points are for an an that will fill the gap where there is a missing face.
            // - We'll also store the points for the 4 edges of our fundamental triangle.
            List <Vector3D> auxPoints = new List <Vector3D>();
            {
                var             edge1 = allPoints.First();
                var             edge2 = allPoints.Last();
                List <Vector3D> edge3 = new List <Vector3D>(), edge4 = new List <Vector3D>();
                for (int i = 0; i < allPoints.Count; i++)
                {
                    edge3.Add(allPoints[i][0]);
                    edge4.Add(allPoints[i][allPoints[i].Length - 1]);
                }
                edge4.Reverse();

                auxPoints.Add(e1.Start);
                auxPoints.Add(e1.End);
                auxPoints.AddRange(edge1.Reverse());
                auxPoints.AddRange(edge2);
                auxPoints.AddRange(edge3);
                auxPoints.AddRange(edge4);
            }

            Vector3D cen = HoneycombPaper.InteriorPointBall;

            /* Reorientation code.  Move this elsewhere.
             *
             * // Face centered orientation.
             * bool faceCentered = false;
             * if( faceCentered )
             *      SimplexCalcs.PrepForFacetCentering( p, q, simplex, ref cen );
             *
             * Mobius mUHS = SimplexCalcs.FCOrientMobius( p, q );
             * Mobius mBall = HoneycombPaper.FCOrientMobius( H3Models.UHSToBall( cellSphere ) );
             *
             * simplex = simplex.Select( s =>
             * {
             *      s = H3Models.UHSToBall( s );
             *      //H3Models.TransformInBall2( s, mBall );
             *      return s;
             * } ).ToArray();
             *
             *
             * {
             *      for( int i = 0; i < mesh.Triangles.Count; i++ )
             *      {
             *              Mesh.Triangle tri = mesh.Triangles[i];
             *
             *              if( faceCentered )
             *              {
             *                      tri.a = mUHS.ApplyToQuaternion( tri.a );
             *                      tri.b = mUHS.ApplyToQuaternion( tri.b );
             *                      tri.c = mUHS.ApplyToQuaternion( tri.c );
             *              }
             *
             *              tri.a = H3Models.UHSToBall( tri.a );
             *              tri.b = H3Models.UHSToBall( tri.b );
             *              tri.c = H3Models.UHSToBall( tri.c );
             *
             *              if( faceCentered )
             *              {
             *                      tri.a = H3Models.TransformHelper( tri.a, mBall );
             *                      tri.b = H3Models.TransformHelper( tri.b, mBall );
             *                      tri.c = H3Models.TransformHelper( tri.c, mBall );
             *              }
             *              mesh.Triangles[i] = tri;
             *      }
             *
             *      if( faceCentered )
             *              cen = H3Models.TransformHelper( cen, mBall );
             * }
             */

            // Now we need to reflect around this fundamental patch.
            H3.Cell[] simplices = GenCell(simplex, mesh, cen, auxPoints.ToArray(), ball);

            // Existing cells take precedence.
            foreach (H3.Cell c in simplices)
            {
                Vector3D t = c.Center;
                H3.Cell  dummy;
                if (!complete.TryGetValue(t, out dummy))
                {
                    complete[t] = c;
                }
            }
        }
示例#14
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;
                }
            }
        }
示例#15
0
        public void Gen(int p, int q, int r)
        {
            Geometry g = Util.GetGeometry(p, q, r);

            if (g != Geometry.Spherical)
            {
                throw new System.Exception("Point group code only for spherical geometry.");
            }

            Simplex simplex = new Simplex();

            simplex.Facets = SimplexCalcs.Mirrors(p, q, r);
            Vector3D cen        = new Vector3D();
            Vector3D faceCenter = SimplexCalcs.FaceCenterSpherical(p, q, r);
            Vector3D edgeMid    = SimplexCalcs.EdgeMidpointSpherical(p, q, r);
            Vector3D vertex     = SimplexCalcs.VertexSpherical(p, q, r);

            List <Vector3D> startingPoles = new List <Vector3D>();

            startingPoles.Add(Sterographic.S3toR3(GreatSphere.FromSphere(simplex.Facets[0]).Pole));
            GreatSphere[] spheres = CalcSpheres(simplex.Facets, startingPoles.ToArray());

            string filename = "point_group.pov";

            using (StreamWriter sw = File.CreateText(filename))
            {
                //foreach( var greatSphere in spheres )
                //sw.WriteLine( PovRay.Sphere( greatSphere.ToSphere() ) );
            }

            /*
             * List<H3.Cell.Edge> startingEdges = new List<H3.Cell.Edge>();
             * startingEdges.Add( new H3.Cell.Edge( cen, faceCenter ) );
             * H3.Cell.Edge[] edges = Recurse.CalcEdges( simplex.Facets, startingEdges.ToArray(), new Recurse.Settings() { G = Geometry.Spherical, Threshold = 0.001 } );
             * //edges = edges.Where( e => !( Infinity.IsInfinite( e.Start ) || Infinity.IsInfinite( e.End ) ) ).ToArray();
             *
             * PovRay.WriteEdges( new PovRay.Parameters() { AngularThickness = 0.01 }, Geometry.Spherical, edges, filename, append: true );
             */

            double minRad = 0;
            double thick  = 0.005;

            System.Func <Vector3D, Sphere> sizeFunc = v =>
            {
                Vector3D c;
                double   rad;
                H3Models.Ball.DupinCyclideSphere(v, thick / 2, g, out c, out rad);
                return(new Sphere()
                {
                    Center = c, Radius = Math.Max(rad, minRad)
                });
            };

            // All geodesics
            List <Circle3D> startingCircles = new List <Circle3D>();

            startingCircles.Add(GeodesicFrom2Points(cen, edgeMid));
            Circle3D[] geodesics = CalcGeodesics(simplex.Facets, startingCircles.ToArray());

            Vector3D color = new Vector3D(0, 0, 1);

            using (StreamWriter sw = File.CreateText(filename))
            {
                Shapeways shapeways = new Shapeways();
                foreach (Circle3D geodesic in geodesics)
                {
                    Vector3D[] points;
                    if (Infinity.IsInfinite(geodesic.Radius))
                    {
                        double  cutoff = 15;
                        Segment seg    = Segment.Line(geodesic.Normal * cutoff, geodesic.Normal * -cutoff);
                        points = seg.Subdivide(42);
                    }
                    else
                    {
                        List <Vector3D> tempPoints = geodesic.Subdivide(150).ToList();
                        tempPoints.Add(tempPoints[0]);
                        tempPoints.Add(tempPoints[1]);
                        points = tempPoints.ToArray();
                    }

                    List <Vector3D> ePoints = new List <Vector3D>();
                    List <double>   eRadii  = new List <double>();
                    foreach (Vector3D pNE in points)
                    {
                        Sphere sphere = sizeFunc(pNE);
                        ePoints.Add(sphere.Center);
                        eRadii.Add(sphere.Radius);
                    }
                    shapeways.AddCurve(ePoints.ToArray(), eRadii.ToArray());

                    sw.WriteLine(PovRay.EdgeSphereSweep(points, sizeFunc, color));
                }

                STL.SaveMeshToSTL(shapeways.Mesh, "533.stl");
            }
        }