private static List <Vector3D[]> BasePointsTiling() { TilingConfig config = new TilingConfig(3, 7, maxTiles: 100); Tiling tiling = new Tiling(); tiling.Generate(config); HashSet <H3.Cell.Edge> finished = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer()); int numPerSeg = 25; List <Vector3D[]> basePoints = new List <Vector3D[]>(); foreach (Tile t in tiling.Tiles) { foreach (Segment s in t.Boundary.Segments) { H3.Cell.Edge e = new H3.Cell.Edge(s.P1, s.P2); if (finished.Contains(e)) { continue; } finished.Add(e); Vector3D[] points = s.Subdivide(numPerSeg).Select(p => { p = new Vector3D(p.X, 0, p.Y); return(H3Models.BallToUHS(p)); }).ToArray(); basePoints.Add(points); } } return(basePoints); }
/// <summary> /// Generate a catenoid, then move it to a point on the hemisphere in S^3. /// </summary> private static Mesh Catenoid(double scale, Vector3D loc, double rld_height, double waist) { double h = waist * 3.5; //Mesh mesh = StandardCatenoid( waist, h ); Mesh mesh = CatenoidSquared(waist, h); mesh.Scale(scale * rld_height * 2 / h); // To make the catenoid meet up with the RLD solution. // First move to north pole, then rotate down to the location. Func <Vector3D, Vector3D> transform = v => { v = H3Models.BallToUHS(v); Vector3D northPole = new Vector3D(0, 0, 1); Vector3D axis = loc.Cross(northPole); if (!axis.Normalize()) // North or south pole? { return(v); } double anglXY = Euclidean2D.AngleToCounterClock(new Vector3D(1, 0), new Vector3D(loc.X, loc.Y)); v.RotateXY(anglXY); double angleDown = loc.AngleTo(northPole); v.RotateAboutAxis(axis, angleDown); if (v.DNE || Infinity.IsInfinite(v)) { throw new System.Exception(); } return(v); }; mesh.Transform(transform); return(mesh); }
private Vector3D ApplyTransformationToSphere(Vector3D v, double t) { v = H3Models.BallToUHS(v); // 437 (hyperbolic) //v *= Math.Pow( 4.259171776329806, t*10-5 ); // 36i (parabolic) //v += new Vector3D( Math.Cos( Math.PI / 6 ), Math.Sin( Math.PI / 6 ) ) * t; // iii (loxodromic) //Complex c = v.ToComplex(); //double x = Math.Sqrt( 2 ) - 1; //Mobius m = new Mobius( new Complex( x, 0 ), Complex.One, new Complex( -x, 0 ) ); // 12,12,12 loxodromic //m = new Mobius( new Complex( 0, 1 ), Complex.One, new Complex( 0, -1 ) ); /* * c = m.Apply( c ); * c *= Complex.Exp( new Complex( 2.5, 4 * Math.PI ) * t ); * c = m.Inverse().Apply( c ); * v = Vector3D.FromComplex( c ); */ // Center cell head in KolorEyes. Mobius m = new Mobius(); m.UpperHalfPlane(); v = m.Inverse().Apply(v); return(H3Models.UHSToBall(v)); }
private static H3.Cell.Edge CalcFiber(Vector3D boundaryPointBall) { bool parallel = false; if (parallel) { Vector3D v2 = new Vector3D(0, 0, -1); // Really we can pick any boundary point. return(new H3.Cell.Edge(boundaryPointBall, v2)); } else { // If the point is above the real line, it will have been connected to z. // If below the real line, it will have been connected to -i // If on the real line, it's degenerate. Vector3D pUHS = H3Models.BallToUHS(boundaryPointBall); if (Tolerance.Equal(pUHS.Y, 0)) { return(null); } Vector3D z = Vector3D.FromComplex(ZParam); Vector3D minusi = new Vector3D(0, -1); double dilation = double.NaN; double translation = double.NaN; if (pUHS.Y > 0) { dilation = pUHS.Y / z.Y; z *= dilation; translation = pUHS.X - z.X; z.X += translation; if (H3Models.UHSToBall(z) != boundaryPointBall) { throw new System.Exception(); } minusi *= dilation; minusi.X += translation; return(new H3.Cell.Edge(H3Models.UHSToBall(minusi), boundaryPointBall)); //return null; } else { dilation = pUHS.Y / -1; minusi *= dilation; translation = pUHS.X - minusi.X; minusi.X += translation; if (H3Models.UHSToBall(minusi) != boundaryPointBall) { throw new System.Exception(); } z *= dilation; z.X += translation; return(new H3.Cell.Edge(boundaryPointBall, H3Models.UHSToBall(z))); //return null; } } }
private void DrawMirrors(Bitmap image, Settings settings) { double b = settings.Bounds; ImageSpace i = new ImageSpace(settings.Width, settings.Height); i.XMin = -b; i.XMax = b; i.YMin = -b; i.YMax = b; float scale = 2; List <Sphere> toDraw = new List <Sphere>(); toDraw.AddRange(settings.Mirrors); //toDraw.Add( AlteredFacetForTrueApparent2DTilings( settings.Mirrors ) ); using (Graphics g = Graphics.FromImage(image)) using (Pen p = new Pen(Color.Red, scale * 3.0f)) //using( Pen p2 = new Pen( Color.FromArgb( 255, 255, 214, 0 ), 3.0f ) ) using (Pen p2 = new Pen(Color.Orange, scale * 3.0f)) using (Pen p3 = new Pen(Color.Orange, scale * 3.0f)) for (int m = 0; m < toDraw.Count; m++) { Sphere s = toDraw[m]; Circle c = H3Models.UHS.IdealCircle(s); // XXX - not correct if (c.IsLine) { DrawUtils.DrawLine(-c.P2 * 25, c.P2 * 25, g, i, p); // XXX - not general. } else { Sphere temp = H3Models.BallToUHS(s); DrawUtils.DrawCircle(new Circle { Center = temp.Center, Radius = temp.Radius }, g, i, m == 0 ? p2 : m == 4 ? p3 : p); } /* // iii * Circle c = new Circle(); * c.Radius = Math.Sqrt( 2 ); * c.Center = new Vector3D( 1, Math.Sqrt( 2 ) ); * DrawUtils.DrawCircle( c, g, i, p ); * c.Center = new Vector3D( -1, Math.Sqrt( 2 ) ); * DrawUtils.DrawCircle( c, g, i, p ); * c.Center = new Vector3D( Math.Sqrt( 2 ) - 1, 0 ); * c.Radius = 2 - Math.Sqrt( 2 ); * DrawUtils.DrawCircle( c, g, i, p ); * * DrawUtils.DrawLine( new Vector3D( -2, 0 ), new Vector3D( 2, 0 ), g, i, p ); */ } }
internal static void CalcSelfSimilarityScale() { double inRadius = DonHatch.h2eNorm(Honeycomb.InRadius(4, 3, 7)); Vector3D facePoint = new Vector3D(0, 0, -inRadius); Sphere s = H3Models.Ball.OrthogonalSphereInterior(facePoint); Vector3D facePoint2 = new Vector3D(0, 0, inRadius); facePoint2 = s.ReflectPoint(facePoint2); facePoint = H3Models.BallToUHS(facePoint); facePoint2 = H3Models.BallToUHS(facePoint2); double scale = facePoint.Z / facePoint2.Z; scale += 0; }
public static void GenImage2() { int size = 10000; Bitmap image = new Bitmap(size, size); ImageSpace iSpace = new ImageSpace(size, size); double b = 1.0; iSpace.XMin = 0; iSpace.XMax = b; iSpace.YMin = 0; iSpace.YMax = b; Vector3D cen = HoneycombPaper.InteriorPointBall; cen = H3Models.BallToUHS(cen); Sphere[] simplex = Simplex(ref cen); Sphere inSphere = InSphere(simplex); using (Graphics g = Graphics.FromImage(image)) { g.Clear(Color.White); int count = 75; double offset = b / count / 2; for (int i = 0; i < count; i++) { for (int j = 0; j < count; j++) { Vector3D center = new Vector3D(2 * offset * i, 2 * offset * j); Circle circ = new Circle { Center = center, Radius = offset * .85 }; using (Brush brush = new SolidBrush(Color.DarkBlue)) DrawUtils.DrawFilledCircle(circ, g, iSpace, brush); } } } image.Save("fundamental.png", ImageFormat.Png); }
public static void GenImage() { int size = 1000; Bitmap image = new Bitmap(size, size); ImageSpace i = new ImageSpace(size, size); double b = 1.1; i.XMin = -b; i.XMax = b; i.YMin = -b; i.YMax = b; Vector3D cen = HoneycombPaper.InteriorPointBall; cen = H3Models.BallToUHS(cen); Sphere[] simplex = Simplex(ref cen); Sphere inSphere = InSphere(simplex); using (Graphics g = Graphics.FromImage(image)) foreach (int[] reflections in AllCells()) { Sphere clone = inSphere.Clone(); foreach (int r in reflections) { clone.Reflect(simplex[r]); } Sphere ball = new Sphere(); Circle3D inSphereIdealBall = ball.Intersection(clone); Circle3D inSphereIdealUHS = H3Models.BallToUHS(inSphereIdealBall); Circle inSphereIdeal = new Circle { Center = inSphereIdealUHS.Center, Radius = inSphereIdealUHS.Radius }; using (Brush brush = new SolidBrush(Color.Blue)) DrawUtils.DrawFilledCircle(inSphereIdeal, g, i, brush); } image.Save("threefifty.png", ImageFormat.Png); }
public static void PovRayModel() { Vector3D cen = HoneycombPaper.InteriorPointBall; cen = H3Models.BallToUHS(cen); Sphere[] simplex = Simplex(ref cen); H3.Cell[] simplicesFinal = GenTruss(simplex, null, cen, ball: true); string fileName = "350cell.pov"; System.IO.File.Delete(fileName); foreach (H3.Cell cell in simplicesFinal) { //int[] include = new int[] { 0, 1, 2, 3 }; int[] include = new int[] { 0 }; PovRay.AppendSimplex(cell.Facets.Select(f => f.Sphere).ToArray(), cell.Center, include, fileName); } /* * HashSet<H3.Cell.Edge> axes = new HashSet<H3.Cell.Edge>( new H3.Cell.EdgeEqualityComparer() ); * H3.Cell.Edge axis = new H3.Cell.Edge( new Vector3D( 0, 0, -1 ), new Vector3D( 0, 0, 1 ) ); * axes.Add( axis ); * foreach( int[] reflections in TrussReflections() ) * { * Vector3D s = axis.Start, e = axis.End; * foreach( int ri in reflections ) * { * s = simplex[ri].ReflectPoint( s ); * e = simplex[ri].ReflectPoint( e ); * } * axes.Add( new H3.Cell.Edge( s, e ) ); * } * PovRay.WriteH3Edges( new PovRay.Parameters { AngularThickness = 0.045 }, axes.ToArray(), "axes.pov" ); * * H3.Cell.Edge[] fibers = new H3.Cell.Edge[] { axis }; * fibers = Recurse.CalcEdges( simplex.Skip(1).ToArray(), fibers ); * PovRay.WriteH3Edges( new PovRay.Parameters { AngularThickness = 0.025 }, fibers, "axes.pov" );*/ }
/// <summary> /// Returns the 6 simplex edges in the UHS model. /// </summary> public static H3.Cell.Edge[] SimplexEdgesUHS(int p, int q, int r) { // Only implemented for honeycombs with hyperideal cells right now. if (!(Geometry2D.GetGeometry(p, q) == Geometry.Hyperbolic)) { throw new System.NotImplementedException(); } Sphere[] simplex = SimplexCalcs.Mirrors(p, q, r, moveToBall: false); Circle[] circles = simplex.Select(s => H3Models.UHS.IdealCircle(s)).ToArray(); Vector3D[] defPoints = new Vector3D[6]; Vector3D dummy; Euclidean2D.IntersectionLineCircle(circles[1].P1, circles[1].P2, circles[0], out defPoints[0], out dummy); Euclidean2D.IntersectionLineCircle(circles[2].P1, circles[2].P2, circles[0], out defPoints[1], out dummy); Euclidean2D.IntersectionLineCircle(circles[1].P1, circles[1].P2, circles[3], out defPoints[2], out dummy); Euclidean2D.IntersectionLineCircle(circles[2].P1, circles[2].P2, circles[3], out defPoints[3], out dummy); Circle3D c = simplex[0].Intersection(simplex[3]); Vector3D normal = c.Normal; normal.RotateXY(Math.PI / 2); Vector3D intersection; double height, off; Euclidean2D.IntersectionLineLine(c.Center, c.Center + normal, circles[1].P1, circles[1].P2, out intersection); off = (intersection - c.Center).Abs(); height = Math.Sqrt(c.Radius * c.Radius - off * off); intersection.Z = height; defPoints[4] = intersection; Euclidean2D.IntersectionLineLine(c.Center, c.Center + normal, circles[2].P1, circles[2].P2, out intersection); off = (intersection - c.Center).Abs(); height = Math.Sqrt(c.Radius * c.Radius - off * off); intersection.Z = height; defPoints[5] = intersection; // Hyperideal vertex too? bool order = false; H3.Cell.Edge[] edges = null; if (Geometry2D.GetGeometry(q, r) == Geometry.Hyperbolic) { edges = new H3.Cell.Edge[] { new H3.Cell.Edge(new Vector3D(), new Vector3D(0, 0, 10)), new H3.Cell.Edge(defPoints[4], defPoints[5], order), new H3.Cell.Edge(defPoints[0], defPoints[4], order), new H3.Cell.Edge(defPoints[1], defPoints[5], order), new H3.Cell.Edge(defPoints[2], defPoints[4], order), new H3.Cell.Edge(defPoints[3], defPoints[5], order), }; } else { Vector3D vPointUHS = H3Models.BallToUHS(VertexPointBall(p, q, r)); defPoints[0] = defPoints[1] = vPointUHS; edges = new H3.Cell.Edge[] { new H3.Cell.Edge(vPointUHS, new Vector3D(0, 0, 10)), new H3.Cell.Edge(defPoints[4], defPoints[5], order), new H3.Cell.Edge(defPoints[0], defPoints[4], order), new H3.Cell.Edge(defPoints[1], defPoints[5], order), new H3.Cell.Edge(defPoints[2], defPoints[4], order), new H3.Cell.Edge(defPoints[3], defPoints[5], order), }; } return(edges); }
/// <summary> /// This will return an altered facet to create true apparent 2D tilings (proper bananas) on the boundary. /// Notes: /// The input simplex must be in the ball model. /// The first mirror of the simplex (the one that mirrors across cells) is the one we end up altering. /// </summary> public static Sphere AlteredFacetForTrueApparent2DTilings(Sphere[] simplex) { //Sphere m = H3Models.BallToUHS( simplex[0] ); //Sphere t = new Sphere() { Center = m.Center, Radius = m.Radius*100 }; //return H3Models.UHSToBall( t ); // We first need to find the size of the apparent 2D disk surrounding the leg. // This is also the size of the apparent cell head disk of the dual. // So we want to get the midsphere (insphere would also work) of the dual cell with that head, // then calculate the intersection of that with the boundary. Sphere cellMirror = simplex[0]; if (cellMirror.IsPlane) { throw new System.NotImplementedException(); } // The point centered on a face is the closest point of the cell mirror to the origin. // This will be the point centered on an edge on the dual cell. Vector3D facePoint = cellMirror.ProjectToSurface(new Vector3D()); // Reflect it to get 3 more points on our midsphere. Vector3D reflected1 = simplex[1].ReflectPoint(facePoint); Vector3D reflected2 = simplex[2].ReflectPoint(reflected1); Vector3D reflected3 = simplex[0].ReflectPoint(reflected2); Sphere midSphere = Sphere.From4Points(facePoint, reflected1, reflected2, reflected3); // Get the ideal circles of the cell mirror and midsphere. // Note: The midsphere is not geodesic, so we can't calculate it the same. Sphere cellMirrorUHS = H3Models.BallToUHS(cellMirror); Circle cellMirrorIdeal = H3Models.UHS.IdealCircle(cellMirrorUHS); Sphere ball = new Sphere(); Circle3D midSphereIdealBall = ball.Intersection(midSphere); // This should exist because we've filtered for honeycombs with hyperideal verts. Circle3D midSphereIdealUHS = H3Models.BallToUHS(midSphereIdealBall); Circle midSphereIdeal = new Circle { Center = midSphereIdealUHS.Center, Radius = midSphereIdealUHS.Radius }; // The intersection point of our cell mirror and the disk of the apparent 2D tiling // gives us "ideal" points on the apparent 2D boundary. These points will be on the new cell mirror. Vector3D i1, i2; if (2 != Euclidean2D.IntersectionCircleCircle(cellMirrorIdeal, midSphereIdeal, out i1, out i2)) { //throw new System.ArgumentException( "Since we have hyperideal vertices, we should have an intersection with 2 points." ); // Somehow works in the euclidean case. // XXX - Make this better. return(H3Models.UHSToBall(new Sphere() { Center = Vector3D.DneVector(), Radius = double.NaN })); } double bananaThickness = 0.025; //bananaThickness = 0.15; bananaThickness = 0.05; // Transform the intersection points to a standard Poincare disk. // The midsphere radius is the scale of the apparent 2D tilings. double scale = midSphereIdeal.Radius; Vector3D offset = midSphereIdeal.Center; i1 -= offset; i2 -= offset; i1 /= scale; i2 /= scale; Circle3D banana = H3Models.Ball.OrthogonalCircle(i1, i2); Vector3D i3 = H3Models.Ball.ClosestToOrigin(banana); i3 = Hyperbolic2D.Offset(i3, -bananaThickness); // Transform back. i1 *= scale; i2 *= scale; i3 *= scale; i1 += offset; i2 += offset; i3 += offset; // Construct our new simplex mirror with these 3 points. Circle3D c = new Circle3D(i1, i2, i3); Sphere result = new Sphere() { Center = c.Center, Radius = c.Radius }; return(H3Models.UHSToBall(result)); }
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); } }
/// <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(); } } }
internal static Sphere SphereFuncUHS(Vector3D v) { return(H3Models.BallToUHS(SphereFuncBall(Geometry.Hyperbolic, H3Models.UHSToBall(v)))); }
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; } } }