private H3.Cell.Edge[] GenEdgesInternal(Vector3D v1, Vector3D v2, Vector3D v3, Vector3D v4) { int div = 5; List <H3.Cell.Edge> result = new List <H3.Cell.Edge>(); for (int i = 0; i <= div; i++) { Vector3D start = v1 + (v2 - v1) * i / div; Vector3D end = v3 + (v4 - v3) * i / div; start.Normalize(); end.Normalize(); start = Sterographic.S3toR3(start); end = Sterographic.S3toR3(end); if (Infinity.IsInfinite(start)) { start = end * 10; } if (Infinity.IsInfinite(end)) { end = start * 10; } result.Add(new H3.Cell.Edge(start, end)); } return(result.ToArray()); }
/// <summary> /// Returns a stereographically sphere representing us. /// </summary> public Sphere ToSphere() { // Equatorial sphere? if (Pole == new Vector3D(0, 0, 0, 1)) { return(new Sphere()); } // A plane? Vector3D poleR3 = Sterographic.S3toR3(Pole); if (Tolerance.Equal(poleR3.Abs(), 1)) { return(Sphere.Plane(poleR3)); } // Get 4 points on the sphere. Vector3D e1 = new Vector3D(1, 0, 0, 0); Vector3D e2 = new Vector3D(0, 1, 0, 0); Vector3D e3 = new Vector3D(0, 0, 1, 0); Vector3D e4 = new Vector3D(0, 0, 0, 1); System.Func <Vector3D, Vector3D> one = v => { v = Euclidean3D.ProjectOntoPlane(Pole, new Vector3D(), v); v.Normalize(); return(Sterographic.S3toR3(v)); }; return(Sphere.From4Points(one(e1), one(e2), one(e3), one(e4))); }
private static Vector3D Transform2(Vector3D p, Matrix4D mat) { p.Normalize(); p = mat.RotateVector(p); p = Sterographic.S3toR3(p); p = SphericalModels.StereoToEquidistant(p); return(p); }
private static Vector3D[] OneHopfCircleProjected(Vector3D s2Point, bool anti) { Vector3D[] circlePoints = S3.OneHopfCircle(s2Point, anti); for (int i = 0; i < circlePoints.Length; i++) { circlePoints[i] = Sterographic.S3toR3(circlePoints[i]); } return(circlePoints); }
public static void ElevenCell() { Graph g = new Graph(); g.SetupCompleteGraph(11); GraphRelaxation relaxer = new GraphRelaxation(); relaxer.Graph = g; relaxer.NodeRepulsion = 0.01; relaxer.EdgeAttraction = 0.0; relaxer.EdgeRepulsion = 0.0; relaxer.Relax(20000); Vector3D northPole = new Vector3D(0, 0, 0, 1); H3.Cell.Edge[] edges = g.Edges.Select(e => { Vector3D v1 = g.Nodes[e.V1].Position.ToVec3D(); Vector3D v2 = g.Nodes[e.V2].Position.ToVec3D(); //if( v1.Compare( northPole, .5 ) || v2.Compare( northPole, 0.5 ) ) // Cull edges near north pole. // return null; v1 = Sterographic.S3toR3(v1); v2 = Sterographic.S3toR3(v2); return(new H3.Cell.Edge(v1, v2)); }).ToArray(); edges = edges.Where(e => e != null).ToArray(); bool povray = false; if (povray) { string filename = "test.pov"; System.IO.File.Delete(filename); using (StreamWriter sw = new StreamWriter(filename)) sw.WriteLine("#include \"C:\\Users\\hrn\\Documents\\roice\\povray\\H3\\horosphere\\633.pov\""); PovRay.WriteEdges(new PovRay.Parameters { AngularThickness = 0.03 }, Geometry.Spherical, edges, filename, append: true); } else { S3.EdgesToStl(edges); } }
public static Circle3D GeodesicFrom2Points(Vector3D a, Vector3D b) { if (a == b || a == -b) { throw new System.Exception("Geodesic not unique"); } System.Func <Vector3D, Circle3D> lineFunc = p => { Circle3D circ = new Circle3D(); circ.Radius = double.PositiveInfinity; p.Normalize(); circ.Normal = p; // Hacky representation of a line. return(circ); }; if (a.IsOrigin || b.IsOrigin) { Vector3D p = a.IsOrigin ? b : a; return(lineFunc(p)); } double mag1 = a.Abs(), mag2 = b.Abs(); if (Tolerance.Equal(mag1, 1) && Tolerance.Equal(mag2, 1)) { return(new Circle3D(a, b, a * -1)); } // The antipode in S^3 of a or b will give us a 3rd point. Vector3D antipode = Sterographic.S3toR3(Sterographic.R3toS3(a) * -1); // If the antipode is also an an antipode in R3, the points are colinear // (or they are on the equatorial 2-sphere, but that is checked above). if (a == antipode * -1) { return(lineFunc(a)); } return(new Circle3D(a, b, antipode)); }
private static void Relax(Vector3D[] coordsR3, int[] elementIndices, Vector3D[] locks) { int dim = 4; Graph g = new Graph(); for (int i = 0; i < coordsR3.Length; i++) { Vector3D v = coordsR3[i]; GraphNode node = new GraphNode(new VectorND(Sterographic.R3toS3(v)), new VectorND(dim)); node.Lock = new VectorND(locks[i]); g.Nodes.Add(node); } for (int i = 0; i < elementIndices.Length; i += 3) { int a = elementIndices[i]; int b = elementIndices[i + 1]; int c = elementIndices[i + 2]; g.AddEdge(new GraphEdge(a, b)); g.AddEdge(new GraphEdge(b, c)); g.AddEdge(new GraphEdge(c, a)); } GraphRelaxation relaxer = new GraphRelaxation(); relaxer.Graph = g; relaxer.NodeRepulsion = 0; relaxer.EdgeAttraction = 0.5; relaxer.EdgeRepulsion = 0; relaxer.Relax(1000); for (int i = 0; i < coordsR3.Length; i++) { GraphNode node = g.Nodes[i]; coordsR3[i] = Sterographic.S3toR3(node.Position.ToVec3D()); } }
private static void CompoundOfFive24Cells(ref H3.Cell.Edge[] edges) { List <H3.Cell.Edge> allEdges = new List <H3.Cell.Edge>(); Vector3D v600 = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 3, 5)); Vector3D v24 = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 4, 3)); Sphere[] mirrors600 = SimplexCalcs.MirrorsSpherical(3, 3, 5); double a24 = v24.AngleTo(Sterographic.R3toS3(new Vector3D())); double a600 = v600.AngleTo(Sterographic.R3toS3(new Vector3D())); Matrix4D m600 = Matrix4D.MatrixToRotateinCoordinatePlane(a600, 2, 3); Matrix4D m600_ = Matrix4D.MatrixToRotateinCoordinatePlane(-a600, 2, 3); Matrix4D m24 = Matrix4D.MatrixToRotateinCoordinatePlane(a24, 2, 3); Matrix4D m24_ = Matrix4D.MatrixToRotateinCoordinatePlane(-a24, 2, 3); double eLength = 2 * Math.PI / 10; // 600-cell edge length double a_id = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 2)); eLength = 1.0 / Math.Sin(2 * Math.PI / 5); // icosahedron edge length double a_i = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 5)); Func <Vector3D, Vector3D> rot600 = v => { v = Sterographic.R3toS3(v); v = m600.RotateVector(v); v = Sterographic.S3toR3(v); return(v); }; Func <Vector3D, int, Vector3D> rotOne = (v, idx) => { v = Sterographic.R3toS3(v); v = m24.RotateVector(v); v = Sterographic.S3toR3(v); v.RotateAboutAxis(new Vector3D(1, 0, 0), -a_id); // Vertex to cell center. v = Sterographic.R3toS3(v); v = m600_.RotateVector(v); v = Sterographic.S3toR3(v); List <int> reflections = new List <int>(); if (idx == 0) { reflections.Add(2); reflections.Add(1); reflections.Add(2); reflections.Add(0); reflections.Add(1); reflections.Add(2); reflections.Add(1); reflections.Add(2); } if (idx != 0) { reflections.Add(3); } if (idx == 2) { reflections.Add(1); reflections.Add(2); } if (idx == 3) { reflections.Add(2); reflections.Add(1); } if (idx == 4) { reflections.Add(1); reflections.Add(0); reflections.Add(1); reflections.Add(2); reflections.Add(0); reflections.Add(1); reflections.Add(0); reflections.Add(1); } foreach (int reflection in reflections) { v = mirrors600[reflection].ReflectPoint(v); } v = Sterographic.R3toS3(v); v = m600.RotateVector(v); v = Sterographic.S3toR3(v); //v.RotateAboutAxis( new Vector3D( 0, 0, 1 ), Math.PI/3 ); //v.RotateAboutAxis( new Vector3D( 1, 0, 0 ), -a_i*2 ); v = Sterographic.R3toS3(v); //v = m24_.RotateVector( v ); v = Sterographic.S3toR3(v); return(v); }; for (int i = 0; i < 5; i++) { //if( i == 0 ) // continue; allEdges.AddRange(edges.Select(e => { H3.Cell.Edge newEdge = new H3.Cell.Edge(rotOne(e.Start, i), rotOne(e.End, i)); //H3.Cell.Edge newEdge = new H3.Cell.Edge( rot600( e.Start ), rot600( e.End ) ); switch (i) { case 0: newEdge.Color = new Vector3D(1, 0, 0, 1); //newEdge.Color = new Vector3D( 1, 1, 1, 0 ); break; case 1: newEdge.Color = new Vector3D(0, 1, 0, 2); break; case 2: newEdge.Color = new Vector3D(0, 0, 1, 3); break; case 3: newEdge.Color = new Vector3D(1, 0, 1, 4); break; case 4: newEdge.Color = new Vector3D(0, 1, 1, 5); break; } return(newEdge); })); } edges = allEdges.ToArray(); //edges = edges.Where( e => Tolerance.Equal( 1, e.Start.Abs() ) || Tolerance.Equal( 1, e.End.Abs() ) ).ToArray(); HashSet <Vector3D> uniqueVerts = new HashSet <Vector3D>(); foreach (H3.Cell.Edge e in edges) { uniqueVerts.Add(e.Start); uniqueVerts.Add(e.End); } System.Diagnostics.Trace.WriteLine("Number of verts = " + uniqueVerts.Count); /*edges = edges.Where( e => * { * Vector3D v = Tolerance.Equal( 1, e.Start.Abs() ) ? e.End : e.Start; * if( v.Abs() >= 0.8 || v.Abs() <= 0.7 ) * return false; * * if( Tolerance.LessThanOrEqual( v.X, 0 ) || Tolerance.GreaterThanOrEqual( v.Y, 0 ) || Tolerance.GreaterThanOrEqual( v.Z, 0 ) ) * return false; * * return true; * } ).ToArray(); * * edges = edges.OrderBy( e => Tolerance.Equal( 1, e.Start.Abs() ) ? e.End.Abs() : e.Start.Abs() ).ToArray();*/ }
public static void S3BiHelicoid() { double cutoff = 8.0; int div = 500; Matrix4D mat = Matrix4D.MatrixToRotateinCoordinatePlane(1 * Math.PI / 4, 0, 3); Mesh m1 = S3Helicoid(div, mat, reciprocal: false); //m1.Triangles = m1.Triangles.Where( t => t.a.Abs() < cutoff && t.b.Abs() < cutoff && t.c.Abs() < cutoff ).ToList(); Mesh m2 = S3Helicoid(div, mat, reciprocal: true); //m2.Triangles = m2.Triangles.Where( t => t.a.Abs() < cutoff && t.b.Abs() < cutoff && t.c.Abs() < cutoff ).ToList(); Mesh m3 = new Mesh(); System.Action <bool> addCore = recip => { List <Vector3D> circlePoints = new List <Vector3D>(); double aOffset = 2 * Math.PI / div; for (int i = 0; i <= div; i++) { double x = Math.Sin(aOffset * i); double y = Math.Cos(aOffset * i); circlePoints.Add(recip ? new Vector3D(x, y) : new Vector3D(0, 0, x, y)); } // partial transform to R3 here. circlePoints = circlePoints.Select(p => { p = mat.RotateVector(p); p = Sterographic.S3toR3(p); return(p); }).ToList(); List <Vector3D> ePoints = new List <Vector3D>(); List <double> eRadii = new List <double>(); foreach (Vector3D pNE in circlePoints) { Sphere sphere = SphereFuncBall(Geometry.Spherical, pNE, false); ePoints.Add(sphere.Center); eRadii.Add(sphere.Radius); } Shapeways shapeways = new Shapeways(); shapeways.AddClosedCurve(ePoints.ToArray(), eRadii.ToArray()); m3.Append(shapeways.Mesh); }; addCore(false); addCore(true); for (int i = 0; i < m3.Triangles.Count; i++) { Mesh.Triangle t = m3.Triangles[i]; m3.Triangles[i] = Transform(t, SphericalModels.StereoToEquidistant); } string filename = "helicoid.stl"; File.Delete(filename); using (StreamWriter sw = File.AppendText(filename)) { STL.AppendMeshToSTL(m1, sw); STL.AppendMeshToSTL(m2, sw); STL.AppendMeshToSTL(m3, sw); } //HelicoidHelper( thinMesh, boundaryPoints ); }
public void Gen(int p, int q, int r) { Geometry g = Util.GetGeometry(p, q, r); if (g != Geometry.Spherical) { throw new System.Exception("Point group code only for spherical geometry."); } Simplex simplex = new Simplex(); simplex.Facets = SimplexCalcs.Mirrors(p, q, r); Vector3D cen = new Vector3D(); Vector3D faceCenter = SimplexCalcs.FaceCenterSpherical(p, q, r); Vector3D edgeMid = SimplexCalcs.EdgeMidpointSpherical(p, q, r); Vector3D vertex = SimplexCalcs.VertexSpherical(p, q, r); List <Vector3D> startingPoles = new List <Vector3D>(); startingPoles.Add(Sterographic.S3toR3(GreatSphere.FromSphere(simplex.Facets[0]).Pole)); GreatSphere[] spheres = CalcSpheres(simplex.Facets, startingPoles.ToArray()); string filename = "point_group.pov"; using (StreamWriter sw = File.CreateText(filename)) { //foreach( var greatSphere in spheres ) //sw.WriteLine( PovRay.Sphere( greatSphere.ToSphere() ) ); } /* * List<H3.Cell.Edge> startingEdges = new List<H3.Cell.Edge>(); * startingEdges.Add( new H3.Cell.Edge( cen, faceCenter ) ); * H3.Cell.Edge[] edges = Recurse.CalcEdges( simplex.Facets, startingEdges.ToArray(), new Recurse.Settings() { G = Geometry.Spherical, Threshold = 0.001 } ); * //edges = edges.Where( e => !( Infinity.IsInfinite( e.Start ) || Infinity.IsInfinite( e.End ) ) ).ToArray(); * * PovRay.WriteEdges( new PovRay.Parameters() { AngularThickness = 0.01 }, Geometry.Spherical, edges, filename, append: true ); */ double minRad = 0; double thick = 0.005; System.Func <Vector3D, Sphere> sizeFunc = v => { Vector3D c; double rad; H3Models.Ball.DupinCyclideSphere(v, thick / 2, g, out c, out rad); return(new Sphere() { Center = c, Radius = Math.Max(rad, minRad) }); }; // All geodesics List <Circle3D> startingCircles = new List <Circle3D>(); startingCircles.Add(GeodesicFrom2Points(cen, edgeMid)); Circle3D[] geodesics = CalcGeodesics(simplex.Facets, startingCircles.ToArray()); Vector3D color = new Vector3D(0, 0, 1); using (StreamWriter sw = File.CreateText(filename)) { Shapeways shapeways = new Shapeways(); foreach (Circle3D geodesic in geodesics) { Vector3D[] points; if (Infinity.IsInfinite(geodesic.Radius)) { double cutoff = 15; Segment seg = Segment.Line(geodesic.Normal * cutoff, geodesic.Normal * -cutoff); points = seg.Subdivide(42); } else { List <Vector3D> tempPoints = geodesic.Subdivide(150).ToList(); tempPoints.Add(tempPoints[0]); tempPoints.Add(tempPoints[1]); points = tempPoints.ToArray(); } List <Vector3D> ePoints = new List <Vector3D>(); List <double> eRadii = new List <double>(); foreach (Vector3D pNE in points) { Sphere sphere = sizeFunc(pNE); ePoints.Add(sphere.Center); eRadii.Add(sphere.Radius); } shapeways.AddCurve(ePoints.ToArray(), eRadii.ToArray()); sw.WriteLine(PovRay.EdgeSphereSweep(points, sizeFunc, color)); } STL.SaveMeshToSTL(shapeways.Mesh, "533.stl"); } }