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); }
public static void OneHoneycombGoursat(int[] active, string baseName, int baseHue, Settings settings = null) { // Setup parameters. int numEdges = 250000; if (settings != null) { active = settings.PovRay.Active; numEdges = settings.PovRay.NumEdges; baseName = string.Join("-", settings.Angles); } CalcThickness(active); if (settings != null) { H3.m_settings.AngularThickness = settings.PovRay.EdgeWidth; // ZZZ - should really stop using that settings class. } // Create the simplex. Simplex simplex = new Simplex(); if (settings != null) { simplex.InitializeGoursat(settings.Angles); } else { simplex.InitializeGoursat(); } // Map of labels for mirrors consistent with input scheme to Goursat function. // Map is from wikipedia labeling scheme to the indices our function generates. // // wiki == our index // 0100 == 0 // 0001 == 1 // 1000 == 2 // 0010 == 3 Func <int, int> mapMirror = i => { switch (i) { case 0: return(2); case 1: return(0); case 2: return(3); case 3: return(1); } throw new System.ArgumentException(); }; // We need to set this up before converting the mirrors. string mirrorsString = ActiveMirrorsString(active); string suffix = "_" + mirrorsString; // Convert our active mirrors into the Goursat tet indices. int[] polyMirrors = new int[] { 1, 2, 3 }; active = active.Select(i => mapMirror(i)).OrderBy(i => i).ToArray(); polyMirrors = polyMirrors.Select(i => mapMirror(i)).OrderBy(i => i).ToArray(); Vector3D startingPoint = IterateToStartingPoint(null, active, simplex); 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)); } bool doEdges = true; bool doCells = false; // Generate the honeycomb. H3.Cell.Edge[] edges = null; if (doEdges) { edges = Recurse.CalcEdgesSmart(simplex.Facets, startingEdges.ToArray(), numEdges); } // Highlighted cells. H3.Cell[] cellsToHighlight = null; if (doCells) { H3.Cell startingCell = PolyhedronToHighlight(Geometry.Hyperbolic, polyMirrors, simplex, startingPoint); cellsToHighlight = Recurse.CalcCells(simplex.Facets, new H3.Cell[] { startingCell }); //cellsToHighlight = new H3.Cell[] { startingCell }; } // plugin Wendy's nonuniform calcs here... //Nonuniform.Wendy( simplex, edges ); // Trim out half the edges (the ones we won't see in our Pov-Ray view). /*Vector3D lookFrom = new Vector3D( 1, 1, 1 ) * 0.7; * Vector3D lookAt = new Vector3D(); // pov-ray lookat * double thresh = -.01; * if( doEdges ) * edges = edges.Where( e => e.Start.Dot( lookAt ) > thresh || e.End.Dot( lookAt ) > thresh ).ToArray(); * //if( doCells ) * // cellsToHighlight = cellsToHighlight.Where( c => c.Center.Dot( lookAt ) > thresh ).ToArray(); // I don't think this works right */ string fileName = baseName + suffix; if (File.Exists(fileName + ".pov")) { File.Delete(fileName + ".pov"); //Console.WriteLine( string.Format( "Skipping {0}", fileName ) ); //return; } SetupBaseHueGoursat(fileName, mirrorsString, baseHue); if (doEdges) { H3.SaveToFile(fileName, edges, finite: true, append: true); } if (doCells) { HashSet <H3.Cell.Edge> cellEdges = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer()); foreach (H3.Cell cell in cellsToHighlight) { cell.AppendAllEdges(cellEdges); } edges = cellEdges.ToArray(); H3.SaveToFile(fileName, edges, finite: true, append: true); H3.AppendFacets(fileName, cellsToHighlight); } }