I am aware that there are a few questions about points and rotation out here, and I feel like Im almost there. I youst need a little push.
I Have a shape with 6 points like this one.
I want to rotate the Point P around Point C
And I need to do this manually so I am not interested in using AffineTransform
thanks in advance
Thread thread = new Thread() {
public void run() {
//THE RADIUS OF THE SHAPE IS 100
//GET THE POINT P
PointClass point_class = points.get(0);
//GET THE CENTER POINT C
Point center = new Point(point_class.point.x - 100, point_class.point.y);
int deg = 0;
while(deg < 360) {
//GET THE ANGLE IN RADIANS
double angle = Math.toRadians(deg);
//FIRST TRANSLATE THE DIFFERENCE
int x1 = point_class.point.x - center.x;
int y1 = point_class.point.y - center.y;
//APPLY ROTATION
x1 = (int) ((double) x1 * Math.cos(angle) - y1 * Math.sin(angle));
y1 = (int) ((double) x1 * Math.sin(angle) + y1 * Math.cos(angle));
//TRANSLATE BACK
point_class.point.x = x1 + center.x;
point_class.point.y = y1 + center.y;
//ROTATE + 1 DEEGRE NEXT TIME
deg++;
try {
//SLEEP TO SEE THE DIFFERENCE
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
thread.start();
What happens with this code is that the Point P ends up in the center like this
I think your radius is shrinking each time through the while loop due to the casting of doubles to ints. This might work better instead:
double x1 = point_class.point.x - center.x;
double y1 = point_class.point.y - center.y;
//APPLY ROTATION
x1 = x1 * Math.cos(angle) - y1 * Math.sin(angle));
y1 = x1 * Math.sin(angle) + y1 * Math.cos(angle));
//TRANSLATE BACK
point_class.point.x = (int)Math.ceil(x1) + center.x;
point_class.point.y = (int)Math.ceil(y1) + center.y;
So I figured out what was wrong.
The Translation of the two points,
//FIRST TRANSLATE THE DIFFERENCE
double x1 = point_class.point.x - center.x;
double y1 = point_class.point.y - center.y;
has to go outside of the loop, because I need to take base at that location when applying the rotation matrix. And also in the loop, I should have the deegre fixed at 1, so that it is only incrementet by 1 and not 81+82+83...Dont know why i did that.
Hope this helps someone =)
Related
The following code is called every 50ms.
// Start point
private double x;
private double y;
private double z;
private double y1;
#Override
public void run() {
double x1 = Math.cos(y1);
double z1 = Math.sin(y1);
double y2 = 4D - y1;
double x2 = Math.sin(y2);
double z2 = Math.cos(y2);
// First new point
double pX1 = x + x1;
double pY1 = y + y1;
double pZ1 = z + z1;
// Second new point
double pX2 = x + x2;
double pY2 = y + y2;
double pZ2 = z + z2;
if (y1 > 4D) {
y1 = 0D;
} else {
y1 = y1 + 0.1D;
}
}
Here is the output in a game. It generates two helices.
I cannot control more than the radius.
I am looking for code I can easily customize to fit my preferences.
How do I control the following aspects?
How fast the helix rises.
Where the helix begins.
helix is circular shape with 'linear' movement of the plane
you use plane xz as helix base and y axis as height
so you need:
r - radius
d - distance between two screws (the y movement after full circle)
t - parameter <0,1> determining the position on helix
h0,h1 - start end height of helix (y-axis)
a0 - angular start position [rad]
Now how to get the point on helix as function of parameter these parameters
aa=fabs(h1-h0)*2.0*M_PI/d; // angular speed coefficient
// if you need opposite angular direction then add aa=-aa;
x=r*cos(a0+aa*t);
z=r*sin(a0+aa*t);
y=h0+((h1-h0)*t);
aa can be precomputed once
now if t=0.0 then you get the start point of helix
if t=1.0 then you got the endpoint of helix
so speed is just how much you add to t during animation per timer cycle
d controls number of screw loops
h1-h0 is the helix height
code is in C++ (sorry I am not a JAVA coder)
One part of the helix begins at:
(x, y, z) = (1.0, 0.0, 0.0)
And the other at:
(x, y, z) = (-0.8, 4.0, -0.7)
And the particle rises at a rate of 0.1 (from y1 = y1 + 0.1D).
So, to control how fast the particles rise, just change this value.
To control where the helix begins you need to change the angle. For example, add some value to the sines and cosines. Like this:
Math.cos(y1 + dy);
To make more rotations before restarting from the ground you can multiply the angle. Make it twice as fast:
Math.cos(2 * y1);
Helix is circular shape with progressive Y value.
// Start point
private double x;
private double y;
private double z;
private double degree;
private double rY;
#Override
public void run() {
// We use the same formula that is used to find a point of a circumference
double rX = Math.cos(degree);
double rZ = Math.sin(degree);
// New point
double pX = x + rX;
double pY = y + rY;
double pZ = z + rZ;
if (degree > 2D * Math.PI) {
degree = 0D;
} else {
degree = degree + 0.2D;
}
if (pY > 2D) {
pY = 0D;
} else {
pY = pY + 0.02D;
}
}
I am writing a game. I need to know how to rotate point a around point b by a given number of degrees. I am writing this in java and it is going to be part of my class, Point.
double x1 = point.x - center.x;
double y1 = point.y - center.y;
double x2 = x1 * Math.cos(angle) - y1 * Math.sin(angle));
double y2 = x1 * Math.sin(angle) + y1 * Math.cos(angle));
point.x = x2 + center.x;
point.y = y2 + center.y;
This approach uses rotation matrices. "point" is your point a, "center" is your point b.
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;
}
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;
}
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).
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);
}
I am having an issue with my program; currently it rotates around a set point, and can rotate models around it. Of course, this is a problem as I want it to be a first-person perspective, and currently, it rotates around a point in front of the viewer, instead of the perspective of the viewer. Here is the trigonometric calculations:
protected void drawWireframe(Graphics g) {
double theta = Math.PI * -azimuth / 180.0D;
double phi = Math.PI * elevation / 180.0D;
float cosT = (float) Math.cos(theta);
float sinT = (float) Math.sin(theta);
float cosP = (float) Math.cos(phi);
float sinP = (float) Math.sin(phi);
float cosTcosP = cosT * cosP;
float cosTsinP = cosT * sinP;
float sinTcosP = sinT * cosP;
float sinTsinP = sinT * sinP;
float near = 6.0F;
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for (int i = 0; i < tiles.size(); i++) {
Point[] points = new Point[vertices.length];
for (int j = 0; j < points.length; j++) {
float x0 = -(tiles.get(i).getX() + xmod + vertices[j]
.getX());
float y0 = (tiles.get(i).getY() + ymod + vertices[j].getY());
float z0 = -(tiles.get(i).getZ() + zmod + vertices[j]
.getZ());
float x1 = cosT * x0 + sinT * z0;
float y1 = -sinTsinP * x0 + cosP * y0 + cosTsinP * z0;
float z1 = cosTcosP * z0 - sinTcosP * x0 - sinP * y0;
if (z1 + near > 0) {
x1 = x1 * near / (z1 + near);
y1 = y1 * near / (z1 + near);
points[j] = new Point((int) (Math.max(getWidth(),
getHeight()) / 2 - (Math.max(getWidth(),
getHeight()) / near) * x1), (int) (Math.max(
getWidth(), getHeight()) / 2 - (Math.max(
getWidth(), getHeight()) / near) * y1));
}
}
}
}
How would I go about moving the rotational point without actually modifying the xmod, ymod and zmod (these are used for movements like jumping, walking, running, crouching... etc)
I know how to figure out how to get the new x, y and z positions, I just don't know how to apply them; if I add them to the mods, it creates a weird loop-d-loop. If I add them to the x1, y1, z1's it doesn't cover the z not rotating from the perspective.
To change the rotation point, you effectively need three transforms:
Translate the coordinate system so that the rotation point becomes the origin.
Perform a rotation around the origin
Translate the coordinate system back again.
This can be factored a number of ways, but that's the basic priniciple: translate->rotate->translate.
The way you "move the rotation point" of an object is by translating the object so that the rotation point is at the origin; do the rotation; then translate the object back. All of this is done in memory, between frames - the user never actually sees the object moving to the origin and back.
By the way, all this stuff is significantly easier if you understand vectors and matrix transformations - as you've seen yourself, without them the code can get out of hand.
Using vectors/matrices, all your code above could be reduced to only a few lines.
There is a mouseMove()method that makes the pointer jump to that location. I want to be able to make the mouse move smoothly throughout the screen. I need to write a method named mouseGLide() which takes a start x, start y, end x, end y, the total time the gliding should take, and the number of steps to make during the glide. It should animate the mouse pointer by moving from (start x, start y) to (end x, start y) in n steps. The total glide should take t milliseconds.
I don't know how to get started can anyone help me get started on this? Can anyone just tell me what steps I need to do in order to make this problem work.
To start off, let's just write out an empty method where the parameters are as you defined in your question.
public void mouseGlide(int x1, int y1, int x2, int y2, int t, int n) {
}
Next, let's create a Robot object and also calculate 3 pieces of information that'll help your future calculations. Don't forget to catch the exception from instantiating Robot.
Robot r = new Robot();
double dx = (x2 - x1) / ((double) n);
double dy = (y2 - y1) / ((double) n);
double dt = t / ((double) n);
dx represents the difference in your mouse's x coordinate everytime it moves while gliding. Basically it's the total move distance divided into n steps. Same thing with dy except with the y coordinate. dt is the total glide time divided into n steps.
Finally, construct a loop that executes n times, each time moving the mouse closer to the final location (taking steps of (dx, dy)). Make the thread sleep for dt milliseconds during each execution. The larger your n is, the smoother the glide will look.
Final result:
public void mouseGlide(int x1, int y1, int x2, int y2, int t, int n) {
try {
Robot r = new Robot();
double dx = (x2 - x1) / ((double) n);
double dy = (y2 - y1) / ((double) n);
double dt = t / ((double) n);
for (int step = 1; step <= n; step++) {
Thread.sleep((int) dt);
r.mouseMove((int) (x1 + dx * step), (int) (y1 + dy * step));
}
} catch (AWTException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
For all those who have been struggling with the programming as I did before, this is how you implement this method and use it correctly:
public class gliding_the_mouse {
public void mouseGlide(int x1, int y1, int x2, int y2, int t, int n) {
try {
Robot r = new Robot();
double dx = (x2 - x1) / ((double) n);
double dy = (y2 - y1) / ((double) n);
double dt = t / ((double) n);
for (int step = 1; step <= n; step++) {
Thread.sleep((int) dt);
r.mouseMove((int) (x1 + dx * step), (int) (y1 + dy * step));
}
} catch (AWTException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main (String[] args) { // program initialization
gliding_the_mouse x = new gliding_the_mouse(); // we declare what are we are going to use
x.mouseGlide(400,500,700,700,5000,10000); // the smaller the time value, the faster the mouse glides.
}
}
Using no. of steps may not be ideal in every situation. Below is the code which moves the mouse by some given pixel amount.
The idea of this logic, is we provide the start point and end point and:
we get the straight line equation for the two points
we identify the points (pixel jump) along the line
we move the mouse to each idenfied point on the line using a very minimal delay to replicate the general mouse movement.
/**
* Moves mouse from (x1,y1) to (x2, y2).
*
* #param x1 initial x
* #param y1 initial y
* #param x2 x
* #param y2 y
*/
private static void moveTo(final int x1, final int y1, final int x2, final int y2) {
int pixelJump = 10;
final double xSqu = (x2 - x1) * (x2 - x1);
final double ySqu = (y2 - y1) * (y2 - y1);
final double lineLength = Math.sqrt(xSqu + ySqu);
double dt = 0;
while (dt < lineLength) {
dt += pixelJump;
final double t = dt / lineLength;
final int dx = (int) ((1 - t) * x1 + t * x2);
final int dy = (int) ((1 - t) * y1 + t * y2);
r.mouseMove(dx, dy);
r.delay(1); // Increase this number if you need to delay the mouse movement
}
r.mouseMove(x2, y2);
}