예제 #1
0
        public OptimizedMesh(SimpleMesh simpleMesh, OptimizedMeshCollection containingCollection)
        {
            this.containingCollection = containingCollection;
            vertices.Capacity         = simpleMesh.faceTriangles.Count * 3;
            facesTriangle.Capacity    = simpleMesh.faceTriangles.Count;

            Dictionary <int, List <int> > indexMap = new Dictionary <int, List <int> >();

            Stopwatch t = new Stopwatch();

            t.Start();
            for (int faceIndex = 0; faceIndex < simpleMesh.faceTriangles.Count; faceIndex++)
            {
                if (MatterSlice.Canceled)
                {
                    return;
                }
                OptimizedFace optimizedFace = new OptimizedFace();
                if ((faceIndex % 1000 == 0) && t.Elapsed.TotalSeconds > 2)
                {
                    LogOutput.logProgress("optimized", faceIndex + 1, simpleMesh.faceTriangles.Count);
                }
                for (int vertexIndex = 0; vertexIndex < 3; vertexIndex++)
                {
                    IntPoint p    = simpleMesh.faceTriangles[faceIndex].vertices[vertexIndex];
                    int      hash = (int)(((p.X + MELD_DIST / 2) / MELD_DIST) ^ (((p.Y + MELD_DIST / 2) / MELD_DIST) << 10) ^ (((p.Z + MELD_DIST / 2) / MELD_DIST) << 20));
                    int      idx  = 0;
                    bool     add  = true;
                    if (indexMap.ContainsKey(hash))
                    {
                        for (int n = 0; n < indexMap[hash].Count; n++)
                        {
                            if ((vertices[indexMap[hash][n]].position - p).Length() < MELD_DIST)
                            {
                                idx = indexMap[hash][n];
                                add = false;
                                break;
                            }
                        }
                    }
                    if (add)
                    {
                        if (!indexMap.ContainsKey(hash))
                        {
                            indexMap.Add(hash, new List <int>());
                        }
                        indexMap[hash].Add(vertices.Count);
                        idx = vertices.Count;
                        vertices.Add(new OptimizedPoint3(p));
                    }
                    optimizedFace.vertexIndex[vertexIndex] = idx;
                }
                if (optimizedFace.vertexIndex[0] != optimizedFace.vertexIndex[1] && optimizedFace.vertexIndex[0] != optimizedFace.vertexIndex[2] && optimizedFace.vertexIndex[1] != optimizedFace.vertexIndex[2])
                {
                    //Check if there is a face with the same points
                    bool duplicate = false;
                    for (int _idx0 = 0; _idx0 < vertices[optimizedFace.vertexIndex[0]].usedByFacesList.Count; _idx0++)
                    {
                        for (int _idx1 = 0; _idx1 < vertices[optimizedFace.vertexIndex[1]].usedByFacesList.Count; _idx1++)
                        {
                            for (int _idx2 = 0; _idx2 < vertices[optimizedFace.vertexIndex[2]].usedByFacesList.Count; _idx2++)
                            {
                                if (vertices[optimizedFace.vertexIndex[0]].usedByFacesList[_idx0] == vertices[optimizedFace.vertexIndex[1]].usedByFacesList[_idx1] && vertices[optimizedFace.vertexIndex[0]].usedByFacesList[_idx0] == vertices[optimizedFace.vertexIndex[2]].usedByFacesList[_idx2])
                                {
                                    duplicate = true;
                                }
                            }
                        }
                    }
                    if (!duplicate)
                    {
                        vertices[optimizedFace.vertexIndex[0]].usedByFacesList.Add(facesTriangle.Count);
                        vertices[optimizedFace.vertexIndex[1]].usedByFacesList.Add(facesTriangle.Count);
                        vertices[optimizedFace.vertexIndex[2]].usedByFacesList.Add(facesTriangle.Count);
                        facesTriangle.Add(optimizedFace);
                    }
                }
            }
            //fprintf(stdout, "\rAll faces are optimized in %5.1fs.\n",timeElapsed(t));

            int openFacesCount = 0;

            for (int faceIndex = 0; faceIndex < facesTriangle.Count; faceIndex++)
            {
                OptimizedFace optimizedFace = facesTriangle[faceIndex];
                optimizedFace.touchingFaces[0] = getOtherFaceIndexContainingVertices(optimizedFace.vertexIndex[0], optimizedFace.vertexIndex[1], faceIndex);
                optimizedFace.touchingFaces[1] = getOtherFaceIndexContainingVertices(optimizedFace.vertexIndex[1], optimizedFace.vertexIndex[2], faceIndex);
                optimizedFace.touchingFaces[2] = getOtherFaceIndexContainingVertices(optimizedFace.vertexIndex[2], optimizedFace.vertexIndex[0], faceIndex);
                if (optimizedFace.touchingFaces[0] == -1)
                {
                    openFacesCount++;
                }
                if (optimizedFace.touchingFaces[1] == -1)
                {
                    openFacesCount++;
                }
                if (optimizedFace.touchingFaces[2] == -1)
                {
                    openFacesCount++;
                }
            }
            //fprintf(stdout, "  Number of open faces: %i\n", openFacesCount);
        }
