Beispiel #1
0
    public static void DrawPolygon(Texture2D draw_tex, List <int> point_list1, List <int> point_list2, Color area_color)
    {
        if (point_list1.Count != point_list2.Count || point_list1.Count < 3)
        {
            Debug.LogError("多边形点集合错误,个数不对!");
            return;
        }
        //创建线多边形,赋值四条边
        PlanePolygon linePolygon = new PlanePolygon();

        for (int i = 0; i < point_list1.Count - 1; i++)
        {
            linePolygon.AddEdge(point_list1[i], point_list2[i], point_list1[i + 1], point_list2[i + 1]);
        }
        linePolygon.AddEdge(point_list1[point_list1.Count - 1], point_list2[point_list1.Count - 1], point_list1[0], point_list2[0]);

        //扫描范围
        int yMin = linePolygon.YMin;
        int yMax = linePolygon.YMax;

        //先画好水平线
        List <PlaneEdge> horizonLine = linePolygon.GetHorizontalLine();

        for (int i = 0; i < horizonLine.Count; i++)
        {
            if (horizonLine[i].x0 < horizonLine[i].x1)
            {
                for (int xValue = horizonLine[i].x0; xValue <= horizonLine[i].x1; xValue++)
                {
                    SetPixelColor(draw_tex, xValue, horizonLine[i].ymin, area_color);
                }
            }
            else
            {
                for (int xValue = horizonLine[i].x1; xValue <= horizonLine[i].x0; xValue++)
                {
                    SetPixelColor(draw_tex, xValue, horizonLine[i].ymin, area_color);
                }
            }
        }
        //初始化活性边表
        List <PlaneEdge> AELTable = new List <PlaneEdge>();

        for (int activeY = yMin; activeY <= yMax; activeY++)
        {
            //加入到活性边表
            List <PlaneEdge> tempAEL = linePolygon.GetAEL(activeY);
            if (tempAEL.Count > 0)
            {
                AELTable.AddRange(tempAEL);
            }


            //遍历活性边表,求交点
            List <int> insectP = new List <int>();
            for (int i = 0; i < AELTable.Count; i++)
            {
                insectP.Add(Convert.ToInt32(AELTable[i].XValue(activeY)));
                //删除求解完成的边
                if (AELTable[i].ymax - 1 == activeY)
                {
                    AELTable.RemoveAt(i);
                    i--;
                }
            }

            //交点排序
            insectP.Sort();
            //填充
            if (insectP.Count % 2 != 0)
            {
                Debug.LogWarning("交点个数不为偶数,自动删除最后一个点,图形应该有误!");
                insectP.RemoveAt(insectP.Count - 1);
            }
            for (int i = 0; i < insectP.Count; i = i + 2)
            {
                for (int xValue = insectP[i]; xValue <= insectP[i + 1]; xValue++)
                {
                    SetPixelColor(draw_tex, xValue, activeY, area_color);
                }
            }
        }
        draw_tex.Apply();
    }
