Algorithm 填充两条线之间的区域(非直线)

Algorithm 填充两条线之间的区域(非直线),algorithm,Algorithm,我问的是一种算法,它允许用浅绿色填充黑色和深绿色区域之间的区域。黑色区域是固定的。绿色是黑色区域之间的痕迹。 黑色和深绿色的线条可以是四个方向中的一个——北、西、南和东 我对算法(不是算法)有一些想法,但认为它容易出错 所以,我有开始和结束的坐标(结束正好是绿色接触黑色的时候)。我有(xstart,ystart)和(xfinish,yfinish)坐标以及连接这些坐标的黑色和深绿色线条。我的目标是用浅绿色填充中间的区域 如果我找到了我的解决方案,而且很短,我也会把它贴在这里。 对于这种算法的任何

我问的是一种算法,它允许用浅绿色填充黑色和深绿色区域之间的区域。黑色区域是固定的。绿色是黑色区域之间的痕迹。 黑色和深绿色的线条可以是四个方向中的一个——北、西、南和东

我对算法(不是算法)有一些想法,但认为它容易出错

所以,我有开始和结束的坐标(结束正好是绿色接触黑色的时候)。我有(xstart,ystart)和(xfinish,yfinish)坐标以及连接这些坐标的黑色和深绿色线条。我的目标是用浅绿色填充中间的区域

如果我找到了我的解决方案,而且很短,我也会把它贴在这里。 对于这种算法的任何想法都将受到高度赞赏。 顺便说一句,are由一个小矩形1x1组成。因此,可以使用高度(或宽度)或1的线条为区域着色

一旦我找到了算法,我会试着把它贴在这里(如果那不是别人的算法)或者给出一个链接

多谢各位


另外,我的第一个想法是注意横穿任何水平线或垂直线的线(总是?)为偶数。

这是一种标准的泛光填充或光栅填充算法。我猜这是30多年前解决的。你可以在任何一本标准教科书或网络上找到它。以下是指向起点的链接:

基本上,如果尚未填充像素或光栅线,则在一边行走填充线或光栅线。每过一个路口,你就换到另一边。让它工作起来很容易。很难做到快

如果您正在使用任何类型的有能力的图形库,从Windows GDI到OpenGL再到GPU着色器代码,它都已经内置了


这里有一些代码作为想法的来源:

这是一个标准的泛光填充或光栅填充算法。我猜这是30多年前解决的。你可以在任何一本标准教科书或网络上找到它。以下是指向起点的链接:

基本上,如果尚未填充像素或光栅线,则在一边行走填充线或光栅线。每过一个路口,你就换到另一边。让它工作起来很容易。很难做到快

如果您正在使用任何类型的有能力的图形库,从Windows GDI到OpenGL再到GPU着色器代码,它都已经内置了

这里有一些代码作为想法的来源:

您可以从上到下循环“图像”

对于每一行,从左到右循环,从“外部”开始。每次你碰到一条与你所看到的当前线相交的垂直线时,你都会翻转“外/内”位

然后你给里面所有的方块上色

下面是一个演示以下内容的程序:

const int scale = 20;

void Main()
{
    var polyline = new[]
    {
        new Point(4, 0),
        new Point(4, 5),
        new Point(10, 5),
        new Point(10, 10),
        new Point(6, 10),
        new Point(6, 3),
        new Point(15, 3),
        new Point(15, 8),
        new Point(14, 8),
        new Point(14, 7),
        new Point(16, 7),
        new Point(16, 0),
    };

    int maxY = polyline.Max(point => point.Y);
    int maxX = polyline.Max(point => point.X);

    var bitmap = new Bitmap((maxX + 1) * scale, (maxY + 1) * scale);
    var previousPoint = polyline[0];

    using (var g = Graphics.FromImage(bitmap))
    {
        // TODO: y=0 should be y = minY - 1
        for (int y = 0; y < maxY + 1; y++)
        {
            bool isInside = false;
            var xCoordinatesOfCrossingLines = new HashSet<int>(
                from index in Enumerable.Range(0, polyline.Length)
                let p1 = polyline[index]
                let p2 = polyline[(index + 1) % polyline.Length]
                where p1.X == p2.X
                where (p1.Y <= y && p2.Y > y)       // must cross the y-slice in downwards
                      || (p2.Y <= y && p1.Y > y)    // or upwards direction
                let x = p1.X
                group x by x into xGroup            // if we somehow have 2 (or an even number of) lines overlapping, don't count them
                where xGroup.Count() % 2 != 0       // so we will only except distinct x values that occur 1, 3, 5, etc. times
                select xGroup.Key);

            // TODO: x=0 should be x = minX - 1
            for (int x = 0; x < maxX + 1; x++)
            {
                // Every time we hit a vertical line, we flip the "is inside" bit
                if (xCoordinatesOfCrossingLines.Contains(x))
                    isInside = !isInside;

                // Colorize all the squares inside
                if (isInside)
                    g.FillRectangle(Brushes.Green, new Rectangle(
                        ScalePoint(new Point(x, y), scale),
                        new Size(scale, scale)));
            }
        }
        for (int index = 1; index <= polyline.Length; index++)
        {
            g.DrawLine(Pens.Black, ScalePoint(previousPoint, scale), ScalePoint(polyline[index % polyline.Length], scale));
            previousPoint = polyline[index % polyline.Length];
        }
    }
    bitmap.Dump();
}