예제 #2
0
        public void GenerateSupportGrid(OptimizedModel model, ConfigSettings config)
        {
            this.generated = false;
            if (config.supportEndAngle < 0)
            {
                return;
            }

            this.generated = true;

            this.gridOffset.X = model.minXYZ_um.x;
            this.gridOffset.Y = model.minXYZ_um.y;
            this.gridScale    = 200;
            this.gridWidth    = (model.size_um.x / this.gridScale) + 1;
            this.gridHeight   = (model.size_um.y / this.gridScale) + 1;
            int gridSize = this.gridWidth * this.gridHeight;

            this.xYGridOfSupportPoints = new List <List <SupportPoint> >(gridSize);
            for (int i = 0; i < gridSize; i++)
            {
                this.xYGridOfSupportPoints.Add(new List <SupportPoint>());
            }

            this.endAngleDegrees         = config.supportEndAngle;
            this.generateInternalSupport = config.generateInternalSupport;
            this.supportXYDistance_um    = config.supportXYDistance_um;
            this.supportLayerHeight_um   = config.layerThickness_um;
            this.supportZGapLayers       = config.supportNumberOfLayersToSkipInZ;
            this.supportInterfaceLayers  = config.supportInterfaceLayers;

            // This should really be a ray intersection as later code is going to count on it being an even odd list of bottoms and tops.
            // As it is we are finding the hit on the plane but not checking for good intersection with the triangle.
            for (int volumeIndex = 0; volumeIndex < model.volumes.Count; volumeIndex++)
            {
                OptimizedVolume vol = model.volumes[volumeIndex];
                for (int faceIndex = 0; faceIndex < vol.facesTriangle.Count; faceIndex++)
                {
                    OptimizedFace faceTriangle = vol.facesTriangle[faceIndex];
                    Point3        v0           = vol.vertices[faceTriangle.vertexIndex[0]].position;
                    Point3        v1           = vol.vertices[faceTriangle.vertexIndex[1]].position;
                    Point3        v2           = vol.vertices[faceTriangle.vertexIndex[2]].position;

                    // get the angle of this polygon
                    double angleFromHorizon;
                    {
                        FPoint3 v0f    = new FPoint3(v0);
                        FPoint3 v1f    = new FPoint3(v1);
                        FPoint3 v2f    = new FPoint3(v2);
                        FPoint3 normal = (v1f - v0f).Cross(v2f - v0f);
                        normal.z = Math.Abs(normal.z);

                        angleFromHorizon = (Math.PI / 2) - FPoint3.CalculateAngle(normal, FPoint3.Up);
                    }

                    v0.x = (int)((v0.x - this.gridOffset.X) / (double)this.gridScale + .5);
                    v0.y = (int)((v0.y - this.gridOffset.Y) / (double)this.gridScale + .5);
                    v1.x = (int)((v1.x - this.gridOffset.X) / (double)this.gridScale + .5);
                    v1.y = (int)((v1.y - this.gridOffset.Y) / (double)this.gridScale + .5);
                    v2.x = (int)((v2.x - this.gridOffset.X) / (double)this.gridScale + .5);
                    v2.y = (int)((v2.y - this.gridOffset.Y) / (double)this.gridScale + .5);

                    if (v0.x > v1.x)
                    {
                        swap(ref v0, ref v1);
                    }
                    if (v1.x > v2.x)
                    {
                        swap(ref v1, ref v2);
                    }
                    if (v0.x > v1.x)
                    {
                        swap(ref v0, ref v1);
                    }
                    for (long x = v0.x; x < v1.x; x++)
                    {
                        long y0 = (long)(v0.y + (v1.y - v0.y) * (x - v0.x) / (double)(v1.x - v0.x) + .5);
                        long y1 = (long)(v0.y + (v2.y - v0.y) * (x - v0.x) / (double)(v2.x - v0.x) + .5);
                        long z0 = (long)(v0.z + (v1.z - v0.z) * (x - v0.x) / (double)(v1.x - v0.x) + .5);
                        long z1 = (long)(v0.z + (v2.z - v0.z) * (x - v0.x) / (double)(v2.x - v0.x) + .5);

                        if (y0 > y1)
                        {
                            swap(ref y0, ref y1);
                            swap(ref z0, ref z1);
                        }

                        for (long y = y0; y < y1; y++)
                        {
                            SupportPoint newSupportPoint = new SupportPoint((int)(z0 + (z1 - z0) * (y - y0) / (double)(y1 - y0) + .5), angleFromHorizon);
                            this.xYGridOfSupportPoints[(int)(x + y * this.gridWidth)].Add(newSupportPoint);
                        }
                    }

                    for (int x = v1.x; x < v2.x; x++)
                    {
                        long y0 = (long)(v1.y + (v2.y - v1.y) * (x - v1.x) / (double)(v2.x - v1.x) + .5);
                        long y1 = (long)(v0.y + (v2.y - v0.y) * (x - v0.x) / (double)(v2.x - v0.x) + .5);
                        long z0 = (long)(v1.z + (v2.z - v1.z) * (x - v1.x) / (double)(v2.x - v1.x) + .5);
                        long z1 = (long)(v0.z + (v2.z - v0.z) * (x - v0.x) / (double)(v2.x - v0.x) + .5);

                        if (y0 > y1)
                        {
                            swap(ref y0, ref y1);
                            swap(ref z0, ref z1);
                        }

                        for (int y = (int)y0; y < y1; y++)
                        {
                            this.xYGridOfSupportPoints[x + y * this.gridWidth].Add(new SupportPoint((int)(z0 + (z1 - z0) * (double)(y - y0) / (double)(y1 - y0) + .5), angleFromHorizon));
                        }
                    }
                }
            }

            for (int x = 0; x < this.gridWidth; x++)
            {
                for (int y = 0; y < this.gridHeight; y++)
                {
                    int gridIndex = x + y * this.gridWidth;
                    List <SupportPoint> currentList = this.xYGridOfSupportPoints[gridIndex];
                    currentList.Sort(SortSupportsOnZ);

                    if (currentList.Count > 1)
                    {
                        // now remove duplicates (try to make it a better bottom and top list)
                        for (int i = currentList.Count - 1; i >= 1; i--)
                        {
                            if (currentList[i].z == currentList[i - 1].z)
                            {
                                currentList.RemoveAt(i);
                            }
                        }
                    }
                }
            }
            this.gridOffset.X += this.gridScale / 2;
            this.gridOffset.Y += this.gridScale / 2;
        }