Beispiel #2
0
    public static void DrawSegment(Texture2D draw_tex, int start_x, int start_y, int end_x, int end_y, Color line_color, int thickness)
    {                      //Debug.Log (start_x);Debug.Log (start_y);Debug.Log (end_x);Debug.Log (end_y);
        int R = thickness; //端点半径

        //DDA算法
        //YX轴步进
        int  xDis    = end_x - start_x;
        int  yDis    = end_y - start_y;
        bool isXStep = true;
        int  maxStep = 0;

        //X、Y轴步进选择
        if (Math.Abs(xDis) >= Math.Abs(yDis))
        {
            isXStep = true;
            maxStep = Math.Abs(xDis);
        }
        else
        {
            isXStep = false;
            maxStep = Math.Abs(yDis);
        }
        float widthMakeUp = 0f;

        //斜线宽度补偿
        if (start_x != end_x && start_y != end_y)
        {
            if (isXStep)
            {
                widthMakeUp = (float)(R / Math.Cos(Math.Atan(Math.Abs((double)(end_y - start_y) / (double)(end_x - start_x)))));
            }
            else
            {
                widthMakeUp = (float)(R / Math.Sin(Math.Atan(Math.Abs((double)(end_y - start_y) / (double)(end_x - start_x)))));
            }
        }
        else
        {
            widthMakeUp = thickness;
        }

        //如果是多边形,求四边

        //四条边上的已知点
        float aX = 0;
        float aY = 0;
        float bX = 0;
        float bY = 0;
        float cX = 0;
        float cY = 0;
        float dX = 0;
        float dY = 0;

        if (thickness > 1)
        {
            if (isXStep)
            {
                aX = start_x;
                aY = start_y + widthMakeUp;
                bX = end_x;
                bY = end_y + widthMakeUp;
                cX = start_x;
                cY = start_y - widthMakeUp;
                dX = end_x;
                dY = end_y - widthMakeUp;
            }
            else
            {
                aX = start_x - widthMakeUp;
                aY = start_y;
                bX = end_x - widthMakeUp;
                bY = end_y;
                cX = start_x + widthMakeUp;
                cY = start_y;
                dX = end_x + widthMakeUp;
                dY = end_y;
            }
            //普通斜线段情况,重新计算4个交点
            if (start_x != end_x && start_y != end_y)
            {
                float k  = (float)(start_x - end_x) / (float)(end_y - start_y);
                float b1 = start_y - k * start_x;
                float b2 = end_y - k * end_x;
                //线段AB
                float bAB = aY + (1f / k) * aX;
                //线段CD
                float bCD = cY + (1f / k) * cX;
                aX = (bAB - b1) / (k + 1f / k);
                aY = k * aX + b1;
                cX = (bCD - b1) / (k + 1f / k);
                cY = k * cX + b1;
                bX = (bAB - b2) / (k + 1f / k);
                bY = k * bX + b2;
                dX = (bCD - b2) / (k + 1f / k);
                dY = k * dX + b2;
            }

            //创建线多边形,赋值四条边
            PlanePolygon linePolygon = new PlanePolygon();
            linePolygon.AddEdge(Convert.ToInt32(aX), Convert.ToInt32(aY), Convert.ToInt32(bX), Convert.ToInt32(bY));
            linePolygon.AddEdge(Convert.ToInt32(aX), Convert.ToInt32(aY), Convert.ToInt32(cX), Convert.ToInt32(cY));
            linePolygon.AddEdge(Convert.ToInt32(bX), Convert.ToInt32(bY), Convert.ToInt32(dX), Convert.ToInt32(dY));
            linePolygon.AddEdge(Convert.ToInt32(cX), Convert.ToInt32(cY), Convert.ToInt32(dX), Convert.ToInt32(dY));

            //扫描范围
            int yMin = linePolygon.YMin;
            int yMax = linePolygon.YMax;

            //先画好水平线
            List <PlaneEdge> horizonLine = linePolygon.GetHorizontalLine();
            for (int i = 0; i < horizonLine.Count; i++)
            {
                if (horizonLine[i].x0 < horizonLine[i].x1)
                {
                    for (int xValue = horizonLine[i].x0; xValue <= horizonLine[i].x1; xValue++)
                    {
                        SetPixelColor(draw_tex, xValue, horizonLine[i].ymin, line_color);
                    }
                }
                else
                {
                    for (int xValue = horizonLine[i].x1; xValue <= horizonLine[i].x0; xValue++)
                    {
                        SetPixelColor(draw_tex, xValue, horizonLine[i].ymin, line_color);
                    }
                }
            }

            //初始化活性边表
            List <PlaneEdge> AELTable = new List <PlaneEdge>();
            for (int activeY = yMin; activeY <= yMax; activeY++)
            {
                //加入到活性边表
                List <PlaneEdge> tempAEL = linePolygon.GetAEL(activeY);
                if (tempAEL.Count > 0)
                {
                    AELTable.AddRange(tempAEL);
                }

                //遍历活性边表,求交点
                List <int> insectP = new List <int>();
                for (int i = 0; i < AELTable.Count; i++)
                {
                    insectP.Add(Convert.ToInt32(AELTable[i].XValue(activeY)));
                    //删除求解完成的边
                    if (AELTable[i].ymax - 1 == activeY)
                    {
                        AELTable.RemoveAt(i);
                        i--;
                    }
                }

                //交点排序
                insectP.Sort();
                //填充
                if (insectP.Count % 2 != 0)
                {
                    Debug.LogWarning("交点个数不为偶数,自动删除最后一个点,图形应该有误!");
                    insectP.RemoveAt(insectP.Count - 1);
                }
                for (int i = 0; i < insectP.Count; i = i + 2)
                {
                    for (int xValue = insectP[i]; xValue <= insectP[i + 1]; xValue++)
                    {
                        SetPixelColor(draw_tex, xValue, activeY, line_color);
                    }
                }
            }

            //端点处理,以终点和起点为圆心,画圆
            //起点
            for (int i = start_x - R; i <= start_x + R; i++)
            {
                for (int j = start_y - R; j <= start_y + R; j++)
                {
                    //判断点是否在圆内
                    if ((i - start_x) * (i - start_x) + (j - start_y) * (j - start_y) <= R * R)
                    {
                        SetPixelColor(draw_tex, i, j, line_color);
                    }
                }
            }
            //终点
            for (int i = end_x - R; i <= end_x + R; i++)
            {
                for (int j = end_y - R; j <= end_y + R; j++)
                {
                    //判断点是否在圆内
                    if ((i - end_x) * (i - end_x) + (j - end_y) * (j - end_y) <= R * R)
                    {
                        SetPixelColor(draw_tex, i, j, line_color);
                    }
                }
            }
        }
        else          //最细线段,因为Unity显示的问题,采用了Wu反走样算法
        {
            float fxUnit = (float)xDis / (float)maxStep;
            float fyUnit = (float)yDis / (float)maxStep;
            //设置起点终点颜色
            SetPixelColor(draw_tex, start_x, start_y, line_color);
            SetPixelColor(draw_tex, end_x, end_y, line_color);
            float x    = (float)start_x;
            float y    = (float)start_y;
            int   xInt = 0;
            int   yInt = 0;
            for (int i = 1; i <= maxStep; i++)
            {
                x   += fxUnit;
                y   += fyUnit;
                xInt = (int)x;
                yInt = (int)y;

                //点对反走样
                if (isXStep)
                {
                    //一条线段用一对点来实现反走样
                    if (yInt < Convert.ToInt32(y))
                    {
                        SetPixelColor(draw_tex, Convert.ToInt32(x), yInt, line_color);
                    }
                    else
                    {
                        SetPixelColor(draw_tex, Convert.ToInt32(x), yInt + 1, line_color);
                    }

                    //1的情况,用填充算法不是很好,采用Wu反走样去填补;
                    if (thickness != 0)
                    {
                        thickness = Convert.ToInt32(widthMakeUp) * 2;

                        if (yInt < Convert.ToInt32(y))
                        {
                            for (int yValue = 0; yValue <= widthMakeUp; yValue++)
                            {
                                if (yValue % 2 == 0)
                                {
                                    SetPixelColor(draw_tex, Convert.ToInt32(x), yInt + yValue / 2, line_color);
                                }
                                else
                                {
                                    SetPixelColor(draw_tex, Convert.ToInt32(x), yInt - 1 - (yValue / 2), line_color);
                                }
                            }
                        }
                        else
                        {
                            for (int yValue = 0; yValue <= widthMakeUp; yValue++)
                            {
                                if (yValue % 2 == 0)
                                {
                                    SetPixelColor(draw_tex, Convert.ToInt32(x), yInt - yValue / 2 - 1, line_color);
                                }
                                else
                                {
                                    SetPixelColor(draw_tex, Convert.ToInt32(x), yInt + (yValue / 2), line_color);
                                }
                            }
                        }
                    }
                }
                else
                {
                    //一条线段用一对点来实现反走样
                    if (xInt < Convert.ToInt32(x))
                    {
                        SetPixelColor(draw_tex, xInt, Convert.ToInt32(y), line_color);
                    }
                    else
                    {
                        SetPixelColor(draw_tex, xInt + 1, Convert.ToInt32(y), line_color);
                    }

                    //1的情况,用填充算法不是很好,采用Wu反走样去填补;
                    if (thickness != 0)
                    {
                        thickness = Convert.ToInt32(widthMakeUp) * 2;

                        if (xInt < Convert.ToInt32(x))
                        {
                            for (int xValue = 0; xValue <= widthMakeUp; xValue++)
                            {
                                if (xValue % 2 == 0)
                                {
                                    SetPixelColor(draw_tex, xInt + xValue / 2, Convert.ToInt32(y), line_color);
                                }
                                else
                                {
                                    SetPixelColor(draw_tex, xInt - 1 - (xValue / 2), Convert.ToInt32(y), line_color);
                                }
                            }
                        }
                        else
                        {
                            for (int xValue = 0; xValue <= widthMakeUp; xValue++)
                            {
                                if (xValue % 2 == 0)
                                {
                                    SetPixelColor(draw_tex, xInt - xValue / 2 - 1, Convert.ToInt32(y), line_color);
                                }
                                else
                                {
                                    SetPixelColor(draw_tex, xInt + (xValue / 2), Convert.ToInt32(y), line_color);
                                }
                            }
                        }
                    }
                }
                SetPixelColor(draw_tex, Convert.ToInt32(x), Convert.ToInt32(y), line_color);
            }
        }


        draw_tex.Apply();
    }