public static void EdgesToStl(H3.Cell.Edge[] edges) { Shapeways mesh = new Shapeways(); int divisions = 25; foreach (H3.Cell.Edge edge in edges) { Segment seg = Segment.Line( Sterographic.R3toS3(edge.Start), Sterographic.R3toS3(edge.End)); Vector3D[] points = seg.Subdivide(divisions); ProjectAndAddS3Points(mesh, points); } for (int i = 0; i < mesh.Mesh.Triangles.Count; i++) { mesh.Mesh.Triangles[i] = new Mesh.Triangle( SphericalModels.StereoToEqualVolume(mesh.Mesh.Triangles[i].a), SphericalModels.StereoToEqualVolume(mesh.Mesh.Triangles[i].b), SphericalModels.StereoToEqualVolume(mesh.Mesh.Triangles[i].c)); } STL.SaveMeshToSTL(mesh.Mesh, @"output.stl"); }
// Maps unit disk to Boy's surface. public static Vector3D MapToBoys(Vector3D v) { // https://en.wikipedia.org/wiki/Boy%27s_surface#Parametrization_of_Boy.27s_surface Complex w = v.ToComplex(); Complex t0 = (Complex.Pow(w, 6) + Complex.Pow(w, 3) * Math.Sqrt(5) - 1); Complex t1 = w * (1 - Complex.Pow(w, 4)) / t0; Complex t2 = w * (1 + Complex.Pow(w, 4)) / t0; Complex t3 = (1 + Complex.Pow(w, 6)) / t0; double g1 = -3 / 2 * t1.Imaginary; double g2 = -3 / 2 * t2.Real; double g3 = t3.Imaginary - 0.5; double denom = g1 * g1 + g2 * g2 + g3 * g3; v = new Vector3D(g1, g2, g3); v /= denom; // The above is actually a map to R^3, but we want a surface in S^3 return(Sterographic.R3toS3(v)); }
/// <summary> /// Inputs and Outputs are in R3 (stereographically projected). /// </summary> public static Vector3D[] GeodesicPoints(Vector3D v1, Vector3D v2) { Vector3D start = Sterographic.R3toS3(v1); Vector3D end = Sterographic.R3toS3(v2); AvoidNorthPole(ref start, end); AvoidNorthPole(ref end, start); int div = 42; //int div = 56; // 343 //int div = 50; // 333 Segment seg = Segment.Line(start, end); Vector3D[] result = seg.Subdivide(div); for (int i = 0; i < result.Length; i++) { result[i].Normalize(); result[i] = Sterographic.S3toR3(result[i]); } return(result); }