/// <summary> /// Make an edge mesh of a regular tiling. /// </summary> public static Mesh MakeEdgeMesh( int p, int q ) { Mesh mesh = new Mesh(); int maxTiles = 400; Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig( p, q, maxTiles: maxTiles ); config.Shrink = 0.6; tiling.GenerateInternal( config ); TilingConfig boundaryConfig = new TilingConfig( 14, 7, maxTiles: 1 ); boundaryConfig.Shrink = 1.01; Tile boundary = Tiling.CreateBaseTile( boundaryConfig ); AddSymmetryTriangles( mesh, tiling, boundary.Drawn ); //AddSymmetryTriangles( mesh, tiling, null ); return mesh; HashSet<Vector3D> completed = new HashSet<Vector3D>(); int count = 0; foreach( Tile tile in tiling.Tiles ) { MeshEdges( mesh, tile, completed, null ); count++; if( count >= maxTiles ) break; } return mesh; }
private static void HopfFibration(Tiling tiling) { int segDivisions = 10; Shapeways mesh = new Shapeways(); HashSet <Vector3D> done = new HashSet <Vector3D>(); foreach (Tile tile in tiling.Tiles) { foreach (Segment seg in tile.Boundary.Segments) { if (done.Contains(seg.Midpoint)) { continue; } // Subdivide the segment, and project points to S2. Vector3D[] points = seg.Subdivide(segDivisions).Select(v => Spherical2D.PlaneToSphere(v)).ToArray(); foreach (Vector3D point in points) { Vector3D[] circlePoints = OneHopfCircle(point); ProjectAndAddS3Points(mesh, circlePoints, shrink: false); } done.Add(seg.Midpoint); } } STL.SaveMeshToSTL(mesh.Mesh, @"D:\p4\R3\sample\out1.stl"); }
public Tile[] FundamentalCell() { Tile template = TemplateTile(); Tile.ShrinkTile(ref template, 0.9); // Generate a cell tiling. TilingConfig tilingConfig = new TilingConfig(Q, P); Tiling poly = new Tiling(); poly.Generate(tilingConfig); m_tiles = poly.Tiles.ToList(); //SetupTransformCircle( tile ); // Call this before transforming. //SetupNeighborCircle( tile ); // Generate our cell. List <Tile> cellTiles = new List <Tile>(); foreach (Tile t in poly.Tiles) { Tile temp = template.Clone(); temp.Transform(t.Isometry.Inverse()); cellTiles.Add(temp); } return(cellTiles.ToArray()); }
private static void GetAssociatedTiling(int p, int q, int maxTiles, out Tiling tiling) { TilingConfig tilingConfig = new TilingConfig(p, q, maxTiles: maxTiles); tiling = new Tiling(); tiling.GenerateInternal(tilingConfig, p == 6 ? Polytope.Projection.VertexCentered : Polytope.Projection.FaceCentered); }
private static void HopfFibration(Tiling tiling) { int segDivisions = 10; int circleDivisions = 125; Shapeways mesh = new Shapeways(); HashSet <Vector3D> done = new HashSet <Vector3D>(); foreach (Tile tile in tiling.Tiles) { foreach (Segment seg in tile.Boundary.Segments) { if (done.Contains(seg.Midpoint)) { continue; } // Subdivide the segment, and project points to S2. Vector3D[] points = seg.Subdivide(segDivisions).Select(v => Spherical2D.PlaneToSphere(v)).ToArray(); foreach (Vector3D point in points) { // Get the hopf circle and add to mesh. // http://en.wikipedia.org/wiki/Hopf_fibration#Explicit_formulae double a = point.X; double b = point.Y; double c = point.Z; double factor = 1 / (Math.Sqrt(1 + c)); if (Tolerance.Equal(c, -1)) { continue; } List <Vector3D> circlePoints = new List <Vector3D>(); double angleInc = 2 * Math.PI / circleDivisions; double angle = 0; for (int i = 0; i <= circleDivisions; i++) { double sinTheta = Math.Sin(angle); double cosTheta = Math.Cos(angle); circlePoints.Add(new Vector3D( (1 + c) * cosTheta, a * sinTheta - b * cosTheta, a * cosTheta + b * sinTheta, (1 + c) * sinTheta)); angle += angleInc; } bool shrink = false; ProjectAndAddS3Points(mesh, circlePoints.ToArray(), shrink); } done.Add(seg.Midpoint); } } STL.SaveMeshToSTL(mesh.Mesh, @"D:\p4\R3\sample\out1.stl"); }
private static Segment[] BaseTileSegments(int p, int q) { Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig(p, q, 1); Tile baseTile = Tiling.CreateBaseTile(config); //baseTile.Transform( Mobius.Scale( 2 ) ); // Only works in Euclidean case return(baseTile.Boundary.Segments.ToArray()); }
private static void GetAssociatedTiling(EHoneycomb honeycomb, out Tiling tiling, out Tile baseTile) { int p, q; GetPQ(honeycomb, out p, out q); TilingConfig tilingConfig = new TilingConfig(p, q, maxTiles: m_params.MaxTiles); tiling = new Tiling(); tiling.Generate(tilingConfig); baseTile = Tiling.CreateBaseTile(tilingConfig); }
public static void Cell633() { TilingConfig config = new TilingConfig( 6, 3, maxTiles: 20000 ); Tiling tiling = new Tiling(); tiling.GenerateInternal( config, Polytope.Projection.VertexCentered ); double edgeLength = Honeycomb.EdgeLength( 6, 3, 3 ); double z = 0.25; double offset = H3Models.UHS.ToEHorizontal( edgeLength, z ); double scale = offset / tiling.Tiles.First().Boundary.Segments.First().Length; foreach( Tile tile in tiling.Tiles ) tile.Transform( Mobius.Scale( scale ) ); Vector3D dummy; double radius; H3Models.UHS.Geodesic( new Vector3D( 0, 0, z ), new Vector3D( scale, 0, z ), out dummy, out radius ); Vector3D midradius = H3Models.UHSToBall( new Vector3D( 0, 0, radius ) ); double temp = midradius.Z; double temp2 = ( 1 - temp ) / 2; double temp3 = temp + temp2; double temp4 = temp3; Vector3D circumradius = H3Models.UHSToBall( new Vector3D( 0, 0, z ) ); temp = circumradius.Z; temp2 = ( 1 - temp ) / 2; temp3 = temp + temp2; temp4 = temp3; // Checking /* Vector3D test = new Vector3D( offset, 0, z ); test = H3Models.UHSToBall( test ); double edgeLength2 = DonHatch.e2hNorm( test.Abs() ); edgeLength2 += 0; */ HashSet<H3.Cell.Edge> edges = new HashSet<H3.Cell.Edge>(); foreach( Tile tile in tiling.Tiles ) foreach( Segment seg in tile.Boundary.Segments ) { H3.Cell.Edge edge = new H3.Cell.Edge( H3Models.UHSToBall( seg.P1 + new Vector3D( 0, 0, z ) ), H3Models.UHSToBall( seg.P2 + new Vector3D( 0, 0, z ) ) ); edges.Add( edge ); } PovRay.WriteH3Edges( new PovRay.Parameters(), edges.ToArray(), "edges.pov" ); }
/// <summary> /// A static helper to generate two dual tilings. /// </summary> /// <remarks>{p,q} will have a vertex at the center.</remarks> /// <remarks>{q,p} will have its center at the center.</remarks> public static void MakeDualTilings(out Tiling tiling1, out Tiling tiling2, int p, int q) { tiling1 = new Tiling(); tiling2 = new Tiling(); int maxTiles = 2000; TilingConfig config1 = new TilingConfig(p, q, maxTiles); TilingConfig config2 = new TilingConfig(q, p, maxTiles); tiling1.GenerateInternal(config1, Polytope.Projection.FaceCentered); tiling2.GenerateInternal(config2, Polytope.Projection.VertexCentered); /* * Circle c = new Circle(); * c.Radius = .9; * tiling1.Clip( c ); * tiling2.Clip( c ); */ }
/// <summary> /// Make an edge mesh of a regular tiling. /// </summary> public static Mesh MakeEdgeMesh(int p, int q) { Mesh mesh = new Mesh(); int maxTiles = 400; Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig(p, q, maxTiles: maxTiles); config.Shrink = 0.6; tiling.GenerateInternal(config); TilingConfig boundaryConfig = new TilingConfig(14, 7, maxTiles: 1); boundaryConfig.Shrink = 1.01; Tile boundary = Tiling.CreateBaseTile(boundaryConfig); AddSymmetryTriangles(mesh, tiling, boundary.Drawn); //AddSymmetryTriangles( mesh, tiling, null ); return(mesh); }
/// <summary> /// Make an edge mesh of a regular tiling. /// </summary> public static Mesh MakeEdgeMesh(int p, int q) { Mesh mesh = new Mesh(); int maxTiles = 400; Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig(p, q, maxTiles: maxTiles); config.Shrink = 0.6; tiling.GenerateInternal(config); TilingConfig boundaryConfig = new TilingConfig(14, 7, maxTiles: 1); boundaryConfig.Shrink = 1.01; Tile boundary = Tiling.CreateBaseTile(boundaryConfig); AddSymmetryTriangles(mesh, tiling, boundary.Drawn); //AddSymmetryTriangles( mesh, tiling, null ); return(mesh); HashSet <Vector3D> completed = new HashSet <Vector3D>(); int count = 0; foreach (Tile tile in tiling.Tiles) { MeshEdges(mesh, tile, completed, null); count++; if (count >= maxTiles) { break; } } return(mesh); }
public static void Polarity() { TilingConfig config = new TilingConfig( 3, 7, 50 ); Tiling tiling = new Tiling(); tiling.GenerateInternal( config ); List<Vector3D> points = new List<Vector3D>(); List<H3.Cell.Edge> edges = new List<H3.Cell.Edge>(); foreach( Polygon p in tiling.Tiles.Select( t => t.Boundary ) ) foreach( Segment s in p.Segments ) foreach( Vector3D v in s.Subdivide( 25 ) ) { Vector3D klein = HyperbolicModels.PoincareToKlein( v ); H3.Cell.Edge e = Dual( klein ); points.Add( klein ); edges.Add( e ); } using( StreamWriter sw = File.CreateText( "polarity.pov" ) ) { double rad = 0.01; foreach( Vector3D vert in points ) sw.WriteLine( PovRay.Sphere( new Sphere() { Center = vert, Radius = rad } ) ); foreach( H3.Cell.Edge edge in edges ) sw.WriteLine( PovRay.Cylinder( edge.Start, edge.End, rad/2 ) ); } }
private static List<H3.Cell.Edge> CopyAndProject( List<H3.Cell.Edge> regionEdges, Tiling tiling, double scale, Vector3D offset ) { HashSet<H3.Cell.Edge> newEdges = new HashSet<H3.Cell.Edge>( new H3.Cell.EdgeEqualityComparer() ); //foreach( Tile tile in tiling.Tiles ) // Needed for doing full ball (rather than just half of it) Tile tile = tiling.Tiles.First(); { foreach( H3.Cell.Edge edge in regionEdges ) { // Translation // The isometry is necessary for the 363, but seems to mess up 636 Vector3D start = tile.Isometry.Apply( edge.Start ) + offset; Vector3D end = tile.Isometry.Apply( edge.End ) + offset; //Vector3D start = edge.Start + tile.Center + offset; //Vector3D end = edge.End + tile.Center + offset; // Scaling start *= scale; end *= scale; // Projections start = H3Models.UHSToBall( start ); end = H3Models.UHSToBall( end ); H3.Cell.Edge transformed = new H3.Cell.Edge( start, end ); if( EdgeOkBall( transformed ) ) newEdges.Add( transformed ); } } return newEdges.ToList(); }
private static Segment[] BaseTileSegments( int p, int q ) { Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig( p, q, 1 ); Tile baseTile = Tiling.CreateBaseTile( config ); //baseTile.Transform( Mobius.Scale( 2 ) ); // Only works in Euclidean case return baseTile.Boundary.Segments.ToArray(); }
private static void GetAssociatedTiling( EHoneycomb honeycomb, out Tiling tiling, out Tile baseTile ) { int p, q; GetPQ( honeycomb, out p, out q ); TilingConfig tilingConfig = new TilingConfig( p, q, maxTiles: m_params.MaxTiles ); tiling = new Tiling(); tiling.Generate( tilingConfig ); baseTile = Tiling.CreateBaseTile( tilingConfig ); }
/// <summary> /// Helper to do one step of reflections. /// Returns a new list of region edges. /// </summary> private static List<H3.Cell.Edge> DoOneStep( List<H3.Cell.Edge> regionEdges, Tiling tiling, Circle region ) { HashSet<H3.Cell.Edge> newEdges = new HashSet<H3.Cell.Edge>( new H3.Cell.EdgeEqualityComparer() ); foreach( Tile tile in tiling.Tiles ) { foreach( H3.Cell.Edge edge in regionEdges ) { H3.Cell.Edge toAdd = null; if( !Tolerance.Zero( tile.Center.Abs() ) ) { // Translate // The isometry is necessary for the 363, but seems to mess up 636 Vector3D start = tile.Isometry.Apply( edge.Start ); Vector3D end = tile.Isometry.Apply( edge.End ); //Vector3D start = edge.Start + tile.Center; //Vector3D end = edge.End + tile.Center; // Reflect start = region.ReflectPoint( start ); end = region.ReflectPoint( end ); toAdd = new H3.Cell.Edge( start, end ); } else toAdd = edge; if( EdgeOkUHS( toAdd, region ) ) newEdges.Add( toAdd ); } } return newEdges.ToList(); }
private static void AddSymmetryTriangles(Mesh mesh, Tiling tiling, Polygon boundary) { // Assume template centered at the origin. Polygon template = tiling.Tiles.First().Boundary; List <Triangle> templateTris = new List <Triangle>(); foreach (Segment seg in template.Segments) { int num = 1 + (int)(seg.Length * m_divisions); Vector3D a = new Vector3D(); Vector3D b = seg.P1; Vector3D c = seg.Midpoint; Vector3D centroid = (a + b + c) / 3; Polygon poly = new Polygon(); Segment segA = Segment.Line(new Vector3D(), seg.P1); Segment segB = seg.Clone(); segB.P2 = seg.Midpoint; Segment segC = Segment.Line(seg.Midpoint, new Vector3D()); poly.Segments.Add(segA); poly.Segments.Add(segB); poly.Segments.Add(segC); Vector3D[] coords = TextureHelper.TextureCoords(poly, Geometry.Hyperbolic); int[] elements = TextureHelper.TextureElements(3, LOD: 3); for (int i = 0; i < elements.Length / 3; i++) { int idx1 = i * 3; int idx2 = i * 3 + 1; int idx3 = i * 3 + 2; Vector3D v1 = coords[elements[idx1]]; Vector3D v2 = coords[elements[idx2]]; Vector3D v3 = coords[elements[idx3]]; templateTris.Add(new Triangle(v1, v2, v3)); } /* * * // Need to shrink a little, so we won't * // get intersections among neighboring faces. * a = Shrink( a, centroid ); * b = Shrink( b, centroid ); * c = Shrink( c, centroid ); * * Vector3D[] list = seg.Subdivide( num * 2 ); * list[0] = b; * list[list.Length / 2] = c; * for( int i = 0; i < list.Length / 2; i++ ) * templateTris.Add( new Triangle( centroid, list[i], list[i + 1] ) ); * * for( int i = num - 1; i >= 0; i-- ) * templateTris.Add( new Triangle( centroid, a + (c - a) * (i + 1) / num, a + (c - a) * i / num ) ); * * for( int i = 0; i < num; i++ ) * templateTris.Add( new Triangle( centroid, a + (b - a) * i / num, a + (b - a) * (i + 1) / num ) ); */ } foreach (Tile tile in tiling.Tiles) { Vector3D a = tile.Boundary.Segments[0].P1; Vector3D b = tile.Boundary.Segments[1].P1; Vector3D c = tile.Boundary.Segments[2].P1; Mobius m = new Mobius(); if (tile.Isometry.Reflected) { m.MapPoints(template.Segments[0].P1, template.Segments[1].P1, template.Segments[2].P1, c, b, a); } else { m.MapPoints(template.Segments[0].P1, template.Segments[1].P1, template.Segments[2].P1, a, b, c); } foreach (Triangle tri in templateTris) { Triangle transformed = new Triangle( m.Apply(tri.a), m.Apply(tri.b), m.Apply(tri.c)); CheckAndAdd(mesh, transformed, boundary); } } }
/// <summary> /// A static helper to generate two dual tilings. /// </summary> /// <remarks>{p,q} will have a vertex at the center.</remarks> /// <remarks>{q,p} will have its center at the center.</remarks> public static void MakeDualTilings( out Tiling tiling1, out Tiling tiling2, int p, int q ) { tiling1 = new Tiling(); tiling2 = new Tiling(); int maxTiles = 2000; TilingConfig config1 = new TilingConfig( p, q, maxTiles ); TilingConfig config2 = new TilingConfig( q, p, maxTiles ); tiling1.GenerateInternal( config1, Polytope.Projection.FaceCentered ); tiling2.GenerateInternal( config2, Polytope.Projection.VertexCentered ); /* Circle c = new Circle(); c.Radius = .9; tiling1.Clip( c ); tiling2.Clip( c ); */ }
private static void AddSymmetryTriangles( Mesh mesh, Tiling tiling, Polygon boundary ) { // Assume template centered at the origin. Polygon template = tiling.Tiles.First().Boundary; List<Triangle> templateTris = new List<Triangle>(); foreach( Segment seg in template.Segments ) { int num = 1 + (int)(seg.Length * m_divisions); Vector3D a = new Vector3D(); Vector3D b = seg.P1; Vector3D c = seg.Midpoint; Vector3D centroid = ( a + b + c ) / 3; Polygon poly = new Polygon(); Segment segA = Segment.Line( new Vector3D(), seg.P1 ); Segment segB = seg.Clone(); segB.P2 = seg.Midpoint; Segment segC = Segment.Line( seg.Midpoint, new Vector3D() ); poly.Segments.Add( segA ); poly.Segments.Add( segB ); poly.Segments.Add( segC ); Vector3D[] coords = TextureHelper.TextureCoords( poly, Geometry.Hyperbolic ); int[] elements = TextureHelper.TextureElements( 3, LOD: 3 ); for( int i = 0; i < elements.Length / 3; i++ ) { int idx1 = i * 3; int idx2 = i * 3 + 1; int idx3 = i * 3 + 2; Vector3D v1 = coords[elements[idx1]]; Vector3D v2 = coords[elements[idx2]]; Vector3D v3 = coords[elements[idx3]]; templateTris.Add( new Triangle( v1, v2, v3 ) ); } /* // Need to shrink a little, so we won't // get intersections among neighboring faces. a = Shrink( a, centroid ); b = Shrink( b, centroid ); c = Shrink( c, centroid ); Vector3D[] list = seg.Subdivide( num * 2 ); list[0] = b; list[list.Length / 2] = c; for( int i = 0; i < list.Length / 2; i++ ) templateTris.Add( new Triangle( centroid, list[i], list[i + 1] ) ); for( int i = num - 1; i >= 0; i-- ) templateTris.Add( new Triangle( centroid, a + (c - a) * (i + 1) / num, a + (c - a) * i / num ) ); for( int i = 0; i < num; i++ ) templateTris.Add( new Triangle( centroid, a + (b - a) * i / num, a + (b - a) * (i + 1) / num ) ); */ } foreach( Tile tile in tiling.Tiles ) { Vector3D a = tile.Boundary.Segments[0].P1; Vector3D b = tile.Boundary.Segments[1].P1; Vector3D c = tile.Boundary.Segments[2].P1; Mobius m = new Mobius(); if( tile.Isometry.Reflected ) m.MapPoints( template.Segments[0].P1, template.Segments[1].P1, template.Segments[2].P1, c, b, a ); else m.MapPoints( template.Segments[0].P1, template.Segments[1].P1, template.Segments[2].P1, a, b, c ); foreach( Triangle tri in templateTris ) { Triangle transformed = new Triangle( m.Apply( tri.a ), m.Apply( tri.b ), m.Apply( tri.c ) ); CheckAndAdd( mesh, transformed, boundary ); } } }
/// <summary> /// Helper to do one step of reflections. /// Returns a new list of region edges. /// </summary> private static List <H3.Cell.Edge> DoOneStep(List <H3.Cell.Edge> regionEdges, Tiling tiling, Circle region) { HashSet <H3.Cell.Edge> newEdges = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer()); foreach (Tile tile in tiling.Tiles) { foreach (H3.Cell.Edge edge in regionEdges) { H3.Cell.Edge toAdd = null; if (!Tolerance.Zero(tile.Center.Abs())) { // Translate // The isometry is necessary for the 363, but seems to mess up 636 Vector3D start = tile.Isometry.Apply(edge.Start); Vector3D end = tile.Isometry.Apply(edge.End); //Vector3D start = edge.Start + tile.Center; //Vector3D end = edge.End + tile.Center; // Reflect start = region.ReflectPoint(start); end = region.ReflectPoint(end); toAdd = new H3.Cell.Edge(start, end); } else { toAdd = edge; } if (EdgeOkUHS(toAdd, region)) { newEdges.Add(toAdd); } } } return(newEdges.ToList()); }
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 List <H3.Cell.Edge> CopyAndProject(List <H3.Cell.Edge> regionEdges, Tiling tiling, double scale, Vector3D offset) { HashSet <H3.Cell.Edge> newEdges = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer()); //foreach( Tile tile in tiling.Tiles ) // Needed for doing full ball (rather than just half of it) Tile tile = tiling.Tiles.First(); { foreach (H3.Cell.Edge edge in regionEdges) { // Translation // The isometry is necessary for the 363, but seems to mess up 636 Vector3D start = tile.Isometry.Apply(edge.Start) + offset; Vector3D end = tile.Isometry.Apply(edge.End) + offset; //Vector3D start = edge.Start + tile.Center + offset; //Vector3D end = edge.End + tile.Center + offset; // Scaling start *= scale; end *= scale; // Projections start = H3Models.UHSToBall(start); end = H3Models.UHSToBall(end); H3.Cell.Edge transformed = new H3.Cell.Edge(start, end); if (EdgeOkBall(transformed)) { newEdges.Add(transformed); } } } return(newEdges.ToList()); }
public static void Generate(EHoneycomb honeycomb, H3.Settings settings) { // XXX - Block the same as in H3. Share code better. H3.Cell template = null; { int p, q, r; Honeycomb.PQR(honeycomb, out p, out q, out r); // Get data we need to generate the honeycomb. Polytope.Projection projection = Polytope.Projection.FaceCentered; double phi, chi, psi; H3.HoneycombData(honeycomb, out phi, out chi, out psi); H3.SetupCentering(honeycomb, settings, phi, chi, psi, ref projection); Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig(p, q); tiling.GenerateInternal(config, projection); H3.Cell first = new H3.Cell(p, H3.GenFacets(tiling)); first.ToSphere(); // Work in ball model. first.ScaleToCircumSphere(1.0); first.ApplyMobius(settings.Mobius); template = first; } // Center Vector3D center = template.Center; // Face H3.Cell.Facet facet = template.Facets[0]; Sphere s = H3Models.Ball.OrthogonalSphereInterior(facet.Verts[0], facet.Verts[1], facet.Verts[2]); Vector3D face = s.Center; face.Normalize(); face *= DistOriginToOrthogonalSphere(s.Radius); // Edge Circle3D c; H3Models.Ball.OrthogonalCircleInterior(facet.Verts[0], facet.Verts[1], out c); Vector3D edge = c.Center; edge.Normalize(); edge *= DistOriginToOrthogonalSphere(c.Radius); // Vertex Vector3D vertex = facet.Verts[0]; Tet fundamental = new Tet(center, face, edge, vertex); // Recurse. int level = 1; Dictionary <Tet, int> completedTets = new Dictionary <Tet, int>(new TetEqualityComparer()); completedTets.Add(fundamental, level); List <Tet> tets = new List <Tet>(); tets.Add(fundamental); ReflectRecursive(level, tets, completedTets, settings); Shapeways mesh = new Shapeways(); foreach (KeyValuePair <Tet, int> kvp in completedTets) { if (Utils.Odd(kvp.Value)) { continue; } Tet tet = kvp.Key; // XXX - really want sphere surfaces here. mesh.Mesh.Triangles.Add(new Mesh.Triangle(tet.Verts[0], tet.Verts[1], tet.Verts[2])); mesh.Mesh.Triangles.Add(new Mesh.Triangle(tet.Verts[0], tet.Verts[3], tet.Verts[1])); mesh.Mesh.Triangles.Add(new Mesh.Triangle(tet.Verts[0], tet.Verts[2], tet.Verts[3])); mesh.Mesh.Triangles.Add(new Mesh.Triangle(tet.Verts[1], tet.Verts[3], tet.Verts[2])); } mesh.Mesh.Scale(settings.Scale); STL.SaveMeshToSTL(mesh.Mesh, H3.m_baseDir + "fundamental" + ".stl"); }
private static void HopfFibration( Tiling tiling ) { int segDivisions = 10; Shapeways mesh = new Shapeways(); HashSet<Vector3D> done = new HashSet<Vector3D>(); foreach( Tile tile in tiling.Tiles ) foreach( Segment seg in tile.Boundary.Segments ) { if( done.Contains( seg.Midpoint ) ) continue; // Subdivide the segment, and project points to S2. Vector3D[] points = seg.Subdivide( segDivisions ).Select( v => Spherical2D.PlaneToSphere( v ) ).ToArray(); foreach( Vector3D point in points ) { Vector3D[] circlePoints = OneHopfCircle( point ); ProjectAndAddS3Points( mesh, circlePoints, shrink: false ); } done.Add( seg.Midpoint ); } STL.SaveMeshToSTL( mesh.Mesh, @"D:\p4\R3\sample\out1.stl" ); }
// https://plus.google.com/u/0/117663015413546257905/posts/BnCEkdNiTZ2 public static void TwinDodecs() { Tiling tiling = new Tiling(); TilingConfig config = new TilingConfig( 5, 3 ); tiling.GenerateInternal( config, Polytope.Projection.VertexCentered ); // Vertex-centered makes infinities tricky Dodec dodec = new Dodec(); foreach( Tile tile in tiling.Tiles ) foreach( Segment seg in tile.Boundary.Segments ) { Vector3D p1 = seg.P1, p2 = seg.P2; if( Infinity.IsInfinite( p1 ) ) p1 = Infinity.InfinityVector; if( Infinity.IsInfinite( p2 ) ) p2 = Infinity.InfinityVector; dodec.Verts.Add( p1 ); dodec.Verts.Add( p2 ); dodec.Midpoints.Add( Halfway( p1, p2 ) ); } // Now recursively add more vertices. HashSet<Vector3D> allVerts = new HashSet<Vector3D>(); foreach( Vector3D v in dodec.Verts ) allVerts.Add( v ); RecurseTwins( allVerts, dodec, 0 ); using( StreamWriter sw = File.CreateText( "dual_dodecs_points_sphere.pov" ) ) { foreach( Vector3D vert in allVerts ) { Vector3D onSphere = Sterographic.PlaneToSphereSafe( vert ); sw.WriteLine( PovRay.Sphere( new Sphere() { Center = onSphere, Radius = 0.01 } ) ); //if( !Infinity.IsInfinite( vert ) ) // sw.WriteLine( PovRay.Sphere( new Sphere() { Center = vert, Radius = 0.01 } ) ); } } }