/// <summary> /// Calculates the point of our simplex that is at the middle of a face. /// </summary> private static Vector3D FaceCenterBall(int p, int q, int r) { Geometry cellGeometry = Geometry2D.GetGeometry(p, q); switch (cellGeometry) { case Geometry.Spherical: { Vector3D cellCenter = CellCenterBall(p, q, r); Sphere[] mirrors = Mirrors(p, q, r, moveToBall: true); return(mirrors[0].ProjectToSurface(cellCenter)); } case Geometry.Euclidean: { Sphere[] mirrors = Mirrors(p, q, r, moveToBall: false); Vector3D faceCenterUHS = mirrors[0].Center; faceCenterUHS.Z += mirrors[0].Radius; return(H3Models.UHSToBall(faceCenterUHS)); } case Geometry.Hyperbolic: { throw new System.NotImplementedException(); } } throw new System.ArgumentException(); }
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)); }
public static Vector3D[] VertsEuclidean() { int p = 4; int q = 3; //int r = 4; // Get a {q,p} tiling on the z=0 plane. Segment[] baseTileSegments = BaseTileSegments(q, p); // These will be unit length. Vector3D pFaceDirection = H3Models.UHSToBall(baseTileSegments.First().P1); Vector3D pMidEdgeDirection = H3Models.UHSToBall(baseTileSegments.First().Midpoint); Vector3D pVertexDirection = new Vector3D(0, 0, -1); // Order is same as facets (these are the points opposite facets). List <Vector3D> verts = new List <Vector3D>(); verts.Add(new Vector3D()); verts.Add(pFaceDirection * m_eScale); verts.Add(pMidEdgeDirection * Math.Sqrt(2) * m_eScale); verts.Add(pVertexDirection * Math.Sqrt(3) * m_eScale); // Apply rotations. double rotation = Math.PI / 2; Vector3D zAxis = new Vector3D(0, 0, 1); for (int i = 0; i < 4; i++) { verts[i].RotateAboutAxis(zAxis, rotation); } return(verts.ToArray()); }
/// <summary> /// Calculates the point of our simplex that is at a vertex. /// </summary> public static Vector3D VertexPointBall(int p, int q, int r) { Geometry vertexGeometry = Geometry2D.GetGeometry(q, r); if (vertexGeometry == Geometry.Hyperbolic) { // Outside the ball, and not in a good way. Use the Klein version. //throw new System.NotImplementedException(); return(new Vector3D(0, 0, -1)); } // Get in UHS first. Sphere cellFacet = Mirrors(p, q, r, moveToBall: false).First(); double rSquared = Math.Pow(cellFacet.Radius, 2); double cSquared = Math.Pow(cellFacet.Center.Abs(), 2); Vector3D uhs; if (Tolerance.Equal(rSquared, cSquared)) // e.g. 363 { uhs = new Vector3D(); } else { double height = Math.Sqrt(rSquared - cSquared); uhs = new Vector3D(0, 0, height); } return(H3Models.UHSToBall(uhs)); }
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 static Sphere[] GetSpheres(Sphere[] facets, Vector3D[] verts, Vector3D interiorPoint, double inSphereHRad) { // Get relevant points (near) inSphere. Vector3D[] transformed = verts.Select(v => { v = H3Models.Transform_PointToOrigin(v, interiorPoint); v.Normalize(); v *= DonHatch.h2eNorm(inSphereHRad * .5); v = H3Models.Transform_PointToOrigin(v, -interiorPoint); return(v); }).ToArray(); List <Sphere> result = new List <R3.Geometry.Sphere>(); result.Add(ConstructSphere(facets, transformed[0], new int[] { 1, 2, 3 })); result.Add(ConstructSphere(facets, transformed[1], new int[] { 0, 2, 3 })); result.Add(ConstructSphere(facets, transformed[2], new int[] { 0, 1, 3 })); result.Add(ConstructSphere(facets, transformed[3], new int[] { 0, 1, 2 })); return(result.ToArray()); /*Vector3D[] verts = SimplexCalcs.VertsBall( p, q, r ); * for( int i = 0; i < 4; i++ ) * { * double hDist = H3Models.Ball.HDist( cen, verts[i] ) - .05; * System.Diagnostics.Trace.WriteLine( hDist + " " + DonHatch.h2eNorm( hDist ) ); * }*/ }
private static H3.Cell.Edge[] ParameterizedFibers(Complex z) { List <H3.Cell.Edge> fibers = new List <H3.Cell.Edge>(); double scale = 0.1; Vector3D v1 = new Vector3D(0, -1); // -i Vector3D v2 = Vector3D.FromComplex(z); int count = (int)Math.Round(Math.Sqrt(NumFibers), 0); for (int i = -count / 2; i < count / 2; i++) { for (int j = 1; j < count; j++) // dilations should remain positive. { double t1 = scale * i; double t2 = scale * j; // Apply the dilation first. Vector3D _v1 = v1; Vector3D _v2 = v2; _v1 *= t2; _v2 *= t2; _v1.X += t1; _v2.X += t1; fibers.Add(new H3.Cell.Edge( H3Models.UHSToBall(_v1), H3Models.UHSToBall(_v2))); } } return(fibers.ToArray()); }
/// <summary> /// Gets fibers for the only fibration with parallel (vs. ultraparallel) fibers. /// Returns result in the ball model. /// </summary> private static H3.Cell.Edge[] ParallelFibers() { List <H3.Cell.Edge> fibers = new List <H3.Cell.Edge>(); double scale = 0.3; // Just a grid of vertical fibers. // We could do any kind of grid we want here really (square, hexagonal, random...) // Each would likely produce different results. // It'd be nice to figure out how to space out the results near the north pole. int count = (int)Math.Round(Math.Sqrt(NumFibers), 0); for (int i = -count / 2; i < count / 2; i++) { for (int j = -count / 2; j < count / 2; j++) { //double off1 = Math.Pow( scale*i, 3 ); //double off2 = Math.Pow( scale*j, 3 ); double off1 = scale * i; double off2 = scale * j; Vector3D v1 = new Vector3D(off1, off2); Vector3D v2 = new Vector3D(double.PositiveInfinity, 1); // Don't use Infinity.InfinityVector, because we want to distiguish this point as being on the boundary. fibers.Add(new H3.Cell.Edge( H3Models.UHSToBall(v1), H3Models.UHSToBall(v2))); } } return(fibers.ToArray()); }
private static Vector3D Transform(Vector3D v) { //v *= 1.35; //v *= 2; v = H3Models.UHSToBall(v); return(v); }
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 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; } } }
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> /// Returns the 6 simplex edges in the Ball model. /// </summary> public static H3.Cell.Edge[] SimplexEdgesBall(int p, int q, int r) { H3.Cell.Edge[] edges = SimplexEdgesUHS(p, q, r); foreach (H3.Cell.Edge e in edges) { e.Start = H3Models.UHSToBall(e.Start); e.End = H3Models.UHSToBall(e.End); } return(edges); }
public static Vector3D EdgeMidpointSpherical(int p, int q, int r) { // Get a {q,p} tiling on the z=0 plane. Segment[] baseTileSegments = BaseTileSegments(q, p); Vector3D direction = H3Models.UHSToBall(baseTileSegments.First().Midpoint); direction.Normalize(); double midRadius = Spherical2D.s2eNorm(Honeycomb.MidRadius(p, q, r)); return(direction * midRadius); }
void CalcFibers(Vector3D[] basePoints, List <H3.Cell.Edge> fibers, double t) { foreach (Vector3D v in basePoints) { H3.Cell.Edge e = CalcFiberFromBase(v); if (e != null) { e.Color = Color(Transform(H3Models.UHSToBall(v), t)); } fibers.Add(Transform(e, t)); } }
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)); } } }
public static Vector3D FaceCenterSpherical(int p, int q, int r) { // Get a {q,p} tiling on the z=0 plane. Segment[] baseTileSegments = BaseTileSegments(q, p); // This will be unit length. Vector3D pFaceDirection = H3Models.UHSToBall(baseTileSegments.First().P1); // In-radius is in conformal model double inRadius = Spherical2D.s2eNorm(Honeycomb.InRadius(p, q, r)); return(pFaceDirection * inRadius); }
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 ); */ } }
public static Vector3D Transform(Vector3D v) { double angle = Math.PI / 3; // Kind of weird, and not really controllable. v.RotateAboutAxis(new Vector3D(1, 0), angle); Mobius m = new Mobius(); m.Isometry(Geometry.Hyperbolic, 0, new Complex(0, 0.5)); v = H3Models.TransformHelper(v, m); v.RotateAboutAxis(new Vector3D(1, 0), -angle); return(v); }
// This was used for making some images "beyond infinity" (paper appendix). //private static double m_jOffset; /// <summary> /// Inputs must be in UHS! /// </summary> public static void PrepForFacetCentering(int p, int q, Sphere[] spheres, ref Vector3D cellCenter) { Mobius m = FCOrientMobius(p, q); foreach (Sphere s in spheres) { H3Models.TransformInUHS2(s, m); } spheres[3].Center *= -1; // Super-hack for 437 & 737, since TransformInUHS2 function is falling short. //spheres[2].Center *= -1; cellCenter = m.ApplyToQuaternion(cellCenter); }
/// <summary> /// Face centered orientation. /// </summary> internal static void FCOrient(H3.Cell cell) { // First, need to scale so the lowest triangles are the same size, // then reorient so that one triangle is oriented along z axis, // then scale so that the triangle is flat. // Calculate how much we need to offset to make the cell facet flat. Mobius m = FCOrientMobius(cell.Facets[0].Sphere); foreach (H3.Cell.Facet f in cell.Facets) { H3Models.TransformInBall2(f.Sphere, m); } cell.Center = H3Models.TransformHelper(cell.Center, m); }
/// <summary> /// XXX - Need to make this a function of clock, so it probably needs to not be static. /// </summary> /// <param name="basePointUHS"></param> /// <returns>A base point in the disk, possibly transformed.</returns> Vector3D Transform(Vector3D basePointUHS, double t) { if (!Ball) { return(basePointUHS); } Vector3D basePointDisk = H3Models.UHSToBall(basePointUHS); // Apply transformations. // XXX - make this a mobius we pass in, so we can edit it on the outside. //basePointDisk.RotateAboutAxis( new Vector3D( 0, 1, 0 ), 2 * Math.PI * t ); return(basePointDisk); }
private static string H3Edge(Parameters parameters, H3.Cell.Edge edge) { Vector3D v1 = edge.Start, v2 = edge.End; Vector3D[] points = null; Func <Vector3D, Sphere> sizeFunc = v => new Sphere() { Center = v, Radius = H3Models.SizeFuncConst(v, parameters.Scale) }; if (parameters.Halfspace) { points = H3Models.UHS.GeodesicPoints(v1, v2); if (!parameters.ThinEdges) { sizeFunc = v => { // XXX, inexact return(new Sphere() { Center = v, Radius = H3Models.UHS.SizeFunc(v, parameters.AngularThickness) }); } } ; } else { points = H3Models.Ball.GeodesicPoints(v1, v2); if (!parameters.ThinEdges) { sizeFunc = v => { Vector3D c; double r; H3Models.Ball.DupinCyclideSphere(v, parameters.AngularThickness / 2, out c, out r); return(new Sphere() { Center = c, Radius = r }); //return new Sphere() { Center = v, Radius = H3Models.Ball.SizeFunc( v, parameters.AngularThickness ) }; // inexact } } ; } return(H3EdgeSphereSweep(points, sizeFunc)); }
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 Vector3D VertexPointKlein(int p, int q, int r) { Geometry vertexGeometry = Geometry2D.GetGeometry(q, r); if (vertexGeometry != Geometry.Hyperbolic) { throw new System.NotImplementedException(); } Sphere[] mirrors = Mirrors(p, q, r); Sphere klein = H3Models.BallToKlein(mirrors[0]); Vector3D off = klein.Offset; double h = off.Abs() / Math.Cos(off.AngleTo(new Vector3D(0, 0, -1))); return(new Vector3D(0, 0, -h)); }
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); }
/// <summary> /// Get a distribution of points on a sphere. /// The points are the vertices of a geodesic dome. /// </summary> private static Vector3D[] SpherePoints() { List <Vector3D> spherePoints = new List <Vector3D>(); TilingConfig config = new TilingConfig(3, 5); Tiling tiling = new Tiling(); tiling.GenerateInternal(config); Tile baseTile = tiling.Tiles.First(); Vector3D[] templateTextureCoords = TextureHelper.TextureCoords(baseTile.Boundary, Geometry.Spherical, doGeodesicDome: true); foreach (Tile tile in tiling.Tiles) { Isometry isom = new Isometry(); isom.CalculateFromTwoPolygons(baseTile, tile, Geometry.Spherical); Vector3D[] textureCoords = Isometry.TransformVertices(templateTextureCoords, isom.Inverse()); spherePoints.AddRange(textureCoords); } return(spherePoints.Select(p => H3Models.UHSToBall(p)).Distinct().ToArray()); }
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 Sphere[] MirrorsEuclidean() { int p = 4; int q = 3; //int r = 4; // Get a {q,p} tiling on the z=0 plane. Segment[] baseTileSegments = BaseTileSegments(q, p); // This will be unit length. Vector3D pFaceDirection = H3Models.UHSToBall(baseTileSegments.First().P1); // NOTES: // Center is the plane normal. // Cell face is only one with an offset // This is constructed already in the ball. Sphere cellBoundary = new Sphere() { Center = -pFaceDirection, Offset = pFaceDirection * m_eScale, Radius = double.PositiveInfinity }; Sphere[] interior = InteriorMirrors(p, q); interior = interior.Select(s => H3Models.UHSToBall(s)).ToArray(); Sphere[] surfaces = new Sphere[] { cellBoundary, interior[0], interior[1], interior[2] }; // Apply rotations. bool applyRotations = false; if (applyRotations) { double rotation = Math.PI / 2; foreach (Sphere s in surfaces) { RotateSphere(s, rotation); } } return(surfaces); }