public Point ScalePoint(Point p, int scale)
{
    return new Point(p.X * scale, p.Y * scale);
}
const int scale=20;
void Main()
{
变量多段线=新[]
{
新点(4,0),
新观点(4,5),
新的点(10,5),
新观点(10,10),
新的点(6,10),
新观点(6,3),
新观点(15,3),
新观点(15,8),
新观点(14,8),
新观点(14,7),
新观点(16,7),
新点(16,0),
};
int maxY=多段线.Max(点=>点.Y);
int maxX=多段线.Max(点=>点.X);
var位图=新位图((maxX+1)*比例,(maxY+1)*比例);
var previousPoint=多段线[0];
使用(var g=Graphics.FromImage(位图))
{
//TODO:y=0应该是y=minY-1
对于(int y=0;y
对于每一条线,你将从左到右循环,从“外部”开始。每次你碰到一条与你正在看的当前线相交的垂直线,你就翻转“外部/内部”位

然后你给里面所有的方块上色

下面是一个演示以下内容的程序:

const int scale = 20;

void Main()
{
    var polyline = new[]
    {
        new Point(4, 0),
        new Point(4, 5),
        new Point(10, 5),
        new Point(10, 10),
        new Point(6, 10),
        new Point(6, 3),
        new Point(15, 3),
        new Point(15, 8),
        new Point(14, 8),
        new Point(14, 7),
        new Point(16, 7),
        new Point(16, 0),
    };

    int maxY = polyline.Max(point => point.Y);
    int maxX = polyline.Max(point => point.X);

    var bitmap = new Bitmap((maxX + 1) * scale, (maxY + 1) * scale);
    var previousPoint = polyline[0];

    using (var g = Graphics.FromImage(bitmap))
    {
        // TODO: y=0 should be y = minY - 1
        for (int y = 0; y < maxY + 1; y++)
        {
            bool isInside = false;
            var xCoordinatesOfCrossingLines = new HashSet<int>(
                from index in Enumerable.Range(0, polyline.Length)
                let p1 = polyline[index]
                let p2 = polyline[(index + 1) % polyline.Length]
                where p1.X == p2.X
                where (p1.Y <= y && p2.Y > y)       // must cross the y-slice in downwards
                      || (p2.Y <= y && p1.Y > y)    // or upwards direction
                let x = p1.X
                group x by x into xGroup            // if we somehow have 2 (or an even number of) lines overlapping, don't count them
                where xGroup.Count() % 2 != 0       // so we will only except distinct x values that occur 1, 3, 5, etc. times
                select xGroup.Key);

            // TODO: x=0 should be x = minX - 1
            for (int x = 0; x < maxX + 1; x++)
            {
                // Every time we hit a vertical line, we flip the "is inside" bit
                if (xCoordinatesOfCrossingLines.Contains(x))
                    isInside = !isInside;

                // Colorize all the squares inside
                if (isInside)
                    g.FillRectangle(Brushes.Green, new Rectangle(
                        ScalePoint(new Point(x, y), scale),
                        new Size(scale, scale)));
            }
        }
        for (int index = 1; index <= polyline.Length; index++)
        {
            g.DrawLine(Pens.Black, ScalePoint(previousPoint, scale), ScalePoint(polyline[index % polyline.Length], scale));
            previousPoint = polyline[index % polyline.Length];
        }
    }
    bitmap.Dump();
}

public Point ScalePoint(Point p, int scale)
{
    return new Point(p.X * scale, p.Y * scale);
}
const int scale=20;
void Main()
{
变量多段线=新[]
{
新点(4,0),
新观点(4,5),
新的点(10,5),
新观点(10,10),
新的点(6,10),
新观点(6,3),
新观点(15,3),
新观点(15,8),
新观点(14,8),
新观点(14,7),
新观点(16,7),
新点(16,0),
};
int maxY=多段线.Max(点=>点.Y);
int maxX=多段线.Max(点=>点.X);
var位图=新位图((maxX+1)*比例,(maxY+1)*比例);
var previousPoint=多段线[0];
使用(var g=Graphics.FromImage(位图))
{
//TODO:y=0应该是y=minY-1
对于(int y=0;y