Пример #1
0
        public void DoProcessing()
        {
            if (!gcode.IsOpened())
            {
                return;
            }

            timeKeeper.Restart();
            LogOutput.Log("Analyzing and optimizing model...\n");
            optomizedModel = new OptimizedModel(simpleModel);
            if (MatterSlice.Canceled)
            {
                return;
            }
            optomizedModel.SetPositionAndSize(simpleModel, config.positionToPlaceObjectCenter_um.X, config.positionToPlaceObjectCenter_um.Y, -config.bottomClipAmount_um, config.centerObjectInXy);
            for (int volumeIndex = 0; volumeIndex < simpleModel.volumes.Count; volumeIndex++)
            {
                LogOutput.Log("  Face counts: {0} . {1} {2:0.0}%\n".FormatWith((int)simpleModel.volumes[volumeIndex].faceTriangles.Count, (int)optomizedModel.volumes[volumeIndex].facesTriangle.Count, (double)(optomizedModel.volumes[volumeIndex].facesTriangle.Count) / (double)(simpleModel.volumes[volumeIndex].faceTriangles.Count) * 100));
                LogOutput.Log("  Vertex counts: {0} . {1} {2:0.0}%\n".FormatWith((int)simpleModel.volumes[volumeIndex].faceTriangles.Count * 3, (int)optomizedModel.volumes[volumeIndex].vertices.Count, (double)(optomizedModel.volumes[volumeIndex].vertices.Count) / (double)(simpleModel.volumes[volumeIndex].faceTriangles.Count * 3) * 100));
            }

            LogOutput.Log("Optimize model {0:0.0}s \n".FormatWith(timeKeeper.Elapsed.Seconds));
            timeKeeper.Reset();

            Stopwatch timeKeeperTotal = new Stopwatch();

            timeKeeperTotal.Start();
            preSetup(config.extrusionWidth_um);
            sliceModels(storage);

            processSliceData(storage);
            if (MatterSlice.Canceled)
            {
                return;
            }
            writeGCode(storage);
            if (MatterSlice.Canceled)
            {
                return;
            }

            LogOutput.logProgress("process", 1, 1);             //Report to the GUI that a file has been fully processed.
            LogOutput.Log("Total time elapsed {0:0.00}s.\n".FormatWith(timeKeeperTotal.Elapsed.Seconds));
        }
Пример #2
0
        public void DoProcessing()
        {
            if (!gcode.IsOpened())
            {
                return;
            }

            timeKeeper.Restart();
            LogOutput.Log("Analyzing and optimizing model...\n");
            optomizedModel = new OptimizedModel(simpleModel);
            if (MatterSlice.Canceled)
            {
                return;
            }
            optomizedModel.SetPositionAndSize(simpleModel, config.positionToPlaceObjectCenter_um.X, config.positionToPlaceObjectCenter_um.Y, -config.bottomClipAmount_um, config.centerObjectInXy);
            for (int volumeIndex = 0; volumeIndex < simpleModel.volumes.Count; volumeIndex++)
            {
                LogOutput.Log("  Face counts: {0} . {1} {2:0.0}%\n".FormatWith((int)simpleModel.volumes[volumeIndex].faceTriangles.Count, (int)optomizedModel.volumes[volumeIndex].facesTriangle.Count, (double)(optomizedModel.volumes[volumeIndex].facesTriangle.Count) / (double)(simpleModel.volumes[volumeIndex].faceTriangles.Count) * 100));
                LogOutput.Log("  Vertex counts: {0} . {1} {2:0.0}%\n".FormatWith((int)simpleModel.volumes[volumeIndex].faceTriangles.Count * 3, (int)optomizedModel.volumes[volumeIndex].vertices.Count, (double)(optomizedModel.volumes[volumeIndex].vertices.Count) / (double)(simpleModel.volumes[volumeIndex].faceTriangles.Count * 3) * 100));
            }

            LogOutput.Log("Optimize model {0:0.0}s \n".FormatWith(timeKeeper.Elapsed.Seconds));
            timeKeeper.Reset();

            Stopwatch timeKeeperTotal = new Stopwatch();
            timeKeeperTotal.Start();
            preSetup(config.extrusionWidth_um);
            sliceModels(storage);

            processSliceData(storage);
            if (MatterSlice.Canceled)
            {
                return;
            }
            writeGCode(storage);
            if (MatterSlice.Canceled)
            {
                return;
            }

            LogOutput.logProgress("process", 1, 1); //Report to the GUI that a file has been fully processed.
            LogOutput.Log("Total time elapsed {0:0.00}s.\n".FormatWith(timeKeeperTotal.Elapsed.Seconds));
        }
Пример #3
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;
        }
Пример #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 OptimizedVolume(SimpleVolume volume, OptimizedModel model)
        {
            this.parentModel       = 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 faceIndex = 0; faceIndex < volume.faceTriangles.Count; faceIndex++)
            {
                if (MatterSlice.Canceled)
                {
                    return;
                }
                OptimizedFace optimizedFace = new OptimizedFace();
                if ((faceIndex % 1000 == 0) && t.Elapsed.Seconds > 2)
                {
                    LogOutput.logProgress("optimized", faceIndex + 1, volume.faceTriangles.Count);
                }
                for (int vertexIndex = 0; vertexIndex < 3; vertexIndex++)
                {
                    Point3 p    = volume.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);
        }
Пример #6
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;
        }