public static List <List <Vector2i> > ScanAlignY(List <Vector2i> poly)
        {
            List <List <Vector2i> > results = new List <List <Vector2i> >();
            Vector2i max = new Vector2i(int.MinValue, int.MinValue);
            Vector2i min = new Vector2i(int.MaxValue, int.MaxValue);

            foreach (Vector2i v in poly)
            {
                max = Vector2i.Max(v, max);
                min = Vector2i.Min(v, min);
            }
            List <Vector2i> trans     = poly.Select(t => { return(t - min); }).ToList();
            int             height    = max[1] - min[1];
            List <ScanEdge> scanLines = new List <ScanEdge>();
            int             count     = trans.Count;
            int             count1    = count - 1;

            for (int i = 0; i < count; ++i)
            {
                Vector2i ps   = trans[i];
                int      post = (i + 1) % count;
                Vector2i pe   = trans[post];
                if (ps[1] == pe[1]) // 水平 去掉
                {
                    Vector2i        hori   = Vector2i.GetVector2i(ps[0], pe[0]);
                    List <Vector2i> result = new List <Vector2i>();
                    for (int hi = hori[0]; hi <= hori[1]; ++hi)
                    {
                        result.Add(new Vector2i(hi, ps[1]));
                    }
                    if (result.Count > 0)
                    {
                        result = result.Select(t => { return(t + min); }).ToList();
                        results.Add(result);
                    }
                    continue;
                }
                int      pre    = (i + count1) % count;
                Vector2i pss    = trans[pre];
                int      ppost  = (post + 1) % count;
                Vector2i pee    = trans[ppost];
                double   dx     = (ps[0] - pe[0]) * 1.0f / (ps[1] - pe[1]);
                bool     yiG0   = ps[1] < pe[1];
                double   startX = yiG0 ? ps[0] : pe[0];
                int      ymin   = yiG0 ? ps[1] : pe[1];
                int      ymax   = yiG0 ? pe[1] : ps[1];
                if (pe[1] > ps[1])
                {
                    if (pee[1] >= pe[1])
                    {
                        ymax -= 1;
                    }
                }
                else
                {
                    if (pss[1] >= ps[1])
                    {
                        ymax -= 1;
                    }
                }
                ScanEdge ep = new ScanEdge();
                ep.mMinY   = ymin;
                ep.mMaxY   = ymax;
                ep.mStartX = startX;
                ep.mDx     = dx;
                scanLines.Add(ep);
            }

            for (int i = 0; i < height; ++i)
            {
                List <Vector2i> result = new List <Vector2i>();
                List <ScanEdge> tmp    = scanLines.FindAll(delegate(ScanEdge line) { return(line.Include(i)); });
                tmp.Sort((e1, e2) =>
                {
                    //此处可以不考虑 斜率。 x相等时,不用考虑谁在前谁在后
                    return(e1.mStartX.CompareTo(e2.mStartX));
                });
                if (tmp.Count % 2 != 0)
                {
                    throw new Exception("必须是偶数");
                }
                for (int idx = 0; idx < tmp.Count; idx += 2)
                {
                    int next = idx + 1;
                    int x1   = (int)tmp[idx].mStartX;
                    int x2   = (int)tmp[next].mStartX;
                    if (x1 > x2)
                    {
                        continue;
                    }
                    for (int xi = x1; xi <= x2; ++xi)
                    {
                        result.Add(new Vector2i(xi, i));
                    }
                    tmp[idx].Increase();
                    tmp[next].Increase();
                }
                scanLines.RemoveAll((t) => t.mMaxY == i);
                if (result.Count > 0)
                {
                    result = result.Select(t => { return(t + min); }).ToList();
                    results.Add(result);
                }
            }
            return(results);
        }
        protected void DrawScreenSpaceTriangleInterpolated(PreparedTriangle triangle)
        {
            WriteableBitmap rt = _renderWindow.Framebuffer;

            if (triangle.GetScreenSpaceDirection() != VisibleTriangleDirection)
            {
                return;
            }

            var triangleArea = CalculateTriangleArea(
                triangle.Vertices[0].X, triangle.Vertices[0].Y,
                triangle.Vertices[1].X, triangle.Vertices[1].Y,
                triangle.Vertices[2].X, triangle.Vertices[2].Y);

            var vertexX = new double[] { triangle.Vertices[0].X, triangle.Vertices[1].X, triangle.Vertices[2].X };
            var vertexY = new double[] { triangle.Vertices[0].Y, triangle.Vertices[1].Y, triangle.Vertices[2].Y };

            var scanEdges = new List <ScanEdge>();

            for (int current = 0; current < 3; ++current)
            {
                int next = (current + 1) % 3;

                double higherx, highery;
                double lowerx, lowery;

                if (vertexY[current] < vertexY[next])
                {
                    higherx = vertexX[current];
                    highery = vertexY[current];
                    lowerx  = vertexX[next];
                    lowery  = vertexY[next];
                }
                else
                {
                    higherx = vertexX[next];
                    highery = vertexY[next];
                    lowerx  = vertexX[current];
                    lowery  = vertexY[current];
                }

                int minY = (int)highery;
                int maxY = (int)lowery;
                //int startX = (int)higherx;
                //int endX = (int)lowerx;

                if (minY == maxY)
                {
                    continue;
                }

                var scanEdge = new ScanEdge();
                scanEdge.MinimalY = (int)Math.Ceiling(highery);
                scanEdge.MaximalY = (int)Math.Ceiling(lowery);
                scanEdge.X        = higherx;
                scanEdge.XSlope   = (lowerx - higherx) / ((double)(lowery - highery));

                scanEdges.Add(scanEdge);
            }

            if (scanEdges.Count == 0)
            {
                return;
            }

            scanEdges = scanEdges.OrderBy(t => t.MinimalY).ToList();
            int scanEdgesActivated = 0;

            var startY = Math.Max(scanEdges.Min(t => t.MinimalY), 0);
            var endY   = Math.Min(scanEdges.Max(t => t.MaximalY), rt.PixelHeight - 1);

            var activeEdges = new List <ScanEdge>();

            for (var y = startY; y <= endY; ++y)
            {
                activeEdges = activeEdges.Where(t => y < t.MaximalY).ToList();

                while (scanEdgesActivated < scanEdges.Count)
                {
                    if (y < scanEdges[scanEdgesActivated].MinimalY)
                    {
                        break;
                    }

                    activeEdges.Add(scanEdges[scanEdgesActivated]);
                    ++scanEdgesActivated;
                }

                activeEdges = activeEdges.OrderBy(t => t.X).ToList();

                for (int i = 0; i < activeEdges.Count - 1; i += 2)
                {
                    int startX = (int)Math.Ceiling(Math.Max(activeEdges[i].X, 0));
                    int endX   = (int)Math.Floor(Math.Min(activeEdges[i + 1].X, rt.PixelWidth - 1));

                    for (int x = startX; x <= endX; ++x)
                    {
                        var aArea = CalculateTriangleArea(
                            x, y,
                            triangle.Vertices[1].X, triangle.Vertices[1].Y,
                            triangle.Vertices[2].X, triangle.Vertices[2].Y);

                        var bArea = CalculateTriangleArea(
                            triangle.Vertices[0].X, triangle.Vertices[0].Y,
                            x, y,
                            triangle.Vertices[2].X, triangle.Vertices[2].Y);

                        var cArea = CalculateTriangleArea(
                            triangle.Vertices[0].X, triangle.Vertices[0].Y,
                            triangle.Vertices[1].X, triangle.Vertices[1].Y,
                            x, y);

                        var fa = Math.Min(aArea / triangleArea, 1.0);
                        var fb = Math.Min(bArea / triangleArea, 1.0);
                        var fc = Math.Min(cArea / triangleArea, 1.0);

                        if (fa + fb + fc > 1.0)
                        {
                            int    lowestAreaIndex = 0;
                            double lowestArea      = fa;

                            if (lowestArea > fb)
                            {
                                lowestAreaIndex = 1;
                                lowestArea      = fb;
                            }

                            if (lowestArea > fc)
                            {
                                lowestAreaIndex = 2;
                                lowestArea      = fc;
                            }

                            switch (lowestAreaIndex)
                            {
                            case 0:
                                fa = 1.0 - fb - fc;
                                break;

                            case 1:
                                fb = 1.0 - fa - fc;
                                break;

                            case 2:
                                fc = 1.0 - fa - fb;
                                break;
                            }
                        }

                        var z = fa * triangle.Vertices[0].Z
                                + fb * triangle.Vertices[1].Z
                                + fc * triangle.Vertices[2].Z;

                        if (z <= 1.0)
                        {
                            continue;
                        }

                        if (_zBuffer[x, y] > z)
                        {
                            continue;
                        }

                        _zBuffer[x, y] = z;

                        // Pixel Shader
                        Color outputColor = InterpolateColor(
                            fa, triangle.Vertices[0].VertexColor,
                            fb, triangle.Vertices[1].VertexColor,
                            fc, triangle.Vertices[2].VertexColor);

                        if (TexturingEnabled && Material.DiffuseTexture != null)
                        {
                            var u = fa * triangle.Vertices[0].U + fb * triangle.Vertices[1].U + fc * triangle.Vertices[2].U;
                            var v = fa * triangle.Vertices[0].V + fb * triangle.Vertices[1].V + fc * triangle.Vertices[2].V;

                            u = Math.Min(Math.Max(u, 0.0), 1.0);
                            v = Math.Min(Math.Max(v, 0.0), 1.0);

                            Color texColor = Material.DiffuseTexture.GetPixel((int)(u * Material.DiffuseTexture.PixelWidth),
                                                                              (int)(v * Material.DiffuseTexture.PixelHeight));
                            outputColor = MultiplyColors(outputColor, texColor);
                        }
                        // End of pixel shader

                        rt.SetPixel(x, y, outputColor);
                    }
                }

                activeEdges.ForEach(t => t.X += t.XSlope);
            }
        }