/// <summary> /// Create the Polygonal Faces for a new Tessellated Solid by extruding the given loop along the given normal. /// </summary> /// <param name="loops"></param> /// <param name="extrudeDirection"></param> /// <param name="extrusionHeight"></param> /// <param name="midPlane"></param> /// <returns></returns> public static List <PolygonalFace> ExtrusionFacesFrom3DLoops(this IEnumerable <IEnumerable <Vector3> > loops, Vector3 extrudeDirection, double extrusionHeight, bool midPlane = false) { // for consistency with adding the extrusionHeight to the base plane, negate if it comes in negative if (extrusionHeight < 0) { extrusionHeight = -extrusionHeight; extrudeDirection = -1 * extrudeDirection; } // find transform to the XY plane and store the backTransform (the transform back to the original) var transform = MiscFunctions.TransformToXYPlane(extrudeDirection, out var backTransform); // make paths, the 2D polygons represening the 3D loops var paths = loops.Select(loop => loop.ProjectTo2DCoordinates(transform, 0, true)); // the basePlaneDistance defines the plane closer to the origin. we can get this from the any input coordinate var basePlaneDistance = extrudeDirection.Dot(loops.First().First()); if (midPlane) { basePlaneDistance -= extrusionHeight / 2.0; } var polygons = paths.CreateShallowPolygonTrees(false); return(polygons.SelectMany(polygon => Extrude.ExtrusionFacesFrom2DPolygons(polygon, extrudeDirection, basePlaneDistance, extrusionHeight)).ToList()); }
/// <summary> /// Create the triangular faces of an extruded solid from 2D paths. /// </summary> /// <param name="paths">The paths.</param> /// <param name="basePlaneNormal">The base plane normal.</param> /// <param name="basePlaneDistance">The base plane distance.</param> /// <param name="extrusionHeight">Height of the extrusion.</param> /// <returns>List<PolygonalFace>.</returns> public static List <PolygonalFace> ExtrusionFacesFrom2DPolygons(this IEnumerable <IEnumerable <Vector2> > paths, Vector3 basePlaneNormal, double basePlaneDistance, double extrusionHeight) { var polygons = paths.CreateShallowPolygonTrees(false); return(polygons.SelectMany(polygon => Extrude.ExtrusionFacesFrom2DPolygons(polygon, basePlaneNormal, basePlaneDistance, extrusionHeight)).ToList()); }
/// <summary> /// Sets the Solid Representation of the bounding box /// </summary> public void SetSolidRepresentation() { if (CornerVertices == null || !CornerVertices.Any()) { SetCornerVertices(); } SolidRepresentation = Extrude.FromLoops(new List <List <Vertex> >() { CornerVertices.Take(4).ToList() }, Directions[2], Dimensions[2]); }
//public void SetVolume() //{ // Volume = 0.0; // for (var i = 0; i < NumLayers - 1; i++) //Include the last index, since we already modified start or stop // { // if (Layer2D[i] == null || !Layer2D[i].Any() || Layer2D[i + 1] == null || !Layer2D[i + 1].Any()) continue; // var halfThickness = 0.5 * (StepDistances[i + 1] - StepDistances[i]); // Volume += halfThickness * (Layer2D[i].Sum(p => p.Area) + Layer2D[i].Sum(p => p.Area)); // } //} /// <summary> /// Layer2D and 3D can be indexed in the forward or reverse order from the step distances. /// This can be useful when working in a bi-directional scope. In both cases, it will start /// by extruding the first valid loop in Layer3D and stop before extruding the last one (the /// n-1 extrusion will have ended on at the distance of the final cross section). /// If reversed, it will simply extrude backward instead of forward. /// </summary> public IReadOnlyCollection <PolygonalFace> ConvertToTessellatedExtrusions(bool extrudeBack = true) { if (!Layer3D.Any()) { SetAllVertices(); } var start = Layer3D.Where(p => p.Value.Any()).FirstOrDefault().Key; var stop = Layer3D.Where(p => p.Value.Any()).LastOrDefault().Key; var reverse = start < stop ? 1 : -1; var direction = reverse == 1 ? Direction : Direction.multiply(-1); var faces = new List <PolygonalFace>(); //If extruding back, then we skip the first loop, and extrude backward from the remaining loops. //Otherwise, extrude the first loop and all other loops forward, except the last loop. //Which of these extrusion options you choose depends on how the cross sections were defined. //But both methods, only result in material between the cross sections. if (extrudeBack) { direction = direction.multiply(-1); start += reverse; } else { stop -= reverse; } for (var i = start; i *reverse <= stop *reverse; i += reverse) //Include the last index, since we already modified start or stop { if (!Layer3D[i].Any()) { continue; //THere can be gaps in layer3D if this actually represents more than one solid body } double distance; if (extrudeBack) { distance = Math.Abs(StepDistances[i] - StepDistances[i - reverse]); //current - prior (reverse extrusion) } else { distance = Math.Abs(StepDistances[i + reverse] - StepDistances[i]); //next - current (forward extrusion) } var layerfaces = Extrude.ReturnFacesFromLoops(Layer3D[i], direction, distance, false); if (layerfaces == null) { continue; } faces.AddRange(layerfaces); } return(faces); }