public static void OneImage( HoneycombDef imageData, double t = 0.0 ) { //string filename = "batch/" + imageData.FormatFilename(); string filename = imageData.FormatFilename(); //if( File.Exists( filename ) ) // return; int p = imageData.P, q = imageData.Q, r = imageData.R; Geometry gCell = Geometry2D.GetGeometry( p, q ); Geometry gVertex = Geometry2D.GetGeometry( q, r ); //if( !( gCell == Geometry.Hyperbolic || gVertex == Geometry.Hyperbolic ) ) //if( !( gVertex == Geometry.Hyperbolic ) ) // return; Sphere[] mirrors = SimplexCalcs.Mirrors( p, q, r ); //double bounds = gCell == Geometry.Spherical ? 9 : 1.1; double bounds = 1.1; bounds = 1; //bounds = 5; //bounds = 7; //bounds = 4.4; //bounds = 10; CoxeterImages imageCalculator = new CoxeterImages(); int size = 200; CoxeterImages.Settings settings = new CoxeterImages.Settings() { Honeycomb = imageData, Width = size, Height = size, Bounds = bounds, Mirrors = mirrors, FileName = imageData.FormatFilename(), }; imageCalculator.AutoCalcScale( settings ); //settings.ColorScaling = 45.1; // 437 //settings.ColorScaling = 60; // 35.58; // 438, 637 cathedral //settings.ColorScaling = 20; // 373 //settings.ColorScaling = 15; //464 if( settings.ColorScaling < 1 ) settings.ColorScaling = 15; settings.ColorScaling = 39; //size = 4320; size = 2500; //settings.Width = size * 4 / 3; settings.Width = size * 2; settings.Width = size; settings.Height = size; //settings.FileName = imageData.FormatFilename( "jpg" ); settings.FileName = filename; imageCalculator.GenImage( settings, t ); }
public static void DoStuff( string[] args ) { int p, q, r; if( args.Length == 3 ) { p = ReadArg( args[0] ); q = ReadArg( args[1] ); r = ReadArg( args[2] ); } else { p = 3; q = 3; r = 7; } HoneycombDef imageData = new HoneycombDef( p, q, r ); ////////////////////////////////////////////////////////////// Various things we've run over time. //Sandbox.CalcSelfSimilarityScale(); //Sandbox.Check_pq_Distances(); //HyperidealSquares(); //S3.Hypercube(); //R3.Geometry.Euclidean.GenEuclidean(); //HoneycombGen.OneHoneycombOldCode(); //CreateCellPovRay( imageData ); //CreateCellSTL( imageData ); //CreateSimplex( imageData ); //HoneycombGen.OneHoneycombNew( new HoneycombDef() { P = imageData.P, Q = imageData.Q, R = imageData.R } ); //SphericalAnimate( imageData ); Program.OneImage( imageData ); 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(); }
private static Sphere[] SphericalCellFacetMirrors( HoneycombDef imageData ) { int p = imageData.P; int q = imageData.Q; int r = imageData.R; double inRadius = Honeycomb.InRadius( p, q, r ); //inRadius *= 1.4; // Experimenting with {3,3,u} Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig( p, q ); tiling.GenerateInternal( config, imageData.Projection ); Sphere[] mirrors = H3.GenFacetSpheres( tiling, inRadius ) .Select( f => f.Sphere ).ToArray(); return mirrors; }
private static string BaseName( HoneycombDef def ) { return string.Format( "{0}{1}{2}", def.P, def.Q, def.R ); }
public static void ParacompactSet() { List<int[]> toRun = new List<int[]>(); toRun.Add( new int[] { 0, 1 } ); toRun.Add( new int[] { 0, 2 } ); toRun.Add( new int[] { 0, 3 } ); toRun.Add( new int[] { 1, 2 } ); toRun.Add( new int[] { 1, 3 } ); toRun.Add( new int[] { 2, 3 } ); toRun.Add( new int[] { 0, 1, 2 } ); toRun.Add( new int[] { 0, 1, 3 } ); toRun.Add( new int[] { 0, 2, 3 } ); toRun.Add( new int[] { 1, 2, 3 } ); toRun.Add( new int[] { 0, 1, 2, 3 } ); //toRun.Clear(); //toRun.Add( new int[] { 0, 1, 3 } ); int baseHue = 0; HoneycombDef def; baseHue = 135; def = new HoneycombDef( 6, 3, 3 ); foreach( int[] active in toRun ) Paracompact( def, active, baseHue ); baseHue = 220; def = new HoneycombDef( 6, 3, 4 ); foreach( int[] active in toRun ) Paracompact( def, active, baseHue ); baseHue = 180; def = new HoneycombDef( 6, 3, 5 ); foreach( int[] active in toRun ) Paracompact( def, active, baseHue ); baseHue = 255; def = new HoneycombDef( 6, 3, 6 ); foreach( int[] active in toRun ) Paracompact( def, active, baseHue ); baseHue = 105; def = new HoneycombDef( 3, 6, 3 ); foreach( int[] active in toRun ) Paracompact( def, active, baseHue ); baseHue = 300; def = new HoneycombDef( 4, 4, 3 ); foreach( int[] active in toRun ) Paracompact( def, active, baseHue ); baseHue = 0; def = new HoneycombDef( 4, 4, 4 ); foreach( int[] active in toRun ) Paracompact( def, active, baseHue ); }
public static void Paracompact( HoneycombDef def, int[] active, int baseHue ) { string baseName = BaseName( def ); string mirrorsString = ActiveMirrorsString( active ); string suffix = "-" + mirrorsString; string fileName = baseName + suffix; if( File.Exists( fileName + ".pov" ) ) { Console.WriteLine( string.Format( "Skipping {0}", fileName ) ); return; } Console.WriteLine( string.Format( "Building {0}", fileName ) ); CalcThickness( active ); // 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( active, simplex ); if( startingPoint.DNE ) return; 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 ) ); } SetupBaseHue( fileName, mirrorsString, baseHue ); Recurse.m_background = new Vector3D( baseHue, 1, .1 ); H3.Cell.Edge[] edges = Recurse.CalcEdgesSmart2( simplex.Facets, startingEdges.ToArray() ); H3.SaveToFile( fileName, edges, finite: true, append: true ); }
/// <summary> /// This generates a honeycomb by reflecting in 4 mirrors of the fundamental simplex. /// </summary> public static void OneHoneycombNew( HoneycombDef imageData ) { int p = imageData.P; int q = imageData.Q; int r = imageData.R; double thickness = 0.1; 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 = 5/*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 ) }; edges = Recurse.CalcEdges( simplex, startingEdges, new Recurse.Settings() { G = g, Threshold = threshold } ); //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 = 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 = 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(); } } // Write the file bool pov = false; 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(); } }
private static double AnimColorScaling( HoneycombDef imageData ) { return 10; int p = imageData.P, q = imageData.Q, r = imageData.R; Sphere[] mirrors = SimplexCalcs.Mirrors( p, q, r ); int size = 200; CoxeterImages.Settings settings = new CoxeterImages.Settings() { Honeycomb = imageData, Width = size*2, Height = size, Bounds = 1.0, Mirrors = mirrors, FileName = string.Empty, }; CoxeterImages imageCalculator = new CoxeterImages(); imageCalculator.AutoCalcScale( settings ); return settings.ColorScaling; }
private static void SphericalAnimate( HoneycombDef imageData ) { double colorScaling = AnimColorScaling( imageData ); int fps = 30; //int frames = 60 * fps; int frames = 5; for( int i = 0; i < frames; i++ ) { string num = i.ToString(); num = num.PadLeft( 3, '0' ); double t = (double)i/frames; string filename = "batch/" + imageData.FormatFilename( string.Empty ) + "_" + num + ".png"; OneAnimationFrame( imageData, filename, colorScaling, t ); } }
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 ); }
private static double GetScalingOld( HoneycombDef imageData ) { // pqi, pir (3qr, p3r, pq3) // Q = 3 = 50, Q = 7 = 130 double scaling = 50 + (imageData.Q - 3) * 20; if( /*imageData.P == -1 ||*/ imageData.Q == -1 ) scaling = 130; // iqr //scaling = 100; (blue) // scaling = 50; (when purple, did constant 50) // Reverse: What did I use this for? /*scaling = 130 - ( imageData.Q - 3 ) * 20; if( imageData.Q == -1 ) scaling = 50;*/ // Euclidean cells/vertex figures. scaling = 75; // Gray scale //scaling = 35; return scaling; }
private static void CreateSimplex( HoneycombDef imageData ) { int p = imageData.P; int q = imageData.Q; int r = imageData.R; Vector3D cen = CellCenBall; 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" ); if( false ) { 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 ); } }
/// <summary> /// Create an STL file for a cell. /// This will be a 2D surface of triangles, which will need to be thickened using an external program. /// Currently only works for cells with both hyperideal vertices and cells. /// </summary> private static void CreateCellSTL( HoneycombDef imageData ) { int p = imageData.P; int q = imageData.Q; int r = imageData.R; 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. int div = 5; 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 * div ); points2 = H3Models.Ball.GeodesicPoints( e2.Start, e2.End, 2 * div ); } else { points1 = H3Models.UHS.GeodesicPoints( e1.Start, e1.End, 2 * div ); points2 = H3Models.UHS.GeodesicPoints( e2.Start, e2.End, 2 * div ); } Sphere cellSphere = simplex[0]; // 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]; // NOTE: This arc is not generally geodesic! Vector3D[] arcPoints; if( i == points1.Length - 1 ) { arcPoints = ball ? H3Models.Ball.GeodesicPoints( p1, p2, div ) : H3Models.UHS.GeodesicPoints( p1, p2, 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, 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.Triangles.Add( new Mesh.Triangle( p1, p2, p3 ) ); mesh.Triangles.Add( new Mesh.Triangle( p2, p4, p3 ) ); } } // Face centered orientation. // XXX - We need to do this prior to mesh generation, so the mesh isn't stretched out by these transformations. bool faceCentered = true; Vector3D cen = CellCenBall; if( faceCentered ) SimplexCalcs.PrepForFacetCentering( p, q, simplex, ref cen ); Mobius mUHS = SimplexCalcs.FCOrientMobius( p, q ); Mobius mBall = 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. bool dual = false; H3.Cell[] simplicesFinal = GenCell( simplex, mesh, cen, ball, dual ); System.IO.File.Delete( "cell.stl" ); foreach( H3.Cell cell in simplicesFinal ) STL.AppendMeshToSTL( cell.Mesh, "cell.stl" ); //STL.AppendMeshToSTL( simplicesFinal[0].Mesh, "cell.stl" ); }
private static void CreateCellPovRay( HoneycombDef imageData ) { int p = imageData.P; int q = imageData.Q; int r = imageData.R; // Calculate scale to make vertex centered. //Vector3D v = SimplexCalcs.VertexPointBall( p, q, r ); //v = H3Models.BallToUHS( v ); /*double t = Math.Sqrt( 1 - Math.Pow( v.Abs(), 2 ) ); v = new Vector3D( t, 0, v.Z ); v = H3Models.BallToUHS( v ); Vector3D v2 = H3Models.BallToUHS( new Vector3D( 1, 0, 0 ) ); t = v.Abs() / v2.Abs(); v = H3Models.UHSToBall( new Vector3D( t, 0, 0 ) );*/ double scale = Geometry2D.GetNormalizedCircumRadius( p, q ); Vector3D cen = CellCenBall; cen = H3Models.BallToUHS( cen ); bool ball = true; bool dual = false; Sphere[] simplex = SimplexCalcs.Mirrors( p, q, r, ref cen, moveToBall: ball/*, scaling: 1.0/v.Abs()*/ ); //Sphere[] simplex = SimplexCalcs.Mirrors( p, q, r, moveToBall: ball/*, scaling: 1.0/v.Abs()*/ ); //Sphere[] simplex = SimplexCalcs.Mirrors( p, q, r, moveToBall: ball, scaling: 1.0 / scale ); H3.Cell[] simplicesFinal = GenCell( simplex, null, cen, ball, dual ); System.IO.File.Delete( "cell.pov" ); foreach( H3.Cell cell in simplicesFinal ) { //int[] include = new int[] { 0, 1, 2, 3 }; int[] include = new int[] { 0 }; if( dual ) include = new int[] { 3 }; Sphere[] facets = cell.Facets.Select( f => f.Sphere ).ToArray(); if( m_toKlein ) facets = facets.Select( s => H3Models.BallToKlein( s ) ).ToArray(); PovRay.AppendSimplex( facets, cell.Center, include, "cell.pov" ); } }