Using Affine Transform to rotate polygon - java

I'm currently trying to rotate a polygon using the Affine Transform class. Using the rotate method, the polygon's graphical representation updates, but the bounding box of the polygon doesn't update. How can I rotate the polygon in addition to updating it's coordinates?

Create a new Shape instead of just rotating the polygon as your paint it. For example:
Polygon shape = new Polygon();
shape.addPoint(...);
....
Rectangle bounds = shape.getBounds();
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(angle), bounds.width / 2, bounds.height / 2);
Path2D path = (shape instanceof Path2D) ? (Path2D)shape : new GeneralPath(shape);
Shape rotated = path.createTransformedShape( transform );
System.out.println(rotated.getBounds());

Related

Points not filling trying to draw an arrow head (triangle) with Graphics2D

When trying to draw an arrowhead using Java Graphics2D by using points and inputting the coordinates.
g2.drawLine(xLeft+290, yTop + 80, xLeft+290,yTop + 100); //first arrow
Polygon arrowHead = new Polygon();
arrowHead.addPoint(xLeft+290, yTop+140);//firstpoint
arrowHead.addPoint(xLeft+285, yTop+120);//secondpoint
arrowHead.addPoint(xLeft+295, yTop+120);//thirdpoint
g2.fillPolygon(arrowHead);
This is my code for drawing the line and the arrowhead, I'm not sure at all of the coordinates are correct but I can't see the shape if it will not appear.

How can I use BoofCV to transform a list of vertices so that the center of the polygon they form will be moved to the middle of the image?

I'm using the code below to detect shapes and extract a list of vertices for each shape found (stored in the List Vertexes). How can I transform the vertices for a shape to ensure that the shape will be located at the center of the image when I draw the vertices?
done here> VisualizeShapes.drawPolygon(vertexes,true,g2);
Is there a built-in way to do it using BoofCV or does it have to be done manually?
/**
* Fits polygons to found contours around binary blobs.
*/
public static void fitBinaryImage(ImageFloat32 input)
{
ImageUInt8 binary = new ImageUInt8(input.width,input.height);
BufferedImage polygon = new BufferedImage(input.width,input.height,BufferedImage.TYPE_INT_RGB);
// the mean pixel value is often a reasonable threshold when creating a binary image
double mean = ImageStatistics.mean(input);
// create a binary image by thresholding
ThresholdImageOps.threshold(input, binary, (float) mean, true);
// reduce noise with some filtering
ImageUInt8 filtered = BinaryImageOps.erode8(binary, 1, null);
filtered = BinaryImageOps.dilate8(filtered, 1, null);
// Find the contour around the shapes
List<Contour> contours = BinaryImageOps.contour(filtered, ConnectRule.EIGHT,null);
// Fit a polygon to each shape and draw the results
Graphics2D g2 = polygon.createGraphics();
g2.setStroke(new BasicStroke(2));
for( Contour c : contours )
{
// Fit the polygon to the found external contour. Note loop = true
List<PointIndex_I32> vertexes = ShapeFittingOps.fitPolygon(c.external,true,toleranceDist,toleranceAngle,100);
g2.setColor(Color.RED);
VisualizeShapes.drawPolygon(vertexes,true,g2);
// handle internal contours now
g2.setColor(Color.BLUE);
for( List<Point2D_I32> internal : c.internal )
{
vertexes = ShapeFittingOps.fitPolygon(internal,true,toleranceDist,toleranceAngle,100);
//********************************************************************************************************************
//** how can I transform the vertexes here so that the polygon they form is centered at the middle of the image ? ****
//********************************************************************************************************************
VisualizeShapes.drawPolygon(vertexes,true,g2);
}
System.out.println(vertexes.toString());
System.out.println(vertexes.size());
}
UtilImageIO.saveImage(polygon, "/Users/m/temp/3_fitbinaryimage.png");
}

What is the correct way to convert a Shape to a Rectangle2D.Double?

