如何解决分割Java多边形
int[] x = {38,100,80,18};
int[] y = {50,50,100};
polygon poly = new polygon(x,y,4);
上面的多边形只是一个例子。上面的多边形实际上可以是任何东西,只要该多边形始终为凸形,始终具有4个点并且为平行四边形即可。我需要将其拆分为任意数量的偶数部分,所有这些均与较大的多边形成比例,只要该数字是平方数即可。有什么简单的方法可以做到这一点吗?如果这很重要,我将在Jframe上使用Graphics。
解决方法
下面的代码适用于任何凸4面多边形。当初始多边形是平行四边形时,生成的子多边形也自然也是所有平行四边形,它们都具有相同的大小,即偶数大小。
由于parts
的所需数目必须是一个平方数,这意味着我们可以简单地将4边多边形水平和垂直地分成partsPerSide = sqrt(parts)
。
当我们将4边形的多边形分成多个部分时,最终可能会得到不完全是整数的坐标。我们可以简单地将值四舍五入为整数,但是碎片的大小可能并不完全相等。这是否可以接受是一个选择的问题。从视觉上看,由于线不会是100%直的,因此可以看到舍入。
在下面的代码中,我们假设舍入是不可接受的,即我们想要精确的偶数大小。如果可以取整,只需在末尾注释掉if (rounded != delta) throw new ArithmeticException()
代码,然后以所需的splitFourSided()
号码调用partsPerSide
。
可以说的是,这是代码:
private static Polygon[][] splitFourSided(Polygon poly,int partsPerSide) {
if (poly.npoints != 4)
throw new IllegalArgumentException("Polygon must be 4-sided");
if (partsPerSide <= 0)
throw new IllegalArgumentException("There must be a positive number of parts per side");
int[][] x = splitFourSided(poly.xpoints,partsPerSide);
int[][] y = splitFourSided(poly.ypoints,partsPerSide);
Polygon[][] pieces = new Polygon[partsPerSide][partsPerSide];
for (int row = 0; row < partsPerSide; row++) {
for (int col = 0; col < partsPerSide; col++) {
pieces[row][col] = new Polygon(
new int[] { x[row][col],x[row][col+1],x[row+1][col+1],x[row+1][col] },new int[] { y[row][col],y[row][col+1],y[row+1][col+1],y[row+1][col] },4);
}
}
return pieces;
}
private static int[][] splitFourSided(int[] xy,int parts) {
// To visualize,assume values are [topLeft,topRight,bottomRight,bottomLeft].
// The 'xy' array is either the x-coordinates or the y-coordinates.
// First we split left and right sides,e.g. for 3 parts:
// From: ┌ To: ┐
// ├ ┤
// ├ ┤
// └ ┘
// Then we split between those:
// ┌─┬─┬─┐
// ├─┼─┼─┤
// ├─┼─┼─┤
// └─┴─┴─┘
int[] from = splitRange(xy[0],xy[3],parts);
int[] to = splitRange(xy[1],xy[2],parts);
int[][] grid = new int[parts + 1][];
for (int i = 0; i <= parts; i++)
grid[i] = splitRange(from[i],to[i],parts);
return grid;
}
private static int[] splitRange(int from,int to,int parts) {
int[] prorated = new int[parts + 1];
for (int i = 0; i <= parts; i++)
prorated[i] = prorate(from,to,i,parts);
return prorated;
}
private static int prorate(int from,int index,int parts) {
if (index == 0)
return from;
if (index == parts)
return to;
double delta = (to - (double) from) * index / parts;
int rounded = (int) Math.round(delta);
if (rounded != delta)
throw new ArithmeticException("Cannot prorate to integer value");
return from + rounded;
}
测试
int[] x = {38,100,80,18};
int[] y = {50,50,100};
Polygon poly = new Polygon(x,y,4);
splitAndDrawFourSided(g,poly,2);
private static void splitAndDrawFourSided(Graphics g,Polygon poly,int partsPerSide) {
Polygon[][] pieces = splitFourSided(poly,partsPerSide);
for (int row = 0; row < partsPerSide; row++)
for (int col = 0; col < partsPerSide; col++)
g.drawPolygon(pieces[row][col]);
Graphics gMain = g.create();
try {
gMain.setColor(Color.RED);
gMain.drawPolygon(poly);
} finally {
gMain.dispose();
}
}
结果
要搜索有效数量的零件,我们可以添加一个搜索循环,并更改坐标,使其只能被7整除。
int[] x = {37,79,16};
int[] y = {50,99,99};
Polygon poly = new Polygon(x,4);
for (int partsPerSide : new int[] { 2,3,5,7,11,13,17,19 }) {
try {
splitAndDrawFourSided(g,partsPerSide);
break; // stop when successful
} catch (@SuppressWarnings("unused") ArithmeticException ignored) {
continue; // try next number of parts
}
}
结果
如果我们删除了四舍五入检查,那么该代码当然总是每边仅分为2部分,即分成4部分。这显示了舍入的效果,例如在这种情况下,中间行的坐标会稍微向右结束,从而导致黑线和红线不匹配。即使没有红线描绘输入的平行四边形,也可以注意到四舍五入。 Anti-aliasing有帮助,但仍然可以注意到垂直线并不是100%笔直。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。