예제 #3
0
        public void MakePolygons(OptimizedVolume optomizedMesh, ConfigConstants.REPAIR_OUTLINES outlineRepairTypes)
        {
            for (int startingSegmentIndex = 0; startingSegmentIndex < segmentList.Count; startingSegmentIndex++)
            {
                if (segmentList[startingSegmentIndex].hasBeenAddedToPolygon)
                {
                    continue;
                }

                Polygon poly = new Polygon();
                // We start by adding the start, as we will add ends from now on.
                IntPoint polygonStartPosition = segmentList[startingSegmentIndex].start;
                poly.Add(polygonStartPosition);


                int  segmentIndexBeingAdded = startingSegmentIndex;
                bool canClose;

                bool lastAddWasAStart = true;

                while (true)
                {
                    canClose = false;
                    segmentList[segmentIndexBeingAdded].hasBeenAddedToPolygon = true;
                    IntPoint addedSegmentEndPoint = segmentList[segmentIndexBeingAdded].end;
                    if (!lastAddWasAStart)
                    {
                        // the last added point was an end so add the start as the text end point
                        addedSegmentEndPoint = segmentList[segmentIndexBeingAdded].start;
                    }

                    poly.Add(addedSegmentEndPoint);
                    int           nextSegmentToCheckIndex = -1;
                    OptimizedFace face = optomizedMesh.facesTriangle[segmentList[segmentIndexBeingAdded].faceIndex];
                    for (int connectedFaceIndex = 0; connectedFaceIndex < 3; connectedFaceIndex++)
                    {
                        int testFaceIndex = face.touchingFaces[connectedFaceIndex];
                        if (testFaceIndex > -1)
                        {
                            // If the connected face has an edge that is in the segment list
                            if (faceTo2DSegmentIndex.ContainsKey(testFaceIndex))
                            {
                                int      touchingSegmentIndex = faceTo2DSegmentIndex[testFaceIndex];
                                IntPoint foundSegmentStart    = segmentList[touchingSegmentIndex].start;
                                if (addedSegmentEndPoint == foundSegmentStart)
                                {
                                    // if we have looped back around to where we started
                                    if (addedSegmentEndPoint == polygonStartPosition)
                                    {
                                        canClose = true;
                                    }

                                    // If this segment has already been added
                                    if (segmentList[touchingSegmentIndex].hasBeenAddedToPolygon)
                                    {
                                        continue;
                                    }

                                    nextSegmentToCheckIndex = touchingSegmentIndex;
                                    lastAddWasAStart        = true;
                                }
                                else // let's check if the other side of this segment can hook up (the normal is facing the wrong way)
                                {
                                    IntPoint foundSegmentEnd = segmentList[touchingSegmentIndex].end;
                                    if (addedSegmentEndPoint == foundSegmentEnd)
                                    {
                                        // if we have looped back around to where we started
                                        if (addedSegmentEndPoint == polygonStartPosition)
                                        {
                                            canClose = true;
                                        }

                                        // If this segment has already been added
                                        if (segmentList[touchingSegmentIndex].hasBeenAddedToPolygon)
                                        {
                                            continue;
                                        }

                                        nextSegmentToCheckIndex = touchingSegmentIndex;
                                        lastAddWasAStart        = false;
                                    }
                                }
                            }
                        }
                    }

                    if (nextSegmentToCheckIndex == -1)
                    {
                        break;
                    }

                    segmentIndexBeingAdded = nextSegmentToCheckIndex;
                }

                if (canClose)
                {
                    polygonList.Add(poly);
                }
                else
                {
                    openPolygonList.Add(poly);
                }
            }

            // Link up all the missing ends, closing up the smallest gaps first. This is an inefficient implementation which can run in O(n*n*n) time.
            while (true)
            {
                long bestScore = 10000 * 10000;
                int  bestA     = -1;
                int  bestB     = -1;
                bool reversed  = false;
                for (int polygonAIndex = 0; polygonAIndex < openPolygonList.Count; polygonAIndex++)
                {
                    if (openPolygonList[polygonAIndex].Count < 1)
                    {
                        continue;
                    }

                    for (int polygonBIndex = 0; polygonBIndex < openPolygonList.Count; polygonBIndex++)
                    {
                        if (openPolygonList[polygonBIndex].Count < 1)
                        {
                            continue;
                        }

                        IntPoint diff1        = openPolygonList[polygonAIndex][openPolygonList[polygonAIndex].Count - 1] - openPolygonList[polygonBIndex][0];
                        long     distSquared1 = (diff1).LengthSquared();
                        if (distSquared1 < bestScore)
                        {
                            bestScore = distSquared1;
                            bestA     = polygonAIndex;
                            bestB     = polygonBIndex;
                            reversed  = false;

                            if (bestScore == 0)
                            {
                                // found a perfect match stop looking
                                break;
                            }
                        }

                        if (polygonAIndex != polygonBIndex)
                        {
                            IntPoint diff2        = openPolygonList[polygonAIndex][openPolygonList[polygonAIndex].Count - 1] - openPolygonList[polygonBIndex][openPolygonList[polygonBIndex].Count - 1];
                            long     distSquared2 = (diff2).LengthSquared();
                            if (distSquared2 < bestScore)
                            {
                                bestScore = distSquared2;
                                bestA     = polygonAIndex;
                                bestB     = polygonBIndex;
                                reversed  = true;

                                if (bestScore == 0)
                                {
                                    // found a perfect match stop looking
                                    break;
                                }
                            }
                        }
                    }

                    if (bestScore == 0)
                    {
                        // found a perfect match stop looking
                        break;
                    }
                }

                if (bestScore >= 10000 * 10000)
                {
                    break;
                }

                if (bestA == bestB)
                {
                    polygonList.Add(new Polygon(openPolygonList[bestA]));
                    openPolygonList[bestA].Clear();
                }
                else
                {
                    if (reversed)
                    {
                        if (openPolygonList[bestA].PolygonLength() > openPolygonList[bestB].PolygonLength())
                        {
                            if (openPolygonList[bestA].PolygonLength() > openPolygonList[bestB].PolygonLength())
                            {
                                openPolygonList[bestA].AddRange(openPolygonList[bestB]);
                                openPolygonList[bestB].Clear();
                            }
                            else
                            {
                                openPolygonList[bestB].AddRange(openPolygonList[bestA]);
                                openPolygonList[bestA].Clear();
                            }
                        }
                        else
                        {
                            openPolygonList[bestB].AddRange(openPolygonList[bestA]);
                            openPolygonList[bestB].Clear();
                        }
                    }
                    else
                    {
                        openPolygonList[bestA].AddRange(openPolygonList[bestB]);
                        openPolygonList[bestB].Clear();
                    }
                }
            }


            if ((outlineRepairTypes & ConfigConstants.REPAIR_OUTLINES.EXTENSIVE_STITCHING) == ConfigConstants.REPAIR_OUTLINES.EXTENSIVE_STITCHING)
            {
                //For extensive stitching find 2 open polygons that are touching 2 closed polygons.
                // Then find the sortest path over this polygon that can be used to connect the open polygons,
                // And generate a path over this shortest bit to link up the 2 open polygons.
                // (If these 2 open polygons are the same polygon, then the final result is a closed polyon)

                while (true)
                {
                    int             bestA      = -1;
                    int             bestB      = -1;
                    GapCloserResult bestResult = new GapCloserResult();
                    bestResult.len          = long.MaxValue;
                    bestResult.polygonIndex = -1;
                    bestResult.pointIndexA  = -1;
                    bestResult.pointIndexB  = -1;

                    for (int i = 0; i < openPolygonList.Count; i++)
                    {
                        if (openPolygonList[i].Count < 1)
                        {
                            continue;
                        }

                        {
                            GapCloserResult res = FindPolygonGapCloser(openPolygonList[i][0], openPolygonList[i][openPolygonList[i].Count - 1]);
                            if (res.len > 0 && res.len < bestResult.len)
                            {
                                bestA      = i;
                                bestB      = i;
                                bestResult = res;
                            }
                        }

                        for (int j = 0; j < openPolygonList.Count; j++)
                        {
                            if (openPolygonList[j].Count < 1 || i == j)
                            {
                                continue;
                            }

                            GapCloserResult res = FindPolygonGapCloser(openPolygonList[i][0], openPolygonList[j][openPolygonList[j].Count - 1]);
                            if (res.len > 0 && res.len < bestResult.len)
                            {
                                bestA      = i;
                                bestB      = j;
                                bestResult = res;
                            }
                        }
                    }

                    if (bestResult.len < long.MaxValue)
                    {
                        if (bestA == bestB)
                        {
                            if (bestResult.pointIndexA == bestResult.pointIndexB)
                            {
                                polygonList.Add(new Polygon(openPolygonList[bestA]));
                                openPolygonList[bestA].Clear();
                            }
                            else if (bestResult.AtoB)
                            {
                                Polygon poly = new Polygon();
                                polygonList.Add(poly);
                                for (int j = bestResult.pointIndexA; j != bestResult.pointIndexB; j = (j + 1) % polygonList[bestResult.polygonIndex].Count)
                                {
                                    poly.Add(polygonList[bestResult.polygonIndex][j]);
                                }

                                poly.AddRange(openPolygonList[bestA]);
                                openPolygonList[bestA].Clear();
                            }
                            else
                            {
                                int n = polygonList.Count;
                                polygonList.Add(new Polygon(openPolygonList[bestA]));
                                for (int j = bestResult.pointIndexB; j != bestResult.pointIndexA; j = (j + 1) % polygonList[bestResult.polygonIndex].Count)
                                {
                                    polygonList[n].Add(polygonList[bestResult.polygonIndex][j]);
                                }
                                openPolygonList[bestA].Clear();
                            }
                        }
                        else
                        {
                            if (bestResult.pointIndexA == bestResult.pointIndexB)
                            {
                                openPolygonList[bestB].AddRange(openPolygonList[bestA]);
                                openPolygonList[bestA].Clear();
                            }
                            else if (bestResult.AtoB)
                            {
                                Polygon poly = new Polygon();
                                for (int n = bestResult.pointIndexA; n != bestResult.pointIndexB; n = (n + 1) % polygonList[bestResult.polygonIndex].Count)
                                {
                                    poly.Add(polygonList[bestResult.polygonIndex][n]);
                                }

                                for (int n = poly.Count - 1; (int)(n) >= 0; n--)
                                {
                                    openPolygonList[bestB].Add(poly[n]);
                                }

                                for (int n = 0; n < openPolygonList[bestA].Count; n++)
                                {
                                    openPolygonList[bestB].Add(openPolygonList[bestA][n]);
                                }

                                openPolygonList[bestA].Clear();
                            }
                            else
                            {
                                for (int n = bestResult.pointIndexB; n != bestResult.pointIndexA; n = (n + 1) % polygonList[bestResult.polygonIndex].Count)
                                {
                                    openPolygonList[bestB].Add(polygonList[bestResult.polygonIndex][n]);
                                }

                                for (int n = openPolygonList[bestA].Count - 1; n >= 0; n--)
                                {
                                    openPolygonList[bestB].Add(openPolygonList[bestA][n]);
                                }

                                openPolygonList[bestA].Clear();
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if ((outlineRepairTypes & ConfigConstants.REPAIR_OUTLINES.KEEP_OPEN) == ConfigConstants.REPAIR_OUTLINES.KEEP_OPEN)
            {
                for (int n = 0; n < openPolygonList.Count; n++)
                {
                    if (openPolygonList[n].Count > 0)
                    {
                        polygonList.Add(new Polygon(openPolygonList[n]));
                    }
                }
            }

            //Remove all the tiny polygons, or polygons that are not closed. As they do not contribute to the actual print.
            int snapDistance = 1000;

            for (int polygonIndex = 0; polygonIndex < polygonList.Count; polygonIndex++)
            {
                int length = 0;

                for (int intPointIndex = 1; intPointIndex < polygonList[polygonIndex].Count; intPointIndex++)
                {
                    length += (polygonList[polygonIndex][intPointIndex] - polygonList[polygonIndex][intPointIndex - 1]).vSize();
                    if (length > snapDistance)
                    {
                        break;
                    }
                }
                if (length < snapDistance)
                {
                    polygonList.RemoveAt(polygonIndex);
                    polygonIndex--;
                }
            }

            //Finally optimize all the polygons. Every point removed saves time in the long run.
            double minimumDistanceToCreateNewPosition = 1.415;

            polygonList = Clipper.CleanPolygons(polygonList, minimumDistanceToCreateNewPosition);
        }
예제 #4
0
        public OptimizedVolume(SimpleVolume volume, OptimizedModel model)
        {
            this.model             = model;
            vertices.Capacity      = volume.faceTriangles.Count * 3;
            facesTriangle.Capacity = volume.faceTriangles.Count;

            Dictionary <int, List <int> > indexMap = new Dictionary <int, List <int> >();

            Stopwatch t = new Stopwatch();

            t.Start();
            for (int i = 0; i < volume.faceTriangles.Count; i++)
            {
                OptimizedFace f = new OptimizedFace();
                if ((i % 1000 == 0) && t.Elapsed.Seconds > 2)
                {
                    LogOutput.logProgress("optimized", i + 1, volume.faceTriangles.Count);
                }
                for (int j = 0; j < 3; j++)
                {
                    Point3 p    = volume.faceTriangles[i].v[j];
                    int    hash = (int)(((p.x + MELD_DIST / 2) / MELD_DIST) ^ (((p.y + MELD_DIST / 2) / MELD_DIST) << 10) ^ (((p.z + MELD_DIST / 2) / MELD_DIST) << 20));
                    int    idx  = 0;
                    bool   add  = true;
                    if (indexMap.ContainsKey(hash))
                    {
                        for (int n = 0; n < indexMap[hash].Count; n++)
                        {
                            if ((vertices[indexMap[hash][n]].position - p).testLength(MELD_DIST))
                            {
                                idx = indexMap[hash][n];
                                add = false;
                                break;
                            }
                        }
                    }
                    if (add)
                    {
                        if (!indexMap.ContainsKey(hash))
                        {
                            indexMap.Add(hash, new List <int>());
                        }
                        indexMap[hash].Add(vertices.Count);
                        idx = vertices.Count;
                        vertices.Add(new OptimizedPoint3(p));
                    }
                    f.vertexIndex[j] = idx;
                }
                if (f.vertexIndex[0] != f.vertexIndex[1] && f.vertexIndex[0] != f.vertexIndex[2] && f.vertexIndex[1] != f.vertexIndex[2])
                {
                    //Check if there is a face with the same points
                    bool duplicate = false;
                    for (int _idx0 = 0; _idx0 < vertices[f.vertexIndex[0]].usedByFacesList.Count; _idx0++)
                    {
                        for (int _idx1 = 0; _idx1 < vertices[f.vertexIndex[1]].usedByFacesList.Count; _idx1++)
                        {
                            for (int _idx2 = 0; _idx2 < vertices[f.vertexIndex[2]].usedByFacesList.Count; _idx2++)
                            {
                                if (vertices[f.vertexIndex[0]].usedByFacesList[_idx0] == vertices[f.vertexIndex[1]].usedByFacesList[_idx1] && vertices[f.vertexIndex[0]].usedByFacesList[_idx0] == vertices[f.vertexIndex[2]].usedByFacesList[_idx2])
                                {
                                    duplicate = true;
                                }
                            }
                        }
                    }
                    if (!duplicate)
                    {
                        vertices[f.vertexIndex[0]].usedByFacesList.Add(facesTriangle.Count);
                        vertices[f.vertexIndex[1]].usedByFacesList.Add(facesTriangle.Count);
                        vertices[f.vertexIndex[2]].usedByFacesList.Add(facesTriangle.Count);
                        facesTriangle.Add(f);
                    }
                }
            }
            //fprintf(stdout, "\rAll faces are optimized in %5.1fs.\n",timeElapsed(t));

            int openFacesCount = 0;

            for (int i = 0; i < facesTriangle.Count; i++)
            {
                OptimizedFace f = facesTriangle[i];
                f.touchingFaces[0] = getFaceIdxWithPoints(f.vertexIndex[0], f.vertexIndex[1], i);
                f.touchingFaces[1] = getFaceIdxWithPoints(f.vertexIndex[1], f.vertexIndex[2], i);
                f.touchingFaces[2] = getFaceIdxWithPoints(f.vertexIndex[2], f.vertexIndex[0], i);
                if (f.touchingFaces[0] == -1)
                {
                    openFacesCount++;
                }
                if (f.touchingFaces[1] == -1)
                {
                    openFacesCount++;
                }
                if (f.touchingFaces[2] == -1)
                {
                    openFacesCount++;
                }
            }
            //fprintf(stdout, "  Number of open faces: %i\n", openFacesCount);
        }
예제 #5
0
        public OptimizedMesh(SimpleMesh simpleMesh, OptimizedMeshCollection containingCollection)
        {
            this.containingCollection = containingCollection;
            vertices.Capacity = simpleMesh.faceTriangles.Count * 3;
            facesTriangle.Capacity = simpleMesh.faceTriangles.Count;

            Dictionary<int, List<int>> indexMap = new Dictionary<int, List<int>>();

            Stopwatch t = new Stopwatch();
            t.Start();
            for (int faceIndex = 0; faceIndex < simpleMesh.faceTriangles.Count; faceIndex++)
            {
                if (MatterSlice.Canceled)
                {
                    return;
                }
                OptimizedFace optimizedFace = new OptimizedFace();
                if ((faceIndex % 1000 == 0) && t.Elapsed.TotalSeconds > 2)
                {
                    LogOutput.logProgress("optimized", faceIndex + 1, simpleMesh.faceTriangles.Count);
                }
                for (int vertexIndex = 0; vertexIndex < 3; vertexIndex++)
                {
                    Point3 p = simpleMesh.faceTriangles[faceIndex].vertices[vertexIndex];
                    int hash = (int)(((p.x + MELD_DIST / 2) / MELD_DIST) ^ (((p.y + MELD_DIST / 2) / MELD_DIST) << 10) ^ (((p.z + MELD_DIST / 2) / MELD_DIST) << 20));
                    int idx = 0;
                    bool add = true;
                    if (indexMap.ContainsKey(hash))
                    {
                        for (int n = 0; n < indexMap[hash].Count; n++)
                        {
                            if ((vertices[indexMap[hash][n]].position - p).AbsLengthLEQ(MELD_DIST))
                            {
                                idx = indexMap[hash][n];
                                add = false;
                                break;
                            }
                        }
                    }
                    if (add)
                    {
                        if (!indexMap.ContainsKey(hash))
                        {
                            indexMap.Add(hash, new List<int>());
                        }
                        indexMap[hash].Add(vertices.Count);
                        idx = vertices.Count;
                        vertices.Add(new OptimizedPoint3(p));
                    }
                    optimizedFace.vertexIndex[vertexIndex] = idx;
                }
                if (optimizedFace.vertexIndex[0] != optimizedFace.vertexIndex[1] && optimizedFace.vertexIndex[0] != optimizedFace.vertexIndex[2] && optimizedFace.vertexIndex[1] != optimizedFace.vertexIndex[2])
                {
                    //Check if there is a face with the same points
                    bool duplicate = false;
                    for (int _idx0 = 0; _idx0 < vertices[optimizedFace.vertexIndex[0]].usedByFacesList.Count; _idx0++)
                    {
                        for (int _idx1 = 0; _idx1 < vertices[optimizedFace.vertexIndex[1]].usedByFacesList.Count; _idx1++)
                        {
                            for (int _idx2 = 0; _idx2 < vertices[optimizedFace.vertexIndex[2]].usedByFacesList.Count; _idx2++)
                            {
                                if (vertices[optimizedFace.vertexIndex[0]].usedByFacesList[_idx0] == vertices[optimizedFace.vertexIndex[1]].usedByFacesList[_idx1] && vertices[optimizedFace.vertexIndex[0]].usedByFacesList[_idx0] == vertices[optimizedFace.vertexIndex[2]].usedByFacesList[_idx2])
                                    duplicate = true;
                            }
                        }
                    }
                    if (!duplicate)
                    {
                        vertices[optimizedFace.vertexIndex[0]].usedByFacesList.Add(facesTriangle.Count);
                        vertices[optimizedFace.vertexIndex[1]].usedByFacesList.Add(facesTriangle.Count);
                        vertices[optimizedFace.vertexIndex[2]].usedByFacesList.Add(facesTriangle.Count);
                        facesTriangle.Add(optimizedFace);
                    }
                }
            }
            //fprintf(stdout, "\rAll faces are optimized in %5.1fs.\n",timeElapsed(t));

            int openFacesCount = 0;
            for (int faceIndex = 0; faceIndex < facesTriangle.Count; faceIndex++)
            {
                OptimizedFace optimizedFace = facesTriangle[faceIndex];
                optimizedFace.touchingFaces[0] = getOtherFaceIndexContainingVertices(optimizedFace.vertexIndex[0], optimizedFace.vertexIndex[1], faceIndex);
                optimizedFace.touchingFaces[1] = getOtherFaceIndexContainingVertices(optimizedFace.vertexIndex[1], optimizedFace.vertexIndex[2], faceIndex);
                optimizedFace.touchingFaces[2] = getOtherFaceIndexContainingVertices(optimizedFace.vertexIndex[2], optimizedFace.vertexIndex[0], faceIndex);
                if (optimizedFace.touchingFaces[0] == -1)
                {
                    openFacesCount++;
                }
                if (optimizedFace.touchingFaces[1] == -1)
                {
                    openFacesCount++;
                }
                if (optimizedFace.touchingFaces[2] == -1)
                {
                    openFacesCount++;
                }
            }
            //fprintf(stdout, "  Number of open faces: %i\n", openFacesCount);
        }