/// <summary> /// Calls <paramref name="plot"/> for points in the trapezoid spanned by two scanlines. /// The points with maximal X or Y coordinates are left out. /// </summary> public static void InterpolatePlot(PointPlotDelegate plot, Scanline scan1, Scanline scan2) { int divisor = scan2._y - scan1._y; if (divisor == 0) divisor = 1; int x1Step = scan2._x1 - scan1._x1; int x2Step = scan2._x2 - scan1._x2; for (var scanline = new Scanline { _y = scan1._y, _x1 = scan1._x1 * divisor, _x2 = scan1._x2 * divisor }; scanline._y < scan2._y; ++scanline._y, scanline._x1 += x1Step, scanline._x2 += x2Step) { int x1 = scanline._x1.DivRound(divisor); int x2 = scanline._x2.DivRound(divisor); for (int x = x1; x < x2; ++x) plot(x, scanline._y); } }
/// <summary> /// Calls <paramref name="plot"/> once for each integer point in a filled triangle. /// The points of the triangle that are maximal in X or Y coordinate are /// not plotted to allow plotting two triangles that share a side without /// the points of the two triangles overlapping each other. /// </summary> public static void FillTriangle(Point point1, Point point2, Point point3, PointPlotDelegate plot) { // Sort points by increasing Y if (point2.Y < point1.Y) Swap(ref point1, ref point2); if (point3.Y < point2.Y) { Swap(ref point2, ref point3); if (point2.Y < point1.Y) Swap(ref point1, ref point2); } // Find master scanlines var scan1 = new Scanline(point1.Y, point1.X); if (point2.Y == point1.Y) scan1.Include(point2.X); if (point3.Y == point1.Y) scan1.Include(point3.X); var scan2 = scan1; if (point2.Y > scan1.Y) { scan2 = new Scanline(point2.Y, point2.X); if (point3.Y == point2.Y) scan2.Include(point3.X); } else if (point3.Y > scan1.Y) { scan2 = new Scanline(point3.Y, point3.X); } var scan3 = scan2; if (point3.Y > scan2.Y) { scan3 = new Scanline(point3.Y, point3.X); scan2.IncludeInterpolated(scan3, scan1); } // Loop through Y, interpolating between master scanlines Scanline.InterpolatePlot(plot, scan1, scan2); Scanline.InterpolatePlot(plot, scan2, scan3); }