设多边形各顶点的坐标为:(x1, y1), (x2, y2), (x3, y3)……(xn, yn),其排列顺序是杂乱的,依次连接这n个点,无法形成确定的多边形。
对多边形的顶点按逆时针方向进行排序,可以得到凸多边形。具体步骤如下:
- 计算多边形的内点O,以内点O作为逆时针旋转的中心点。
多边形的内点:(Σxn/n, Σyn/n) - 判断点A与点B之间的方向:计算OA与OB的向量叉积,如果OA与OB的叉积大于0,则OB在OA的逆时针方向,即点A大于点B。
向量叉积:设P=(x1, y1),Q=(x2, y2),则P×Q = x1y2 - x2y1
package Polygon;
import java.awt.*;
/**
* 对多边形的顶点按逆时针方向进行排序
*/
public class PolygonSort {
public static void main(String[] args) {
Polygon polygon = new Polygon(new int[]{1,2,6,4,5}, new int[]{4,5,2,1,4}, 5);
for (int i = 0; i < polygon.npoints; i++) {
System.out.println("(" + polygon.xpoints[i] + ", " + polygon.ypoints[i] + ")");
}
// 对多边形的顶点按逆时针方向进行排序
PolygonSort polygonSort = new PolygonSort();
Polygon polygonAfterSort = polygonSort.PolygonClockwiseSort(polygon);
System.out.println("对多边形的顶点按逆时针方向进行排序:");
for (int i = 0; i < polygonAfterSort.npoints; i++) {
System.out.println("(" + polygonAfterSort.xpoints[i] + ", " + polygonAfterSort.ypoints[i] + ")");
}
}
/**
* 对多边形的顶点按逆时针方向进行排序
*/
public Polygon PolygonClockwiseSort(Polygon polygon) {
PolygonSort polygonSort = new PolygonSort();
// 计算多边形的内点O
Point center = polygonSort.getCenter(polygon);
// 冒泡排序
Point tmp = new Point();
for (int i = 1; i < polygon.npoints; i++) {
for (int j = 0; j < polygon.npoints - i; j++) {
// 判断点A与点B之间的方向
if (PointCmp(new Point(polygon.xpoints[j], polygon.ypoints[j]), new Point(polygon.xpoints[j+1], polygon.ypoints[j+1]), center)) {
tmp.setLocation(polygon.xpoints[j], polygon.ypoints[j]);
polygon.xpoints[j] = polygon.xpoints[j+1]; polygon.ypoints[j] = polygon.ypoints[j+1];
polygon.xpoints[j+1] = tmp.x; polygon.ypoints[j+1] = tmp.y;
}
}
}
return polygon;
}
/**
* 计算多边形的内点O
*/
public Point getCenter(Polygon polygon) {
// 多边形的顶点个数
int num = polygon.npoints;
// 多边形的顶点求和
double X = 0, Y = 0;
for (int i = 0; i < num; i++) {
X += polygon.xpoints[i];
Y += polygon.ypoints[i];
}
// 返回内点
Point center = new Point();
center.setLocation(X / num, Y / num);
return center;
}
/**
* 判断点A与点B之间的方向
*/
public boolean PointCmp(Point pointA, Point pointB, Point center) {
// 计算OA与OB的向量叉积
int det = (pointA.x - center.x) * (pointB.y - center.y) - (pointB.x - center.x) * (pointA.y - center.y);
// 若OA在OB的顺时针方向,点A大于点B,按降序排列,则返回false
if (det > 0) {
return false;
}
else {
return true;
}
}
}
参考:
- https://zhuanlan.zhihu.com/p/265688744