Reputation: 1269
I'm creating a Canvas object ( lines, vertices, triangle, ...) and I would like to apply to them a rotation around a point.
I can't use the rotate() method of Canvas because points are attached to GeoPoint on a Map, so if I use the rotate() method the all map is rotating ...
The problem is that Canvas needs Point(int,int) and applying a rotation creates double because of cos and sin functions. So when I apply the rotation to the all points, because of casting double to int, I have some graphical issue that happens...
So I'm looking for the best solution.
Here my rotation code :
public Point rotatePoint(Point pt, Point center)
{
this.angle = ((this.angle/180)*Math.PI);
double cosAngle = Math.cos(this.angle);
double sinAngle = Math.sin(this.angle);
pt.x = center.x + (int) ((pt.x-center.x)*cosAngle-(pt.y-center.y)*sinAngle);
pt.y = center.y + (int) ((pt.x-center.x)*sinAngle+(pt.y-center.y)*cosAngle);
return pt;
}
Upvotes: 3
Views: 9062
Reputation: 21
Try this:
public Point rotatePoint(Point pt, Point anchorPoint, double angleDeg) {
double angleRad = Math.toRadians(angleDeg);
double dx = (pt.x - anchorPoint.x); //x-cord. is transformed to origin
double dy = (pt.y - anchorPoint.y); //y-cord. is transformed to origin
double ptX = anchorPoint.x + (dx * Math.cos(angleRad) - dy * Math.sin(angleRad));
double ptY = anchorPoint.y + (dx * Math.sin(angleRad) + dy * Math.cos(angleRad));
return new Point((int) ptX, (int) ptY);
}
Upvotes: 0
Reputation: 600
the code has a small bug when calculating pt.y. (pt.x is updated but is later on used). instead try the following:
public Point rotatePoint(Point pt, Point center)
{
this.angle = ((this.angle/180)*Math.PI);
double cosAngle = Math.cos(this.angle);
double sinAngle = Math.sin(this.angle);
double dx = (pt.x-center.x);
double dy = (pt.y-center.y);
pt.x = center.x + (int) (dx*cosAngle-dy*sinAngle);
pt.y = center.y + (int) (dx*sinAngle+dy*cosAngle);
return pt;
}
I also use the following variation:
public Point rotatePoint(Point pt, Point center, double angleDeg)
{
double angleRad = (angleDeg/180)*Math.PI);
double cosAngle = Math.cos(angleRad );
double sinAngle = Math.sin(angleRad );
double dx = (pt.x-center.x);
double dy = (pt.y-center.y);
pt.x = center.x + (int) (dx*cosAngle-dy*sinAngle);
pt.y = center.y + (int) (dx*sinAngle+dy*cosAngle);
return pt;
}
Upvotes: 7
Reputation: 70931
I believe your solution is quite good. A small improvement would be to add 0.5 to the coordinates before casting them to integer and that way you will have the rounding we are usually used to - everything above 0.5 will get rounded to 1 for instance. Other than that I don't think you can avoid doing rounding as you want to place a continuous space into discrete one(i.e. the plane to a canvas).
Upvotes: 1