public void GetPerimetersForAllLayers(Mesh meshToSlice, double firstLayerHeight, double otherLayerHeights) { AllLayers.Clear(); AxisAlignedBoundingBox meshBounds = meshToSlice.GetAxisAlignedBoundingBox(); double heightWithoutFirstLayer = meshBounds.ZSize - firstLayerHeight; int layerCount = (int)((heightWithoutFirstLayer / otherLayerHeights) + .5); double currentZ = otherLayerHeights; if (firstLayerHeight > 0) { layerCount++; currentZ = firstLayerHeight; } for (int i = 0; i < layerCount; i++) { allLayers.Add(new SliceLayer(currentZ)); currentZ += otherLayerHeights; } foreach (Face face in meshToSlice.Faces) { double minZ = double.MaxValue; double maxZ = double.MinValue; foreach (FaceEdge faceEdge in face.FaceEdges()) { minZ = Math.Min(minZ, faceEdge.firstVertex.Position.z); maxZ = Math.Max(maxZ, faceEdge.firstVertex.Position.z); } for (int layerIndex = 0; layerIndex < layerCount; layerIndex++) { SliceLayer layer = allLayers[layerIndex]; double zHeight = layer.ZHeight; if (zHeight < minZ) { // not up to the start of the face yet continue; } if (zHeight > maxZ) { // done with this face break; } Plane cutPlane = new Plane(Vector3.UnitZ, zHeight); Vector3 start; Vector3 end; if (face.GetCutLine(cutPlane, out start, out end)) { layer.UnorderedSegments.Add(new SliceLayer.Segment(new Vector2(start.x, start.y), new Vector2(end.x, end.y))); } } } }
public UpArrow3D(View3DWidget view3DWidget) : base(null, view3DWidget.meshViewerWidget) { this.view3DWidget = view3DWidget; string arrowFile = Path.Combine("Icons", "3D Icons", "up_pointer.stl"); if (StaticData.Instance.FileExists(arrowFile)) { using (Stream staticDataStream = StaticData.Instance.OpenSteam(arrowFile)) { using (MemoryStream arrowStream = new MemoryStream()) { staticDataStream.CopyTo(arrowStream, 1 << 16); List<MeshGroup> loadedMeshGroups = MeshFileIo.Load(arrowStream, Path.GetExtension(arrowFile)); upArrow = loadedMeshGroups[0].Meshes[0]; CollisionVolume = PlatingHelper.CreateTraceDataForMesh(upArrow); AxisAlignedBoundingBox arrowBounds = upArrow.GetAxisAlignedBoundingBox(); //CollisionVolume = new CylinderShape(arrowBounds.XSize / 2, arrowBounds.ZSize, new SolidMaterial(RGBA_Floats.Red, .5, 0, .4)); //CollisionVolume = new CylinderShape(arrowBounds.XSize / 2 * 4, arrowBounds.ZSize * 4, new SolidMaterial(RGBA_Floats.Red, .5, 0, .4)); } } } }
public static Mesh[] SplitIntoMeshesOnOrthographicZ(Mesh meshToSplit, Vector3 buildVolume, ReportProgressRatio reportProgress) { // 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); bool continueProcessin = true; if (reportProgress != null) { reportProgress(.2, "", out continueProcessin); } //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 (reportProgress != null) { reportProgress(.5, "", out continueProcessin); } //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 (reportProgress != null) { reportProgress(.8, "", out continueProcessin); } for (int i = 0; i < discreteMeshes.Count(); i++) { Mesh mesh = discreteMeshes[i]; } return discreteMeshes; }
public void GetMinMaxZ(Mesh mesh, ref double minZ, ref double maxZ) { AxisAlignedBoundingBox meshBounds = mesh.GetAxisAlignedBoundingBox(trackballTumbleWidget.ModelviewMatrix); minZ = Math.Min(meshBounds.minXYZ.z, minZ); maxZ = Math.Max(meshBounds.maxXYZ.z, maxZ); }
private static ImageBuffer BuildImageFromSTL(Mesh loadedMesh, string stlHashCode, Point2D size) { if(loadedMesh != null) { ImageBuffer tempImage = new ImageBuffer(size.x, size.y, 32, new BlenderBGRA()); Graphics2D partGraphics2D = tempImage.NewGraphics2D(); partGraphics2D.Clear(new RGBA_Bytes()); AxisAlignedBoundingBox aabb = loadedMesh.GetAxisAlignedBoundingBox(); double maxSize = Math.Max(aabb.XSize, aabb.YSize); double scale = size.x / (maxSize * 1.2); RectangleDouble bounds2D = new RectangleDouble(aabb.minXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.x, aabb.maxXYZ.y); PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partGraphics2D, loadedMesh, new Vector2((size.x / scale - bounds2D.Width) / 2 - bounds2D.Left, (size.y / scale - bounds2D.Height) / 2 - bounds2D.Bottom), scale, RGBA_Bytes.White); List<MeshEdge> nonManifoldEdges = loadedMesh.GetNonManifoldEdges(); if (nonManifoldEdges.Count > 0) { if (File.Exists("RunUnitTests.txt")) { partGraphics2D.Circle(size.x / 4, size.x / 4, size.x / 8, RGBA_Bytes.Red); } } // and save it to disk string applicationUserDataPath = ApplicationDataStorage.Instance.ApplicationUserDataPath; string folderToSavePrintsTo = Path.Combine(applicationUserDataPath, "data", "temp", "thumbnails"); string tgaFileName = Path.Combine(folderToSavePrintsTo, "{0}_{1}x{2}.tga".FormatWith(stlHashCode, size.x, size.y)); if (!Directory.Exists(folderToSavePrintsTo)) { Directory.CreateDirectory(folderToSavePrintsTo); } ImageTgaIO.SaveImageData(tgaFileName, tempImage); // and give it back return tempImage; } return null; }