I've spent almost a week to figure this out, but I still cant find a solution.
The language is Java.
Bellow is my current formula for rotating a random point:
rotatedx = (int) ((x - centerx)*Math.cos(theta) - (y - centery)*Math.sin(theta) + centerx);
rotatedy = (int) ((y - centery)*Math.cos(theta) + (y - centery)*Math.sin(theta) + centery);
Bellow is how I calculate theta (trying to make the point rotate when the user moves his/her mouse):
double dx = mousex - centerx;
double dy = mousey - centery;
theta = Math.atan2(dy, dx);
The formula works, sort of.
int onex = 100, oney = 100;
int twox = 150, twoy = 100;
int threex = 100, threey = 150;
int fourx = 150, foury = 150;
int centerx = 125, centery = 125;
onex = (int) ((onex - centerx)*Math.cos(theta) - (oney - centery)*Math.sin(theta) + centerx);
oney = (int) ((oney - centery)*Math.cos(theta) + (oney - centery)*Math.sin(theta) + centery);
twox = (int) ((twox - centerx)*Math.cos(theta) - (twoy - centery)*Math.sin(theta) + centerx);
twoy = (int) ((twoy - centery)*Math.cos(theta) + (twoy - centery)*Math.sin(theta) + centery);
threex = (int) ((threex - centerx)*Math.cos(theta) - (threey - centery)*Math.sin(theta) + centerx);
threey = (int) ((threey - centery)*Math.cos(theta) + (threey - centery)*Math.sin(theta) + centery);
fourx = (int) ((fourx - centerx)*Math.cos(theta) - (foury - centery)*Math.sin(theta) + centerx);
foury = (int) ((foury - centery)*Math.cos(theta) + (foury - centery)*Math.sin(theta) + centery);
But it only works when all point's (including the center point) X equals to it's Y, so only point one and four works. Point two and three were in a weird motion, moving back and forth passing through the center point.
Perhaps Someone could tell me how to rotate a point around another point when the user move's the mouse? or how do I convert the Theta value into degrees and rotate the point with degrees instead of theta?
Its my first time posting on this site.
You have a typo in rotating formula for rotatedy, you use (y - centery) in both expressions. There should be x in the second term:
rotatedy = (int) ((y - centery)*Math.cos(theta) + (x - centerx)*Math.sin(theta) + centery);
The same is true for oney, twoy, threey, foury.
The problem was solved, I was being stupid.
Instead of Transforming the original point's X and Y,
onex = (int) ((onex - centerx)*Math.cos(theta) - (oney - centery)*Math.sin(theta) +
centerx);
oney = (int) ((oney - centery)*Math.cos(theta) + (oney - centery)*Math.sin(theta) +
centery);
I should declare a new point, and my formula was incorrect:
newonex = (int) ((onex - centerx)*Math.cos(theta) - (oney - centery)*Math.sin(theta) +
centerx);
newoney = (int) ((onex - centerx)*Math.cos(theta) + (oney - centery)*Math.sin(theta) +
centery);
Im trying to work out how to smooth a big list of longitude latitude points i currently draw a line from point to point and interpolate each point in-between but as i change direction it shows a sharp turn where i would like to smooth this out to a neat curve, but i dont know exactly where the turns are so i need an algorithm to smooth over an average of points.
I have done some research into this already and had a look at the Bezier curve but does not work as i expect, i took the implementation that i found here.
http://sourcecodesforfree.blogspot.co.uk/2013/05/33-bezier-curve.html
I cant really find much documentation on how the Bezier Curve algorithm works, or at least not fully understanding how it works.
function bspline(lats, lons) {
var i, t, ax, ay, bx, by, cx, cy, dx, dy, lat, lon, points;
points = [];
// For every point
for (i = 2; i < lats.length - 2; i++) {
for (t = 0; t < 1; t += 0.2) {
ax = (-lats[i - 2] + 3 * lats[i - 1] - 3 * lats[i] + lats[i + 1]) / 6;
ay = (-lons[i - 2] + 3 * lons[i - 1] - 3 * lons[i] + lons[i + 1]) / 6;
bx = (lats[i - 2] - 2 * lats[i - 1] + lats[i]) / 2;
by = (lons[i - 2] - 2 * lons[i - 1] + lons[i]) / 2;
cx = (-lats[i - 2] + lats[i]) / 2;
cy = (-lons[i - 2] + lons[i]) / 2;
dx = (lats[i - 2] + 4 * lats[i - 1] + lats[i]) / 6;
dy = (lons[i - 2] + 4 * lons[i - 1] + lons[i]) / 6;
lat = ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx;
lon = ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy;
points.push(new google.maps.LatLng(lat, lon));
}
}
return points;
}
Above code in JavaScript else logic are same just change bit variables and method as JAVA then check
Or
please find an Algorithm from this link en.wikipedia.org/wiki/Interpolation#Linear_interpolation
I have various entities in my game that have hit-boxes defined by Vector array's,
one of my entities rotates slowly to follow the player's movements so naturally I need the hit-box to rotate too.
My code results in warped and distorted lines as I draw each vertex to the screen. My entites are 64 x 64 in size so + 32 indicates the center of the object.
public void rotateVertices(Vector2[] vertices, double angle) {
double cos = Math.cos(angle);
double sin = Math.sin(angle);
for(int i = 0; i < vertices.length; i++){
Vector2 v = vertices[i];
vertices[i].x = ((v.x - (x + 32)) * cos - (v.y - (y + 32)) * sin) + (x + 32);
vertices[i].y = ((v.x - (x + 32)) * sin + (v.y - (y + 32)) * cos) + (y + 32);
}
}
my constructor:
public EnemyTriBall(Handler handler, float x, float y) {
super(handler, x, y, 3, 6);
vertices[0] = new Vector2(x + 25, y + 13);
vertices[1] = new Vector2(x + 64, y + 33);
vertices[2] = new Vector2(x + 25, y + 53);
}
Here:
Vector2 v = vertices[i];
You don't make a copy of the old vector, you just reference vectices[i]. So when you do this:
vertices[i].x = ((v.x - (x + 32)) * cos - (v.y - (y + 32)) * sin) + (x + 32);
you modify x of of the original vector. Then in the next line:
vertices[i].y = ((v.x - (x + 32)) * sin + (v.y - (y + 32)) * cos) + (y + 32);
You use old v.y but new v.x which gives you weird results. The easiest fix would be to get x and y and use them instead:
float vx = vertices[i].x;
float vy = vertices[i].y;
vertices[i].x = ((vx - (x + 32)) * cos - (vy - (y + 32)) * sin) + (x + 32);
vertices[i].y = ((vx - (x + 32)) * sin + (vy - (y + 32)) * cos) + (y + 32);
There might be other issues, I did not check the formulas but I'd start with this one.
I wrote a program which draws a circle colored thanks to a chromatic gradation, using the Andres' algorithm. Here is an execution's result :
Now I would want to shift this gradation. For example, I would want the red to begin at the right of the circle. Or at 70°. Etc.
So I have a shift, in radians. And I must use it in my Andres' algorithm.
But I don't understand how. However, I see two ways to do that :
Either I change the Andres' algorithm, I mean I change the coordinates of each pixel of each octant (= I change the circle's drawing) ;
Or I really shift the gradation and not the drawing.
I would prefer the solution number one. And I know it will make use of trigonometry. But my skills are too bad and I really need your help please...
Here is the source of my Andres' implementation. If you need it, I can also show you the code of my gradation-function. Thank you in advance.
NB : the most important part is just below the line while (y >= x) (id est : the octants' coordinates).
case "Andres' algorithm":
w = 2 * Math.PI;
for(double current_thickness = 0; current_thickness < this.thickness; current_thickness++) {
x = 0;
y = (int) (radius + current_thickness);
double d = radius + current_thickness - 1;
while (y >= x) {
double octant_1_x = x0 + x, octant_1_y = y0 + y;
double octant_2_x = x0 + y, octant_2_y = y0 + x;
double octant_3_x = x0 - x, octant_3_y = y0 + y;
double octant_4_x = x0 - y, octant_4_y = y0 + x;
double octant_5_x = x0 + x, octant_5_y = y0 - y;
double octant_6_x = x0 + y, octant_6_y = y0 - x;
double octant_7_x = x0 - x, octant_7_y = y0 - y;
double octant_8_x = x0 - y, octant_8_y = y0 - x;
max_counter++;
double[] rgb_gradation_octant_1 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_1_y - y0, octant_1_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_1_x, octant_1_y, Color.color(rgb_gradation_octant_1[0], rgb_gradation_octant_1[1], rgb_gradation_octant_1[2]))); // octant n°1
double[] rgb_gradation_octant_2 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_2_y - y0, octant_2_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_2_x, octant_2_y, Color.color(rgb_gradation_octant_2[0], rgb_gradation_octant_2[1], rgb_gradation_octant_2[2])));
double[] rgb_gradation_octant_3 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_3_y - y0, octant_3_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_3_x, octant_3_y, Color.color(rgb_gradation_octant_3[0], rgb_gradation_octant_3[1], rgb_gradation_octant_3[2])));
double[] rgb_gradation_octant_4 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_4_y - y0, octant_4_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_4_x, octant_4_y, Color.color(rgb_gradation_octant_4[0], rgb_gradation_octant_4[1], rgb_gradation_octant_4[2]))); // octant n°4
double[] rgb_gradation_octant_5 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_5_y-y0, octant_5_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_5_x, octant_5_y, Color.color(rgb_gradation_octant_5[0], rgb_gradation_octant_5[1], rgb_gradation_octant_5[2]))); // octant n°5
double[] rgb_gradation_octant_6 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_6_y-y0, octant_6_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_6_x, octant_6_y, Color.color(rgb_gradation_octant_6[0], rgb_gradation_octant_6[1], rgb_gradation_octant_6[2])));
double[] rgb_gradation_octant_7 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_7_y-y0, octant_7_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_7_x, octant_7_y, Color.color(rgb_gradation_octant_7[0], rgb_gradation_octant_7[1], rgb_gradation_octant_7[2])));
double[] rgb_gradation_octant_8 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_8_y-y0, octant_8_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_8_x, octant_8_y, Color.color(rgb_gradation_octant_8[0], rgb_gradation_octant_8[1], rgb_gradation_octant_8[2]))); // octant n°8
if (d >= 2 * x) {
d -= 2 * x + 1;
x++;
} else if (d < 2 * (radius + thickness - y)) {
d += 2 * y - 1;
y--;
} else {
d += 2 * (y - x - 1);
y--;
x++;
}
}
}
gui.getImageAnimation().setMax(max_counter*8);
break;
In 2 dimensions, you can achieve rotation with the following formulas:
x' = x cos f - y sin f
y' = y cos f + x sin f
Instead of repeating the transformation in every Pixel instantiation, you could write a helper that creates a rotated pixel and returns it. I meant something like:
Pixel rotated_pixel (double x, double y, Pixel rotation_center, Color color, double angle) {
double x0 = rotation_center.x,
y0 = rotation_center.y, // Oh god I hope I'm not also wrong about the field names now
sinw = Math.sin(angle), cosw = Math.cos(angle),
x_rot = x0 + (x-x0)*cosw - (y-y0)*sinw,
y_rot = y0 + (y-y0)*cosw + (x-x0)*sinw;
return new Pixel(x_rot, y_rot, color); // or smth
}
Then you can use it like updates.add(rotated_pixel(x,y,whatever));
I'm sorry that I cannot check the validity of this code; I don't currently have access to a computer with Java.
Thanks to #kubuzetto , the code below allows me to draw a circle taking account of a shift, expressed in radians. I mean its drawing begins at a certain angle (which is the shift). I still use Andres.
The only new problem with this solution is that gaps appear when the circle is rotated (ie. : when there is a shift).
Indeed :
http://imgur.com/BcAsP9n
I thought it was because of a cast which would have decreased the precision of the coordinates, but it's not the case.
If someone see why there is this problem, it would be fine !
/**
* Constructs a Pixel taking account of a shift and near the position (x0 ; y0)
* #param x
* #param y
* #param color
* #param angle
* #param x0
* #param y0
*/
Pixel(double x, double y, Color color, double angle, double x0, double y0) {
this.x = (int) (x0 + (x-x0) * Math.cos(angle) - (y-y0) * Math.sin(angle));
this.y = (int) (y0 + (y-y0) * Math.cos(angle) + (x-x0) * Math.sin(angle));
this.color = color;
}
And the Andres' algorithm :
case "Andres' algorithm":
w = 2 * Math.PI;
for(double current_thickness = 0; current_thickness < this.thickness; current_thickness++) {
x = 0;
y = (int) (radius + current_thickness);
double d = radius + current_thickness - 1;
while (y >= x) {
double octant_1_x = x0 + x, octant_1_y = y0 + y;
double octant_2_x = x0 + y, octant_2_y = y0 + x;
double octant_3_x = x0 - x, octant_3_y = y0 + y;
double octant_4_x = x0 - y, octant_4_y = y0 + x;
double octant_5_x = x0 + x, octant_5_y = y0 - y;
double octant_6_x = x0 + y, octant_6_y = y0 - x;
double octant_7_x = x0 - x, octant_7_y = y0 - y;
double octant_8_x = x0 - y, octant_8_y = y0 - x;
max_counter++;
double[] rgb_gradation_octant_1 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_1_y - y0, octant_1_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_1_x, octant_1_y,
Color.color(rgb_gradation_octant_1[0], rgb_gradation_octant_1[1], rgb_gradation_octant_1[2]),
circle_gradation_beginning, x0, y0)); // octant n°1
double[] rgb_gradation_octant_2 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_2_y - y0, octant_2_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_2_x, octant_2_y,
Color.color(rgb_gradation_octant_2[0], rgb_gradation_octant_2[1], rgb_gradation_octant_2[2]),
circle_gradation_beginning, x0, y0));
double[] rgb_gradation_octant_3 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_3_y - y0, octant_3_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_3_x, octant_3_y,
Color.color(rgb_gradation_octant_3[0], rgb_gradation_octant_3[1], rgb_gradation_octant_3[2]),
circle_gradation_beginning, x0, y0));
double[] rgb_gradation_octant_4 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_4_y - y0, octant_4_x - x0) + Math.PI, w);
updates.add(new Pixel(octant_4_x, octant_4_y,
Color.color(rgb_gradation_octant_4[0], rgb_gradation_octant_4[1], rgb_gradation_octant_4[2]),
circle_gradation_beginning, x0, y0)); // octant n°4
double[] rgb_gradation_octant_5 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_5_y-y0, octant_5_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_5_x, octant_5_y,
Color.color(rgb_gradation_octant_5[0], rgb_gradation_octant_5[1], rgb_gradation_octant_5[2]),
circle_gradation_beginning, x0, y0)); // octant n°5
double[] rgb_gradation_octant_6 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_6_y-y0, octant_6_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_6_x, octant_6_y,
Color.color(rgb_gradation_octant_6[0], rgb_gradation_octant_6[1], rgb_gradation_octant_6[2]),
circle_gradation_beginning, x0, y0));
double[] rgb_gradation_octant_7 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_7_y-y0, octant_7_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_7_x, octant_7_y,
Color.color(rgb_gradation_octant_7[0], rgb_gradation_octant_7[1], rgb_gradation_octant_7[2]),
circle_gradation_beginning, x0, y0));
double[] rgb_gradation_octant_8 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_8_y-y0, octant_8_x-x0) + Math.PI, w);
updates.add(new Pixel(octant_8_x, octant_8_y,
Color.color(rgb_gradation_octant_8[0], rgb_gradation_octant_8[1], rgb_gradation_octant_8[2]),
circle_gradation_beginning, x0, y0)); // octant n°8
if (d >= 2 * x) {
d -= 2 * x + 1;
x++;
} else if (d < 2 * (radius + thickness - y)) {
d += 2 * y - 1;
y--;
} else {
d += 2 * (y - x - 1);
y--;
x++;
}
}
}
gui.getImageAnimation().setMax(max_counter*8);
break;