예제 #1
0
		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)));
					}
				}
			}
		}
예제 #2
0
		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;
		}
예제 #4
0
		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;
        }