示例#1
0
    /* Function to sort an array using insertion sort*/
    void insertionSort(EdgeTableTuple ett)
    {
        int        i, j;
        EdgeBucket temp = new EdgeBucket();

        for (i = 1; i < ett.countEdgeBucket; i++)
        {
            temp.ymax         = ett.buckets[i].ymax;
            temp.xofymin      = ett.buckets[i].xofymin;
            temp.slopeinverse = ett.buckets[i].slopeinverse;
            j = i - 1;

            while (j >= 0)
            {
                bool v = (temp.xofymin < ett.buckets[j].xofymin);
                if (!v)
                {
                    break;
                }
                ett.buckets[j + 1].ymax         = ett.buckets[j].ymax;
                ett.buckets[j + 1].xofymin      = ett.buckets[j].xofymin;
                ett.buckets[j + 1].slopeinverse = ett.buckets[j].slopeinverse;
                j = j - 1;
            }
            ett.buckets[j + 1].ymax         = temp.ymax;
            ett.buckets[j + 1].xofymin      = temp.xofymin;
            ett.buckets[j + 1].slopeinverse = temp.slopeinverse;
        }
    }
    // menambah data edge
    public void AddEdge(int x1, int y1, int x2, int y2)
    {
        EdgeBucket edgeBucket = new EdgeBucket();

        // menentukan titik maksimum dan minimum
        if (y1 > y2)
        {
            edgeBucket.yMax = y1;
            edgeBucket.xMax = x1;

            edgeBucket.yMin = y2;
            edgeBucket.xMin = x2;
        }
        else
        {
            edgeBucket.yMax = y2;
            edgeBucket.xMax = x2;

            edgeBucket.yMin = y1;
            edgeBucket.xMin = x1;
        }

        edgeBucket.sum = x1;

        float dx = (float)x2 - (float)x1;
        float dy = (float)y2 - (float)y1;

        float m = (float)dy / (float)dx;

        // menentukan arah garis berdasarkan nilai gradiennya
        if (m < 0)
        {
            edgeBucket.sign = -1;
        }
        else
        {
            edgeBucket.sign = 1;
        }

        edgeBucket.dX = Mathf.Abs(dx);
        edgeBucket.dY = Mathf.Abs(dy);

        // hanya garis yang memiliki jarak y yang dimasukkan,
        // garis horizontal tidak perlu dimasukkan
        if (Mathf.Abs(edgeBucket.dY) > 0)
        {
            this.EdgeTable.Add(edgeBucket);
        }
    }
        public void EdgeTableFill(Color?color, bool del = false)
        {
            EdgeTable    activeEdgeTable = new EdgeTable();
            List <Point> vertices        = new List <Point>();

            for (int i = 0; i < Vertices.Count - 1; i++)
            {
                vertices.Add(Vertices[i]);
            }

            List <int> indexList = Enumerable.Range(0, vertices.Count).OrderBy(x => vertices[x].Y).ToList();
            int        tmpIndex = 0;
            int        beg = indexList[0];
            int        yMin = (int)vertices.Min(x => x.Y), yMax = (int)vertices.Max(x => x.Y);

            while (yMin < yMax)
            {
                if (vertices[beg].Y == yMin)
                {
                    if (vertices[(beg + 1) % vertices.Count].Y > vertices[beg].Y)
                    {
                        activeEdgeTable.Buckets.Add(new EdgeBucket(vertices[beg], vertices[(beg + 1 + vertices.Count) % vertices.Count]));
                    }
                    if (vertices[(beg - 1 + vertices.Count) % vertices.Count].Y > vertices[beg].Y)
                    {
                        activeEdgeTable.Buckets.Add(new EdgeBucket(vertices[beg], vertices[(beg - 1 + vertices.Count) % vertices.Count]));
                    }
                    beg = indexList[++tmpIndex];
                }

                activeEdgeTable.Buckets = activeEdgeTable.Buckets.OrderBy(x => x.XOfYMin).ToList();
                for (int i = 0; i < activeEdgeTable.Buckets.Count - 1; i++)
                {
                    EdgeBucket start = activeEdgeTable.Buckets[i], end = activeEdgeTable.Buckets[i + 1];
                    MainWindow.DrawLine((int)start.XOfYMin, yMin, (int)end.XOfYMin, yMin, 1, color == null ? ColorPoly : (Color)color, del);
                }
                yMin++;
                activeEdgeTable.RemoveElems(yMin);
                activeEdgeTable.Increment();
            }
            IsFilled  = true;
            FillColor = (Color)color;
        }
    public void ProcessEdgeTable()
    {
        if (EdgeTable.Count <= 0)
        {
            return;
        }

        // menyusun edge table berdasarkan nilai yMin
        EdgeTable.Sort((a, b) => a.yMin.CompareTo(b.yMin));

        int y = EdgeTable[0].yMin;

        // mendapatkan posisi minimum dan maksimum semua edge
        // untuk menentukan batas scan
        int minX = int.MaxValue;
        int maxX = int.MinValue;
        int minY = int.MaxValue;
        int maxY = int.MinValue;

        for (int itET = 0; itET < EdgeTable.Count; itET++)
        {
            EdgeBucket bucket = EdgeTable[itET];

            if (bucket.xMin <= minX)
            {
                minX = bucket.xMin;
            }

            if (bucket.xMax <= minX)
            {
                minX = bucket.xMax;
            }

            if (bucket.xMax >= maxX)
            {
                maxX = bucket.xMax;
            }

            if (bucket.xMin >= maxX)
            {
                maxX = bucket.xMin;
            }

            // mencari batas y
            if (bucket.yMin <= minY)
            {
                minY = bucket.yMin;
            }

            if (bucket.yMax <= minY)
            {
                minY = bucket.yMax;
            }

            if (bucket.yMax >= maxY)
            {
                maxY = bucket.yMax;
            }

            if (bucket.yMin >= maxY)
            {
                maxY = bucket.yMin;
            }
        }

        // proses scan
        while (EdgeTable.Count > 0)
        {
            // masukkan edge ke active list jika posisi yMin == y
            for (int itET = 0; itET < EdgeTable.Count; itET++)
            {
                EdgeBucket currentBucket = EdgeTable[itET];

                if (currentBucket.yMin == y && currentBucket.dY != 0)
                {
                    ActiveList.Add(currentBucket);
                }
            }

            // sort edges di Active List berdasarkan nilai x
            ActiveList.Sort((a, b) => a.xMin.CompareTo(b.xMin));

            // update active list x
            for (int itAL = 0; itAL < ActiveList.Count; itAL++)
            {
                EdgeBucket currentBucket = ActiveList[itAL];

                // ubah nilai x berdasarkan gradiennya
                if (currentBucket.dX != 0)
                {
                    float calcX = (float)(y - currentBucket.yMin) / (currentBucket.dY / currentBucket.dX);

                    currentBucket.sum = (int)(currentBucket.xMin + currentBucket.sign * calcX);
                }
            }

            // isi scanline di antara pasangan edges dalam Active List
            List <Vector2Int> edgePair = new List <Vector2Int>();
            for (int x = minX; x <= maxX; x++)
            {
                for (int i = 0; i < ActiveList.Count; i++)
                {
                    EdgeBucket activeBucket = ActiveList[i];
                    if (activeBucket.sum == x)
                    {
                        // masukkan posisi titik perpotongan scanline
                        edgePair.Add(new Vector2Int(x, y));
                    }


                    if (edgePair.Count >= 2)
                    {
                        var pair1 = edgePair[0];
                        var pair2 = edgePair[1];

                        for (int itPair = pair1.x; itPair <= pair2.x; itPair++)
                        {
                            Color previousColor = targetTex.GetPixel(itPair, y);

                            // warnai kolom di antara dua garis potong
                            Color color = gradient.Evaluate(Mathf.InverseLerp(minY, maxY, y));
                            color = color + previousColor * (1f - color.a);
                            targetTex.SetPixel(itPair, y, color);
                        }
                        edgePair.Clear();
                    }
                }
            }

            // lakukan proses ke baris selanjutnya
            y++;

            // hilangkan dari list jika sudah menyentuh titik ujung paling atas
            for (int itAL = ActiveList.Count - 1; itAL >= 0; itAL--)
            {
                EdgeBucket activeEdge = ActiveList[itAL];
                if (y == activeEdge.yMax)
                {
                    EdgeTable.Remove(activeEdge);
                    ActiveList.Remove(activeEdge);
                }
            }
        }
    }
