Java: AffineTransform 旋转多边形,然后得到它的点
Java: AffineTransform rotate Polygon, then get its points
我想画一个多边形并像这样用 AffineTransform 旋转它。
float theta = 90;
Polygon p = new Polygon(new int[]{0, 4, 4, 0}, new int[]{0, 0, 4, 4}, 4);
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(theta), p.xpoints[0], p.ypoints[0]);
Shape transformed = transform.createTransformedShape(p);
g2.fill(transformed);
但是,我希望能够像访问多边形一样访问点 (transformed.xpoints[0])。一种看待这个问题的方法是将形状转换为多边形——但据我所知这是不可能的。
最好的选择是什么?
作为旁注:这是创建由 4 边多边形(矩形)组成的分形树的练习。我选择使用多边形来分别将分支锚定到左上角和右上角。如果这不必要地复杂化,请告诉我。
您也可以使用 AffineTransform
来变换各个点,如下所示:
Point2D[] srcPoints = new Point2D[] { new Point(0, 0), new Point(4, 0), new Point(4, 4), new Point(4, 0) };
Point2D[] destPoints = new Point2D[4];
transform.transform(srcPoints, 0, destPoints, 0, 4);
生成的 destPoints
数组如下所示:
[Point2D.Float[-0.0, 0.0], Point2D.Float[-0.0, 4.0], Point2D.Float[-4.0, 4.0], Point2D.Float[-0.0, 4.0]]
您可以从 createTransformedShape(...)
返回的路径中获取坐标。
Path2D.Double transformed = (Path2D.Double) transform.createTransformedShape(p);
List<Double> xpointsList = new ArrayList<>();
List<Double> ypointsList = new ArrayList<>();
PathIterator pi = transformed.getPathIterator(null);
while(!pi.isDone()){
double[] coords = new double[6];
int type = pi.currentSegment(coords);
if(type == PathIterator.SEG_MOVETO || type == PathIterator.SEG_LINETO){ // The only types we're interested in given the original shape
xpointsList.add(coords[0]);
ypointsList.add(coords[1]);
}
pi.next();
}
我有一段时间没有这样做了,可能有更简单的方法来实现你想要的。此外,转换为 Path2D.Double
并不理想。
已经有一段时间了,但我忍不住把它放在这里,以供以后遇到此问题的人使用。
那么我们只使用 teenie-weenie 一点数学而不是 AffineTransform 怎么样?
public class ROTOR {
/**
* Method for rotating a Point object in the XY plane or in any plane
* parallel to the XY plane. The Point object to be rotated and the one
* about which it is rotating must have the same Z coordinates.
*
* @param p a Point object in the xy plane The z coordinates of both Point
* objects must be either the same or must both be zero.
* @param cen a Point object about which the rotation of the first Point
* object will occur.
* @param angle the angle of rotation
* @return
*/
public static Point planarXYRotate(Point p,Point cen,double angle){
double sin = Math.sin(angle);
double cos = Math.cos(angle);
double X = p.x*cos-p.y*sin+cen.x*(1-cos)+cen.y*sin;
double Y = p.x*sin+p.y*cos+cen.y*(1-cos)-cen.x*sin;
return new Point( (int) X, (int) Y );
}//end method
/**
*
* @param polygon The polygon to rotate
* @param origin The point about which to rotate it.
* @param angle The angle of rotation.
* @return a new Polygon rotated through the specified angle and about the said point.
*/
public static Polygon rotate(Polygon polygon , Point origin , double angle){
Point cen = new Point(origin.x , origin.y);
Polygon newPolygon = new Polygon();
for(int i=0;i<polygon.npoints;i++){
Point p = new Point( polygon.xpoints[i] , polygon.ypoints[i] );
Point point = ROTOR.planarXYRotate(p, cen, angle);
newPolygon.addPoint((int) point.x, (int) point.y);
}
return newPolygon;
}
}
然后您可以轻松获得旋转的多边形并根据需要获取其点,使用:
Polygon rotatedPolygon = ROTOR.rotate(polygon, origin, angle);
我想画一个多边形并像这样用 AffineTransform 旋转它。
float theta = 90;
Polygon p = new Polygon(new int[]{0, 4, 4, 0}, new int[]{0, 0, 4, 4}, 4);
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(theta), p.xpoints[0], p.ypoints[0]);
Shape transformed = transform.createTransformedShape(p);
g2.fill(transformed);
但是,我希望能够像访问多边形一样访问点 (transformed.xpoints[0])。一种看待这个问题的方法是将形状转换为多边形——但据我所知这是不可能的。
最好的选择是什么?
作为旁注:这是创建由 4 边多边形(矩形)组成的分形树的练习。我选择使用多边形来分别将分支锚定到左上角和右上角。如果这不必要地复杂化,请告诉我。
您也可以使用 AffineTransform
来变换各个点,如下所示:
Point2D[] srcPoints = new Point2D[] { new Point(0, 0), new Point(4, 0), new Point(4, 4), new Point(4, 0) };
Point2D[] destPoints = new Point2D[4];
transform.transform(srcPoints, 0, destPoints, 0, 4);
生成的 destPoints
数组如下所示:
[Point2D.Float[-0.0, 0.0], Point2D.Float[-0.0, 4.0], Point2D.Float[-4.0, 4.0], Point2D.Float[-0.0, 4.0]]
您可以从 createTransformedShape(...)
返回的路径中获取坐标。
Path2D.Double transformed = (Path2D.Double) transform.createTransformedShape(p);
List<Double> xpointsList = new ArrayList<>();
List<Double> ypointsList = new ArrayList<>();
PathIterator pi = transformed.getPathIterator(null);
while(!pi.isDone()){
double[] coords = new double[6];
int type = pi.currentSegment(coords);
if(type == PathIterator.SEG_MOVETO || type == PathIterator.SEG_LINETO){ // The only types we're interested in given the original shape
xpointsList.add(coords[0]);
ypointsList.add(coords[1]);
}
pi.next();
}
我有一段时间没有这样做了,可能有更简单的方法来实现你想要的。此外,转换为 Path2D.Double
并不理想。
已经有一段时间了,但我忍不住把它放在这里,以供以后遇到此问题的人使用。
那么我们只使用 teenie-weenie 一点数学而不是 AffineTransform 怎么样?
public class ROTOR {
/**
* Method for rotating a Point object in the XY plane or in any plane
* parallel to the XY plane. The Point object to be rotated and the one
* about which it is rotating must have the same Z coordinates.
*
* @param p a Point object in the xy plane The z coordinates of both Point
* objects must be either the same or must both be zero.
* @param cen a Point object about which the rotation of the first Point
* object will occur.
* @param angle the angle of rotation
* @return
*/
public static Point planarXYRotate(Point p,Point cen,double angle){
double sin = Math.sin(angle);
double cos = Math.cos(angle);
double X = p.x*cos-p.y*sin+cen.x*(1-cos)+cen.y*sin;
double Y = p.x*sin+p.y*cos+cen.y*(1-cos)-cen.x*sin;
return new Point( (int) X, (int) Y );
}//end method
/**
*
* @param polygon The polygon to rotate
* @param origin The point about which to rotate it.
* @param angle The angle of rotation.
* @return a new Polygon rotated through the specified angle and about the said point.
*/
public static Polygon rotate(Polygon polygon , Point origin , double angle){
Point cen = new Point(origin.x , origin.y);
Polygon newPolygon = new Polygon();
for(int i=0;i<polygon.npoints;i++){
Point p = new Point( polygon.xpoints[i] , polygon.ypoints[i] );
Point point = ROTOR.planarXYRotate(p, cen, angle);
newPolygon.addPoint((int) point.x, (int) point.y);
}
return newPolygon;
}
}
然后您可以轻松获得旋转的多边形并根据需要获取其点,使用:
Polygon rotatedPolygon = ROTOR.rotate(polygon, origin, angle);