Пример #1
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());
        }
    }