对矩形进行分区时出现差一错误

Off-by-one Error when partitioning rectangle

提问人:Raildex 提问时间:10/10/2023 最后编辑:halferRaildex 更新时间:10/11/2023 访问量:37

问:

我正在尝试将矩形拆分为相同大小的桶,如果边框处没有足够的空间,则调整桶的大小。

为了确定存储桶的数量,我使用

int partitionsX = Math.Max((textureWidth / PartitionSize),1);
int partitionsY = Math.Max((textureHeight / PartitionSize), 1);
SampleBucket[] buckets = new SampleBucket[(partitionsX * partitionsY)];
for(int x=0; x < partitionsX; ++x)
{
    for(int y = 0;y < partitionsY; ++y)
    {
        int idx = x + (y * partitionsX);
        var bucketX = x * PartitionSize;
        var bucketY = y * PartitionSize;
        var bucketWidth = PartitionSize;
        var bucketHeight = PartitionSize;
        bucketWidth = Math.Min(bucketX + bucketWidth, (int)textureWidth) - bucketX;
        bucketHeight = Math.Min(bucketY + bucketHeight, (int)textureHeight) - bucketY;
        Debug.Assert(bucketWidth > 0);
        Debug.Assert(bucketHeight > 0);
        buckets[idx] = new SampleBucket()
        {
            X = bucketX,
            Y = bucketY,
            W = bucketWidth,
            H = bucketHeight,
            SampleLocations = Enumerable.Repeat(new SampleLocation() { Index = NOOP}, bucketWidth * bucketHeight).ToArray()
        };
    }
}

当我尝试用我的数据填充存储桶时,会出现此问题。

foreach(var l in sampleLocations)
{
    int bucketX = (int)(l.PixelX / PartitionSize); // PixelX/PixelY is absolute within the original texture/rectangle
    int bucketY = (int)(l.PixelY / PartitionSize);
    int bucketIdx = bucketX + bucketY * partitionsX;
    Debug.Assert(bucketIdx < buckets.Length);
    var bucket = buckets[bucketIdx]; // OOB occurs here, but I don't know where my mistake is
    var locations = bucket.SampleLocations;
    var sampleX = l.PixelX - bucket.X;
    var sampleY = l.PixelY - bucket.Y;
    var sampleIdx = sampleX + sampleY * bucket.W;
    Debug.Assert(sampleIdx < locations.Length);
    locations[sampleIdx] = l;
}

其中 textureWidth = 416、textureHeight = 452 以及 PixelX = 51 和 PixelY = 448 的 SampleLocation 当 PartitionSize 为 32 时,我会收到一个 Out of Bounds Bucket。

我三重检查了数学,但我找不到我的错误在哪里。

带有崩溃用例的演示:https://dotnetfiddle.net/VKYvpP

C# 索引OutOfBoundsException

评论

1赞 jdweng 10/10/2023
错误在第 77 行:var bucket = buckets[bucketIdx];bucketIdx = 桶X + 桶 Y * 分区 X;桶数 = new SampleBucket[(partitionsX * partitionsY)];应该很容易调试。在第 77 行放置一个断点并验证可变值。

答:

1赞 hijinxbassist 10/10/2023 #1

确定分区 X 和 Y 的行使用整数数学。这会导致存储桶少于所需存储桶。

要解决此问题,请采用 的上限。size / partitionSize

int partitionsX = Math.Max((int)Math.Ceiling(textureWidth / (float)PartitionSize),1);
int partitionsY = Math.Max((int)Math.Ceiling(textureHeight / (float)PartitionSize), 1);