示例#5
0
    public int[][] ConvexFill(int[][] points)
    {
        // edge table
        EdgeTable et = new EdgeTable();
        int       topx1 = -1, topx2 = -1, topy = -1;

        for (int pIndex = 0, len = points.GetLength(0); pIndex < len; pIndex++)
        {
            int[] p1 = points[pIndex];
            int[] p2 = points[pIndex + 1 >= len ? 0 : pIndex + 1];
            if (p1[1] != p2[1])
            {
                int      yMin = 0;
                EdgeNode node = new EdgeNode();
                if (p1[1] > p2[1])
                {
                    yMin      = p2[1];
                    node.yMax = p1[1];
                    node.xMin = p2[0];
                }
                else
                {
                    yMin      = p1[1];
                    node.yMax = p2[1];
                    node.xMin = p1[0];
                }
                node.m = (float)(p1[0] - p2[0]) / (p1[1] - p2[1]);
                et.AddNode(yMin, node);
            }
            else
            {
                // 记录top horizontal edge
                // 这种简单判断topEdge的方式只对Convex有效
                if (p1[1] > topy)
                {
                    topy = p1[1];
                    if (p1[0] > p2[0])
                    {
                        topx1 = p2[0];
                        topx2 = p1[0];
                    }
                    else
                    {
                        topx1 = p1[0];
                        topx2 = p2[0];
                    }
                }
                if (pIndex == len - 1 &&
                    topy < points[1][1])
                {
                    topy = -1;
                }
            }
        }

        // active edge table
        EdgeBucket aet = new EdgeBucket();

        if (et.Count == 0)
        {
            return(null);
        }
        else
        {
            // loop
            Queue <int[]> result = new Queue <int[]>();
            while (et.Count > 0 || aet.Count > 0)
            {
                if (aet.Count == 0)
                {
                    aet.yMin = et[0].yMin;
                    et[0].ForEach((EdgeNode each) => aet.AddNode(each));
                    et.RemoveAt(0);
                }
                else
                {
                    if (et.Count > 0 &&
                        aet.yMin == et[0].yMin)
                    {
                        et[0].ForEach((EdgeNode each) => aet.AddNode(each));
                        et.RemoveAt(0);
                    }
                }
                for (int aIndex = aet.Count - 1; aIndex >= 0; aIndex--)
                {
                    if (aet[aIndex].yMax <= aet.yMin)
                    {
                        aet.RemoveAt(aIndex);
                    }
                }
                for (int aIndex = 0; aIndex < aet.Count; aIndex++)
                {
                    if (aIndex % 2 == 0 &&
                        aIndex < aet.Count - 1)
                    {
                        float left  = aet[aIndex].xMin;
                        float right = aet[aIndex + 1].xMin;
                        if (topy == -1 || aet.yMin != topy || left >= topx2 || right <= topx1)
                        {
                            // 以上判断是为了排除top horizontal edge
                            int ileft  = MathS.Floor(left);
                            int iright = MathS.Floor(right);
                            for (int ixMin = ileft; ixMin <= iright; ixMin += 1)
                            {
                                if (ixMin >= left && ixMin < right)
                                {
                                    // 以上判断是为了排除像素点刚好在rightEdge的情况
                                    result.Enqueue(new int[] { ixMin, aet.yMin });
                                }
                            }
                        }
                        aet[aIndex].xMin     += aet[aIndex].m;
                        aet[aIndex + 1].xMin += aet[aIndex + 1].m;
                        if (aet[aIndex].xMin > aet[aIndex + 1].xMin)
                        {
                            EdgeNode temp = aet[aIndex];
                            aet[aIndex]     = aet[aIndex + 1];
                            aet[aIndex + 1] = temp;
                        }
                    }
                }
                aet.yMin += 1;
            }
            return(result.ToArray());
        }
    }