public static Solid Sphere(SphereOptions options) { var center = options.Center; var radius = Math.Abs(options.Radius); if (radius == 0.0) { return(new Solid()); } var resolution = options.Resolution; var xvector = options.XAxis * radius; var yvector = options.YAxis * radius; var zvector = options.ZAxis * radius; if (resolution < 4) { resolution = 4; } var qresolution = resolution / 4; var prevcylinderpoint = new Vector3D(0, 0, 0); var polygons = new List <Polygon>(); for (var slice1 = 0; slice1 <= resolution; slice1++) { var angle = Math.PI * 2.0 * slice1 / resolution; var cylinderpoint = xvector * (Math.Cos(angle)) + (yvector * (Math.Sin(angle))); if (slice1 > 0) { double prevcospitch = 0, prevsinpitch = 0; for (var slice2 = 0; slice2 <= qresolution; slice2++) { var pitch = 0.5 * Math.PI * (double)slice2 / qresolution; var cospitch = Math.Cos(pitch); var sinpitch = Math.Sin(pitch); if (slice2 > 0) { var vertices = new List <Vertex>(); vertices.Add(new Vertex(center + (prevcylinderpoint * (prevcospitch) - (zvector * (prevsinpitch))))); vertices.Add(new Vertex(center + (cylinderpoint * (prevcospitch) - (zvector * (prevsinpitch))))); if (slice2 < qresolution) { vertices.Add(new Vertex(center + (cylinderpoint * (cospitch) - (zvector * (sinpitch))))); } vertices.Add(new Vertex(center + (prevcylinderpoint * (cospitch) - (zvector * (sinpitch))))); polygons.Add(new Polygon(vertices, -1)); vertices = new List <Vertex>(); vertices.Add(new Vertex(center + (prevcylinderpoint * (prevcospitch) + (zvector * (prevsinpitch))))); vertices.Add(new Vertex(center + (cylinderpoint * (prevcospitch) + (zvector * (prevsinpitch))))); if (slice2 < qresolution) { vertices.Add(new Vertex(center + (cylinderpoint * (cospitch) + (zvector * (sinpitch))))); } vertices.Add(new Vertex(center + (prevcylinderpoint * (cospitch) + (zvector * (sinpitch))))); vertices.Reverse(); polygons.Add(new Polygon(vertices, -1)); } prevcospitch = cospitch; prevsinpitch = sinpitch; } } prevcylinderpoint = cylinderpoint; } var result = Solid.FromPolygons(polygons); return(result); }
public static Solid Cylinder(CylinderOptions options) { var s = options.Start; var e = options.End; var r = Math.Abs(options.RadiusStart); var rEnd = Math.Abs(options.RadiusEnd); var rStart = r; var alpha = options.SectorAngle; alpha = alpha > 360 ? alpha % 360 : alpha; if ((rEnd == 0) && (rStart == 0)) { return(new Solid()); } if (s.Equals(e)) { return(new Solid()); } var slices = options.Resolution; var ray = e - (s); var axisZ = ray.Unit; var axisX = axisZ.RandomNonParallelVector().Unit; var axisY = axisX.Cross(axisZ).Unit; axisX = axisZ.Cross(axisY).Unit; var start = new Vertex(s); var end = new Vertex(e); var polygons = new List <Polygon>(); Func <double, double, double, Vertex> point = (stack, slice, radius) => { var angle = slice * Math.PI * alpha / 180; var outp = axisX * (Math.Cos(angle)) + (axisY * (Math.Sin(angle))); var pos = s + (ray * (stack)) + (outp * (radius)); return(new Vertex(pos)); }; if (alpha > 0) { for (var i = 0; i < slices; i++) { double t0 = (double)i / slices; double t1 = (double)(i + 1) / slices; if (rEnd == rStart) { polygons.Add(new Polygon(start, point(0, t0, rEnd), point(0, t1, rEnd))); polygons.Add(new Polygon(point(0, t1, rEnd), point(0, t0, rEnd), point(1, t0, rEnd), point(1, t1, rEnd))); polygons.Add(new Polygon(end, point(1, t1, rEnd), point(1, t0, rEnd))); } else { if (rStart > 0) { polygons.Add(new Polygon(start, point(0, t0, rStart), point(0, t1, rStart))); polygons.Add(new Polygon(point(0, t0, rStart), point(1, t0, rEnd), point(0, t1, rStart))); } if (rEnd > 0) { polygons.Add(new Polygon(end, point(1, t1, rEnd), point(1, t0, rEnd))); polygons.Add(new Polygon(point(1, t0, rEnd), point(1, t1, rEnd), point(0, t1, rStart))); } } } if (alpha < 360) { polygons.Add(new Polygon(start, end, point(0, 0, rStart))); polygons.Add(new Polygon(point(0, 0, rStart), end, point(1, 0, rEnd))); polygons.Add(new Polygon(start, point(0, 1, rStart), end)); polygons.Add(new Polygon(point(0, 1, rStart), point(1, 1, rEnd), end)); } } var result = Solid.FromPolygons(polygons); return(result); }