public static void ArrangeOnBed(List <IObject3D> object3DList, Vector3 bedCenter) { if (object3DList.Count == 0) { return; } // move them all out of the way for (int i = 0; i < object3DList.Count; i++) { object3DList[i].Matrix *= Matrix4X4.CreateTranslation(10000, 10000, 0); } // sort them by size object3DList.Sort(SortOnSize); double ratioPerMeshGroup = 1.0 / object3DList.Count; double currentRatioDone = 0; // put them onto the plate (try the center) starting with the biggest and moving down for (int meshGroupIndex = 0; meshGroupIndex < object3DList.Count; meshGroupIndex++) { var object3D = object3DList[meshGroupIndex]; Vector3 meshLowerLeft = object3D.GetAxisAlignedBoundingBox().MinXYZ; object3D.Matrix *= Matrix4X4.CreateTranslation(-meshLowerLeft); PlatingHelper.MoveToOpenPositionRelativeGroup(object3D, object3DList); currentRatioDone += ratioPerMeshGroup; // and put it on the bed PlatingHelper.PlaceOnBed(object3D); } // and finally center whatever we have as a group { AxisAlignedBoundingBox bounds = object3DList[0].GetAxisAlignedBoundingBox(); for (int i = 1; i < object3DList.Count; i++) { bounds = AxisAlignedBoundingBox.Union(bounds, object3DList[i].GetAxisAlignedBoundingBox()); } Vector3 boundsCenter = (bounds.MaxXYZ + bounds.MinXYZ) / 2; for (int i = 0; i < object3DList.Count; i++) { object3DList[i].Matrix *= Matrix4X4.CreateTranslation(-boundsCenter + new Vector3(0, 0, bounds.ZSize / 2) + bedCenter); } } }
public static Mesh[] SplitIntoMeshes(Mesh meshToSplit, Vector3 buildVolume, BackgroundWorker backgroundWorker, int startPercent, int endPercent) { int lengthPercent = endPercent - startPercent; // check if the part is bigger than the build plate (if it is we need to use that as our size) AxisAlignedBoundingBox partBounds = meshToSplit.GetAxisAlignedBoundingBox(); buildVolume.x = Math.Max(buildVolume.x, partBounds.XSize + 2); buildVolume.y = Math.Max(buildVolume.y, partBounds.YSize + 2); buildVolume.z = Math.Max(buildVolume.z, partBounds.ZSize + 2); // Find all the separate objects that are on the plate // Create a 2D image the size of the printer bed at some scale with the parts draw on it top down double scaleFactor = 5; ImageBuffer partPlate = new ImageBuffer((int)(buildVolume.x * scaleFactor), (int)(buildVolume.y * scaleFactor), 32, new BlenderBGRA()); Vector2 renderOffset = new Vector2(buildVolume.x / 2, buildVolume.y / 2) - new Vector2(partBounds.Center.x, partBounds.Center.y); PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partPlate.NewGraphics2D(), meshToSplit, renderOffset, scaleFactor, RGBA_Bytes.White); if (backgroundWorker != null) { backgroundWorker.ReportProgress(startPercent + (int)(lengthPercent * .2)); } //ImageIO.SaveImageData("test part plate 0.png", partPlate); // expand the bounds a bit so that we can collect all the vertices and polygons within each bound Dilate.DoDilate3x3Binary(partPlate, 1); //ImageIO.SaveImageData("test part plate 1.png", partPlate); // trace all the bounds of the objects on the plate PolyTree polyTreeForPlate = FindDistictObjectBounds(partPlate); if (polyTreeForPlate == null) { Mesh[] singleMesh = new Mesh[1]; singleMesh[0] = meshToSplit; return(singleMesh); } // get all the discrete areas that are polygons so we can search them Polygons discreteAreas = new Polygons(); GetAreasRecursive(polyTreeForPlate, discreteAreas); if (discreteAreas.Count == 0) { return(null); } else if (discreteAreas.Count == 1) { Mesh[] singleMesh = new Mesh[1]; singleMesh[0] = meshToSplit; return(singleMesh); } Graphics2D graphics2D = partPlate.NewGraphics2D(); graphics2D.Clear(RGBA_Bytes.Black); Random rand = new Random(); foreach (Polygon polygon in discreteAreas) { graphics2D.Render(PlatingHelper.PolygonToPathStorage(polygon), new RGBA_Bytes(rand.Next(128, 255), rand.Next(128, 255), rand.Next(128, 255))); } if (backgroundWorker != null) { backgroundWorker.ReportProgress(startPercent + (int)(lengthPercent * .50)); } //ImageIO.SaveImageData("test part plate 2.png", partPlate); // add each of the separate bounds polygons to new meshes Mesh[] discreteMeshes = new Mesh[discreteAreas.Count]; for (int i = 0; i < discreteAreas.Count; i++) { discreteMeshes[i] = new Mesh(); } foreach (Face face in meshToSplit.Faces) { bool faceDone = false; // figure out which area one or more of the vertices are in add the face to the right new mesh foreach (FaceEdge faceEdge in face.FaceEdges()) { Vector2 position = new Vector2(faceEdge.firstVertex.Position.x, faceEdge.firstVertex.Position.y); position += renderOffset; position *= scaleFactor; for (int areaIndex = discreteAreas.Count - 1; areaIndex >= 0; areaIndex--) { if (PointInPolygon(discreteAreas[areaIndex], new IntPoint((int)position.x, (int)position.y))) { List <Vertex> faceVertices = new List <Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { Vertex newVertex = discreteMeshes[areaIndex].CreateVertex(faceEdgeToAdd.firstVertex.Position); faceVertices.Add(newVertex); } discreteMeshes[areaIndex].CreateFace(faceVertices.ToArray()); faceDone = true; break; } } if (faceDone) { break; } } } if (backgroundWorker != null) { backgroundWorker.ReportProgress(startPercent + (int)(lengthPercent)); } for (int i = 0; i < discreteMeshes.Count(); i++) { Mesh mesh = discreteMeshes[i]; } return(discreteMeshes); }
public static void ArrangeMeshGroups(List <MeshGroup> asyncMeshGroups, List <ScaleRotateTranslate> asyncMeshGroupTransforms, List <PlatingMeshGroupData> asyncPlatingDatas, Action <double, string> reportProgressChanged) { // move them all out of the way for (int i = 0; i < asyncMeshGroups.Count; i++) { ScaleRotateTranslate translate = asyncMeshGroupTransforms[i]; translate.translation *= Matrix4X4.CreateTranslation(10000, 10000, 0); asyncMeshGroupTransforms[i] = translate; } // sort them by size for (int i = 0; i < asyncMeshGroups.Count; i++) { AxisAlignedBoundingBox iAABB = asyncMeshGroups[i].GetAxisAlignedBoundingBox(asyncMeshGroupTransforms[i].TotalTransform); for (int j = i + 1; j < asyncMeshGroups.Count; j++) { AxisAlignedBoundingBox jAABB = asyncMeshGroups[j].GetAxisAlignedBoundingBox(asyncMeshGroupTransforms[j].TotalTransform); if (Math.Max(iAABB.XSize, iAABB.YSize) < Math.Max(jAABB.XSize, jAABB.YSize)) { PlatingMeshGroupData tempData = asyncPlatingDatas[i]; asyncPlatingDatas[i] = asyncPlatingDatas[j]; asyncPlatingDatas[j] = tempData; MeshGroup tempMeshGroup = asyncMeshGroups[i]; asyncMeshGroups[i] = asyncMeshGroups[j]; asyncMeshGroups[j] = tempMeshGroup; ScaleRotateTranslate iTransform = asyncMeshGroupTransforms[i]; ScaleRotateTranslate jTransform = asyncMeshGroupTransforms[j]; Matrix4X4 tempTransform = iTransform.translation; iTransform.translation = jTransform.translation; jTransform.translation = tempTransform; asyncMeshGroupTransforms[i] = jTransform; asyncMeshGroupTransforms[j] = iTransform; iAABB = jAABB; } } } double ratioPerMeshGroup = 1.0 / asyncMeshGroups.Count; double currentRatioDone = 0; // put them onto the plate (try the center) starting with the biggest and moving down for (int meshGroupIndex = 0; meshGroupIndex < asyncMeshGroups.Count; meshGroupIndex++) { reportProgressChanged(currentRatioDone, "Calculating Positions...".Localize()); MeshGroup meshGroup = asyncMeshGroups[meshGroupIndex]; Vector3 meshLowerLeft = meshGroup.GetAxisAlignedBoundingBox(asyncMeshGroupTransforms[meshGroupIndex].TotalTransform).minXYZ; ScaleRotateTranslate atZero = asyncMeshGroupTransforms[meshGroupIndex]; atZero.translation *= Matrix4X4.CreateTranslation(-meshLowerLeft); asyncMeshGroupTransforms[meshGroupIndex] = atZero; PlatingHelper.MoveMeshGroupToOpenPosition(meshGroupIndex, asyncPlatingDatas, asyncMeshGroups, asyncMeshGroupTransforms); // and create the trace info so we can select it if (asyncPlatingDatas[meshGroupIndex].meshTraceableData.Count == 0) { PlatingHelper.CreateITraceableForMeshGroup(asyncPlatingDatas, asyncMeshGroups, meshGroupIndex, null); } currentRatioDone += ratioPerMeshGroup; // and put it on the bed PlatingHelper.PlaceMeshGroupOnBed(asyncMeshGroups, asyncMeshGroupTransforms, meshGroupIndex); } // and finally center whatever we have as a group { AxisAlignedBoundingBox bounds = asyncMeshGroups[0].GetAxisAlignedBoundingBox(asyncMeshGroupTransforms[0].TotalTransform); for (int i = 1; i < asyncMeshGroups.Count; i++) { bounds = AxisAlignedBoundingBox.Union(bounds, asyncMeshGroups[i].GetAxisAlignedBoundingBox(asyncMeshGroupTransforms[i].TotalTransform)); } Vector3 boundsCenter = (bounds.maxXYZ + bounds.minXYZ) / 2; for (int i = 0; i < asyncMeshGroups.Count; i++) { ScaleRotateTranslate translate = asyncMeshGroupTransforms[i]; translate.translation *= Matrix4X4.CreateTranslation(-boundsCenter + new Vector3(0, 0, bounds.ZSize / 2)); asyncMeshGroupTransforms[i] = translate; } } }