Ejemplo n.º 1
0
        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);
                }
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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;
                }
            }
        }