WorldEdit

WorldEdit

43M Downloads

getArea() and Polygonal2DRegion - don't return real value.

LadyCailinBot opened this issue ยท 8 comments

commented

WORLDEDIT-3096 - Reported by BukkitSmerf

Every Polygonal2DRegion returns other sizes than should, even rectangles:
Example code:

		Polygonal2DRegion polReg = new Polygonal2DRegion();
		polReg.addPoint(new BlockVector2D(1, 1));
		polReg.addPoint(new BlockVector2D(1, 10));
		polReg.addPoint(new BlockVector2D(10, 10));
		polReg.addPoint(new BlockVector2D(10, 1));
		// 10x10 = 100
		sender.sendMessage(Integer.toString(polReg.getArea()));
		// send 89 (9x9) instead of 100

I need that to block creating too big regions/selections.

commented

Comment by wizjany

duplicate

edit: spoke to soon, apparently WE is just as broken as WG?
however your code is using the wrong kind of region - WG regions and WE regions are not interchangeable

commented

Comment by BukkitSmerf

I only need size, but WG don't provide any options in ProtectedPolygonalRegion, so I used WE by java new Polygonal2DRegion(null, protectedPolygonalRegion.getPoints(), 64, 64);
;/ PS: any idea how to fix this, and calculate size without WE?

commented

Comment by sk89q

Well, you'll need a better algorithm than the one that WE uses, which is apparently broken.

I don't have a better one off my head, otherwise WE would already be using it. You can try searching the web. Be careful though: most implementations are not for discrete points (blocks).

commented

Comment by BukkitSmerf

hyym... So problem is in Minecraft blocks?, in normal math, if you have point x = 1 and x = 10 then you have 9 units, but in minecraft - 10 units? ;/ But I have no idea how to fix that...

But maybe this code can be used:

	public static int getArea(Polygonal2DRegion region)
	{
		Vector maxP = region.getMaximumPoint();
		Vector minP = region.getMinimumPoint();
		int minY = minP.getBlockY();
		int maxY = maxP.getBlockY();
		int y = (minY + maxY) / 2;
		int size = 0;
		for (int x = minP.getBlockX(); x <= maxP.getBlockX(); x++)
		{
			for (int z = minP.getBlockZ(); z <= maxP.getBlockY(); z++)
			{
				if (region.contains(new BlockVector(x, y, z)))
				{
					size++;
				}
			}
		}
		return size * ((maxY - minY) + 1);
	}```

Tested on region with 102 points and 101x101 size [very big "spiral"], and works good with time between 15-8 ms.
Maybe not great, but seems to work.
commented

Comment by sk89q

That does work, but yeah, as you said, it's not ideal.

Unfortunately, I have not yet studied computational geometry.

commented

Comment by BukkitSmerf

Me too :/ But i think that code will be better than old - return good size, but in longer time. (1000 x 1000 - 80 ms ;/) And... only //size command is using this?

I looking for any code for my plugin so I ask question here: http://stackoverflow.com/questions/23136512/area-of-polygon
Maybe one of comments will be helpful for you. (I'm too weak in math to fully understand all this algorithms))

commented
commented

Comment by BukkitSmerf

Hyym, sorry for time, I test it tomorrow, but if you only add this: " + .5" then result will be this same :P