private AddCurve ( List |
||
disks | List |
|
points | Vector3D | |
start | Vector3D | |
end | Vector3D | |
return | void |
/// <summary> /// Add a finite (truncated) banana to our mesh. Passed in edge should be in Ball model. /// </summary> public static void AddBanana( Shapeways mesh, Vector3D e1, Vector3D e2, H3.Settings settings ) { Vector3D e1UHS = H3Models.BallToUHS( e1 ); Vector3D e2UHS = H3Models.BallToUHS( e2 ); // Endpoints of the goedesic on the z=0 plane. Vector3D z1, z2; H3Models.UHS.GeodesicIdealEndpoints( e1UHS, e2UHS, out z1, out z2 ); // XXX - Do we want to do a better job worrying about rotation here? // (multiply by complex number with certain imaginary part as well) //Vector3D z3 = ( z1 + z2 ) / 2; //if( Infinity.IsInfinite( z3 ) ) // z3 = new Vector3D( 1, 0 ); Vector3D z3 = new Vector3D( Math.E, Math.PI ); // This should vary the rotations a bunch. // Find the Mobius we need. // We'll do this in two steps. // (1) Find a mobius taking z1,z2 to origin,inf // (2) Deal with scaling e1 to a height of 1. Mobius m1 = new Mobius( z1, z3, z2 ); Vector3D e1UHS_transformed = m1.ApplyToQuaternion( e1UHS ); double scale = 1.0 / e1UHS_transformed.Z; Mobius m2 = Mobius.Scale( scale ); Mobius m = m2 * m1; // Compose them (multiply in reverse order). Vector3D e2UHS_transformed = m.ApplyToQuaternion( e2UHS ); // Make our truncated cone. // For regular tilings, we really would only need to do this once for a given LOD. List<Vector3D> points = new List<Vector3D>(); double logHeight = Math.Log( e2UHS_transformed.Z ); if( logHeight < 0 ) throw new System.Exception( "impl issue" ); int div1, div2; H3Models.Ball.LOD_Finite( e1, e2, out div1, out div2, settings ); double increment = logHeight / div1; for( int i=0; i<=div1; i++ ) { double h = increment * i; // This is to keep different bananas from sharing exactly coincident vertices. double tinyOffset = 0.001; if( i == 0 ) h -= tinyOffset; if( i == div1 ) h += tinyOffset; Vector3D point = new Vector3D( 0, 0, Math.Exp( h ) ); points.Add( point ); } Shapeways tempMesh = new Shapeways(); tempMesh.Div = div2; tempMesh.AddCurve( points.ToArray(), v => H3Models.UHS.SizeFunc( v, settings.AngularThickness ) ); // Unwind the transforms. TakePointsBack( tempMesh.Mesh, m.Inverse(), settings ); mesh.Mesh.Triangles.AddRange( tempMesh.Mesh.Triangles ); }
/// <summary> /// Helper to project points from S3 -> S2, then add an associated curve. /// </summary> private static void ProjectAndAddS3Points(Shapeways mesh, Vector3D[] pointsS3, bool shrink) { // Project to S3, then to R3. List <Vector3D> projected = new List <Vector3D>(); foreach (Vector3D v in pointsS3) { v.Normalize(); Vector3D c = v.ProjectTo3DSafe(1.0); // Pull R3 into a smaller open disk. if (shrink) { double mag = Math.Atan(c.Abs()); c.Normalize(); c *= mag; } projected.Add(c); } System.Func <Vector3D, double> sizeFunc = v => { // Constant thickness. // return 0.08; double sphericalThickness = 0.002; double abs = v.Abs(); if (shrink) { abs = Math.Tan(abs); // The unshrunk abs. } // The thickness at this vector location. double result = Spherical2D.s2eNorm(Spherical2D.e2sNorm(abs) + sphericalThickness) - abs; if (shrink) { result *= Math.Atan(abs) / abs; // shrink it back down. } return(result); }; mesh.AddCurve(projected.ToArray(), sizeFunc); }
public static void GenPolyhedron() { Tiling tiling; int p = 3; int q = 6; GetAssociatedTiling(p, q, 5000, out tiling); double overallScale = 12.5; // 2.5 cm = 1 in diameter Shapeways mesh = new Shapeways(); foreach (Tile tile in tiling.Tiles) { foreach (Segment seg in tile.Boundary.Segments) { double tilingScale = 0.75; seg.Scale(new Vector3D(), tilingScale); Vector3D v1 = Sterographic.PlaneToSphereSafe(seg.P1); Vector3D v2 = Sterographic.PlaneToSphereSafe(seg.P2); //if( v1.Dist( v2 ) < 0.01 ) // continue; if (SphericalCoords.CartesianToSpherical(v1).Y < Math.PI / 12 && SphericalCoords.CartesianToSpherical(v2).Y < Math.PI / 12) { continue; } double dist = v1.Dist(v2); int divisions = 2 + (int)(dist * 20); Vector3D[] points = seg.Subdivide(divisions); points = points.Select(v => Sterographic.PlaneToSphereSafe(v)).ToArray(); mesh.AddCurve(points, v => SizeFunc(v, overallScale)); } } mesh.Mesh.Scale(overallScale); string outputFileName = @"d:\temp\" + p + q + ".stl"; STL.SaveMeshToSTL(mesh.Mesh, outputFileName); }
private static void ProjectAndAddS3Points(Shapeways mesh, Vector3D[] pointsS3) { double r = 0.02; List <Vector3D> projected = new List <Vector3D>(); List <double> radii = new List <double>(); foreach (Vector3D v in pointsS3) { v.Normalize(); Vector3D c = v.ProjectTo3DSafe(1.0); Vector3D p; double d; H3Models.Ball.DupinCyclideSphere(c, r, Geometry.Spherical, out p, out d); projected.Add(p); radii.Add(d); } mesh.AddCurve(projected.ToArray(), radii.ToArray()); }
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); }
/// <summary> /// Helper to project points from S3 -> S2, then add an associated curve. /// XXX - Not completely correct. /// </summary> private static void ProjectAndAddS3Points( Shapeways mesh, Vector3D[] pointsS3, bool shrink ) { List<Vector3D> projected = new List<Vector3D>(); foreach( Vector3D v in pointsS3 ) { v.Normalize(); Vector3D c = v.ProjectTo3DSafe( 1.0 ); // Pull R3 into a smaller open disk. if( shrink ) { double mag = Math.Atan( c.Abs() ); c.Normalize(); c *= mag; } projected.Add( c ); } System.Func<Vector3D, double> sizeFunc = v => { // Constant thickness. // return 0.08; double sphericalThickness = 0.05; double abs = v.Abs(); if( shrink ) abs = Math.Tan( abs ); // The unshrunk abs. // The thickness at this vector location. double result = Spherical2D.s2eNorm( Spherical2D.e2sNorm( abs ) + sphericalThickness ) - abs; if( shrink ) result *= Math.Atan( abs ) / abs; // shrink it back down. return result; }; mesh.AddCurve( projected.ToArray(), sizeFunc ); }
private static void ProjectAndAddS3Points( Shapeways mesh, Vector3D[] pointsS3 ) { double r = 0.02; List<Vector3D> projected = new List<Vector3D>(); List<double> radii = new List<double>(); foreach( Vector3D v in pointsS3 ) { v.Normalize(); Vector3D c = v.ProjectTo3DSafe( 1.0 ); Vector3D p; double d; H3Models.Ball.DupinCyclideSphere( c, r, Geometry.Spherical, out p, out d ); projected.Add( p ); radii.Add( d ); } mesh.AddCurve( projected.ToArray(), radii.ToArray() ); }
/// <summary> /// Add an ideal banana to our mesh. Passed in edge should be in Ball model. /// </summary> public static void AddIdealBanana( Shapeways mesh, Vector3D e1, Vector3D e2, H3.Settings settings ) { Vector3D z1 = H3Models.BallToUHS( e1 ); Vector3D z2 = H3Models.BallToUHS( e2 ); // Mobius taking z1,z2 to origin,inf Complex dummy = new Complex( Math.E, Math.PI ); Mobius m = new Mobius( z1, dummy, z2 ); // Make our truncated cone. We need to deal with the two ideal endpoints specially. List<Vector3D> points = new List<Vector3D>(); double logHeight = 2; // XXX - magic number, and going to cause problems for infinity checks if too big. int div1, div2; H3Models.Ball.LOD_Ideal( e1, e2, out div1, out div2, settings ); double increment = logHeight / div1; for( int i=-div1; i<=div1; i+=2 ) points.Add( new Vector3D( 0, 0, Math.Exp( increment * i ) ) ); Shapeways tempMesh = new Shapeways(); tempMesh.Div = div2; System.Func<Vector3D, double> sizeFunc = v => H3Models.UHS.SizeFunc( v, settings.AngularThickness ); //Mesh.OpenCylinder... pass in two ideal endpoints? tempMesh.AddCurve( points.ToArray(), sizeFunc, new Vector3D(), Infinity.InfinityVector ); // Unwind the transforms. TakePointsBack( tempMesh.Mesh, m.Inverse(), settings ); mesh.Mesh.Triangles.AddRange( tempMesh.Mesh.Triangles ); }