I have the need to transform (rotate) a Rectangle2D.Double. However, I don't just need to draw the shape, I also need to keep the transformed rectangle as an object so that I can use .intersects() and other methods. This is the current way I am transforming it
private Rectangle2D.Double transform(Rectangle2D.Double rect) {
// make a new transform
AffineTransform transform = new AffineTransform();
// apply the transformation
transform.rotate(Math.toRadians(theta), rect.x + rect.width / 2, rect.y + rect.height / 2);
// get the resulting Shape
Shape s = transform.createTransformedShape(hitbox);
//return the finalized Rectangle
// ?
}
Now, one would think that the following would work
Rectangle2D.Double newRect = new Rectangle2D.Double();
newRect.setFrame(transform.createTransformedShape(rect).getBounds2D());
However, when drawn this appears to not rotate the rect at all, but instead scale it by very large amounts (140 times as large).
So the question is: How do I get that Shape, which by the way when drawn appears to be transformed correctly, into the correct form, which is a Rectangle2D.Double?
If it isn't possible then what is a good alternative that still has the .intersects() and similar methods?
Rectangle2D is axis aligned. It cannot be turned. Try using a Path2D instead. There is a nice constructor that seems to be doing exactly what you want:
Path2D.Double(Shape shape, AffineTransform transform)
private Path2D.Double transform(Rectangle2D.Double rect) {
AffineTransform transform = new AffineTransform();
double angle = Math.toRadians(theta);
transform.rotate(angle, rect.x + rect.width / 2, rect.y + rect.height / 2);
return new Path2D.Double(rect, transform);
}
Also note that your toRadians(toRadians(theta)) is very suspicious and makes your angles very tiny.

Image not drawn to a fixed position when rotating with AffineTransform

I have a problem with rotating image in a fixed position with Graphcis2D and AffineTransform.
The idea is to rotate an image according to body's rotation.
The rotation is happening correctly as the rotation angle of the image matches the angle of the body's rotation. However, as the rotation takes place, the image is not drawn to the same position as the body should be drawn. The code of the method painting the picture is the following:
public void paintPicture(Graphics g, Body body) {
Graphics2D g2 = (Graphics2D) g;
Vector2f[] vertices = ((Box) body.getShape()).getPoints(body.getPosition(), body.getRotation());
Vector2f topLeftCorner = vertices[0];
AffineTransform oldTransform = g2.getTransform();
AffineTransform at = new AffineTransform();
at.rotate(body.getRotation());
g2.setTransform(at);
g2.drawImage(this.img, (int) topLeftCorner.x, (int) topLeftCorner.y, null);
g2.setTransform(oldTransform);
}
Any ideas what might cause the movement of the image instead of drawing it according to the coordinates (topLeftCorner.x, topLeftCorner.y)?
You need to first translate you object so the anchor point (the point around which you want it to rotate) is at the origin, perform your rotation, then translate it back. So if you want to rotate around the point (50, 75), you'd do the following:
at.translate (-50, -75);
at.rotate (body.getRotation());
at.translate (50, 75);
I'm assuming that your AffineTransform class can accumulate transformations. If not, you'll need 3 different transforms.

Rotating a Rectangle on an Image using Swing

Ok when a user draws a Rectangle on top of an image, I want to find all the rotated Rectangles ahead of time for all image rotation angles (90,180,270,360).
According to Java API I can just keep calling the Graphics2D rotate() method. I can then use this Graphics2D transformer to get the rotated Rectangle.
This works for the very first rotation(1.5708) call. I get the correct Rectangle Point. All other calls after that return the wrong Rectangle Point after using Transformer.
I think my problem is the Graphics2D translate(x,y). I don't understand how to use it.
Anyone knows how to fix my code so that it will return the correct Rectangle after every rotation?
Thank you.
public void rotateRectangles(BufferedImage bim,int width,int height,Rectangle rect){
BufferedImage bim = new BufferedImage(height, width,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) (bufferedImage.createGraphics());
g2d.translate(bufferedImage.getHeight(),0);
//Get Rectangle for 90 degree image rotation. This always good.
g2d.rotate(1.5708);
Shape shape = g2d.getTransform().createTransformedShape(rect);
Rectangle rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 90 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
//Get Rectangle for 180 degree image rotation. Getting wrong rotatedRect.
g2d.rotate(1.5708);
shape = g2d.getTransform().createTransformedShape(rect);
rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 180 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
//Get Rectangle for 270 degree image rotation. Getting wrong rotatedRect.
g2d.rotate(1.5708);
shape = g2d.getTransform().createTransformedShape(rect);
rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 270 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
//Get Rectangle for 360 degree image rotation.Getting wrong rotatedRect.
g2d.rotate(1.5708);
shape = g2d.getTransform().createTransformedShape(rect);
rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 360 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
}
Thank you.
Instead of rotating the graphics context's affine transform via g2d.rotate(), consider using createTransformedShape() as suggested in this example.
Addendum: Note in particular that the baseline of the example Polygon is initially centered on the origin. As a result, the initial transformation is rotation around the origin. In your case, you can use the rotate() method that includes an anchor point, which would be the center of your rectangle.

Categories