private static void ShapewaysPolytopes() { VEF loader = new VEF(); loader.Load(@"C:\Users\roice\Documents\projects\vZome\VefProjector\data\24cell-cellFirst.vef"); int divisions = 25; Shapeways mesh = new Shapeways(); //int count = 0; foreach (GraphEdge edge in loader.Edges) { Segment seg = Segment.Line( loader.Vertices[edge.V1].ConvertToReal(), loader.Vertices[edge.V2].ConvertToReal()); Vector3D[] points = seg.Subdivide(divisions); bool shrink = true; ProjectAndAddS3Points(mesh, points, shrink); //if( count++ > 10 ) // break; } STL.SaveMeshToSTL(mesh.Mesh, @"D:\p4\R3\sample\out1.stl"); }
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"); }
public static Polygon Heart() { Polygon newPoly = new Polygon(); double size = 0.12; double angle = -3 * Math.PI / 2; Vector3D p1 = new Vector3D(0, -1.5 * size); Vector3D p2 = new Vector3D(-size, 0); Vector3D p3 = new Vector3D(-size / 2, size); Vector3D p4 = new Vector3D(0, size / 2); Vector3D p5 = new Vector3D(size / 2, size); Vector3D p6 = new Vector3D(size, 0); p1.RotateXY(angle); p2.RotateXY(angle); p3.RotateXY(angle); p4.RotateXY(angle); p5.RotateXY(angle); p6.RotateXY(angle); newPoly.Segments.Add(Segment.Line(p1, p2)); newPoly.Segments.Add(Segment.Arc(p2, p3, p4)); newPoly.Segments.Add(Segment.Arc(p4, p5, p6)); newPoly.Segments.Add(Segment.Line(p6, p1)); return(newPoly); }
/// <summary> /// Slicing function used for earthquake puzzles. /// c should be geodesic (orthogonal to the disk boundary). /// </summary> public static void SlicePolygonWithHyperbolicGeodesic(Polygon p, CircleNE c, double thickness, out List <Polygon> output) { Geometry g = Geometry.Hyperbolic; Segment seg = null; if (c.IsLine) { Vector3D p1, p2; Euclidean2D.IntersectionLineCircle(c.P1, c.P2, new Circle(), out p1, out p2); seg = Segment.Line(p1, p2); } else { // Setup the two slicing circles. // These are cuts equidistant from the passed in geodesic. Vector3D closestToOrigin = H3Models.Ball.ClosestToOrigin(new Circle3D() { Center = c.Center, Radius = c.Radius, Normal = new Vector3D(0, 0, 1) }); Vector3D p1, p2; Euclidean2D.IntersectionCircleCircle(c, new Circle(), out p1, out p2); seg = Segment.Arc(p1, closestToOrigin, p2); } Circle c1 = H3Models.Ball.EquidistantOffset(g, seg, thickness / 2); Circle c2 = H3Models.Ball.EquidistantOffset(g, seg, -thickness / 2); CircleNE c1NE = c.Clone(), c2NE = c.Clone(); c1NE.Center = c1.Center; c2NE.Center = c2.Center; c1NE.Radius = c1.Radius; c2NE.Radius = c2.Radius; SlicePolygonHelper(p, c1NE, c2NE, out output); }
public static Vector3D[] GeodesicPoints(Vector3D v1, Vector3D v2) { int div = 4; Segment seg = Segment.Line(v1, v2); Vector3D[] result = seg.Subdivide(div); return(result); }
/// <summary> /// Create a new polygon from a set of points. /// Line segments will be used. /// </summary> public static Polygon FromPoints(Vector3D[] points) { Polygon result = new Polygon(); for (int i = 0; i < points.Length; i++) { int idx1 = i; int idx2 = i == points.Length - 1 ? 0 : i + 1; Segment newSeg = Segment.Line(points[idx1], points[idx2]); result.Segments.Add(newSeg); } result.Center = result.CentroidApprox; return(result); }
/// <summary> /// Create a Euclidean polygon from a set of points. /// NOTE: Do not include starting point twice. /// </summary> public void CreateEuclidean(Vector3D[] points) { this.Segments.Clear(); for (int i = 0; i < points.Length; i++) { int idx1 = i; int idx2 = i + 1; if (idx2 == points.Length) { idx2 = 0; } Segment newSeg = Segment.Line(points[idx1], points[idx2]); this.Segments.Add(newSeg); } Center = this.CentroidApprox; }
/// <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); }
private static void AddEuclideanEdge(Shapeways mesh, HashSet <H3.Cell.Edge> completed, Vector3D start, Vector3D end) { H3.Cell.Edge edge = new H3.Cell.Edge(start, end); if (completed.Contains(edge)) { return; } Shapeways tempMesh = new Shapeways(); Segment seg = Segment.Line(start, end); int div = 20 - (int)(start.Abs() * 4); if (div < 1) { div = 1; } tempMesh.AddCurve(seg.Subdivide(div), .05); Transform(tempMesh.Mesh); mesh.Mesh.Triangles.AddRange(tempMesh.Mesh.Triangles); completed.Add(edge); }
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); } } }