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
Related
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);
I'm trying to draw line over all circle surface, my current shape look like:
My wrong attempt:
for (int i = 0; i < 24; i++) {
g.drawLine(xCenter - clockRadius + i , yCenter - clockRadius + i, xCenter - clockRadius + i + 5,
yCenter - clockRadius + i + 5);
}
I'm trying to draw a full clock :
You are looking for cosinus and sinus.
Your clock is a circle, and you can easily translate your steps into degrees on that circle. If you want to have 24 steps, 12 would be 180° (or π) and 24 would be 360°, or 2π. So to get the correct angles for each index, just devide 2π (360°) by 24 and multiply it by the current index. Then feed that resulting angle to the cos and sin functions, which give you the x and y coordinates respectively:
double x = Math.cos(2 * Math.PI / 24 * i);
double y = Math.sin(2 * Math.PI / 24 * i);
Of course you can optimize the 2 and the 24 into one constant that you define somewhere and then use in your code.
I suspect that you want to draw small segments - ticks, centered at circumference and directed from the circle center. In this case use trigonometry alike hour hands drawing.
for (int i = 0; i < 24; i++) {
double ang = i * Math.Pi / 12;
g.drawLine((int) (xCenter + (clockRadius - 5) * Math.Cos(ang)),
(int) (yCenter + (clockRadius - 5) * Math.Sin(ang)),
(int) (xCenter + (clockRadius + 5) * Math.Cos(ang)),
(int) (yCenter + (clockRadius + 5) * Math.Sin(ang)));
}
You need to calculate points over 360 degree not just 24, so you have the radius and angel rotation (angel rotation from 0 to 360) to get the proper point of (x,y) we need to multiply sin or cos of angel with radius.
for (int i = 0; i < 360; i++) {
int x = (int) (clockRadius * Math.cos(i)) + xCenter;
int y = (int) (clockRadius * Math.sin(i)) + yCenter;
g.drawLine(x, y, x + 5, y + 5);
}
Note: for better result you may need to develop two loops, one for right (180) part and another for left (180) part.
Edit: to get the right direction you need to check for angel e.g:
int xV = 0, yV = 0;
if (i <= 90){
xV = 5;
yV = 5;
}
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 have two equations (Distance and slope of a line formula)
d = sqrt( (x2 - x1)^2 + (y2 - y1)^2 )
m = (y2 - y1) / (x2 - x1)
Known: d, m, x1, y1
Unknown: x2, y2
The problem is the distance equation isn't linear...
Is there a way to code this in java (using Android compatible libraries) to solve? I tried doing simple guessing but it is too slow.
Thanks
EDIT: Code for triangle
Point p1 = new Point();
Point p2 = new Point();
projection.toPixels(gp1, p1);
projection.toPixels(gp2, p2);
Point p3 = new Point();
double slope = (p2.y - p1.y) / (p2.x - p1.x);
double x = 0;
if (p2.y - p1.y >= 0 && p2.x - p1.x >= 0) {
x = - Math.sqrt(600 / (1 + slope*slope)) + p2.x;
} else if (p2.y - p1.y >= 0 && p2.x - p1.x < 0) {
x = Math.sqrt(600 / (1 + slope*slope)) + p2.x;
} else if (p2.y - p1.y < 0 && p2.x - p1.x >= 0) {
x = - Math.sqrt(600 / (1 + slope*slope)) + p2.x;
} else if (p2.y - p1.y < 0 && p2.x - p1.x < 0) {
x = Math.sqrt(600 / (1 + slope*slope)) + p2.x;
}
double y = -slope*p2.x + slope*x + p2.y;
p3.set((int) x, (int) y);
double inverseSlope = 0;
if (slope == 0) {
inverseSlope = Double.MAX_VALUE;
} else {
inverseSlope = -1 / slope;
}
x = -Math.sqrt(300 / (1 + inverseSlope*inverseSlope)) + p3.x;
y = -Math.sqrt(300 / (1 + inverseSlope*inverseSlope))*inverseSlope + p3.y;
Point p4 = new Point();
p4.set((int) x, (int) y);
x = Math.sqrt(300 / (1 + inverseSlope*inverseSlope)) + p3.x;
y = Math.sqrt(300 / (1 + inverseSlope*inverseSlope))*inverseSlope + p3.y;
Point p5 = new Point();
p5.set((int)x, (int) y);
Path path = new Path();
path.moveTo(p2.x, p2.y);
path.lineTo(p4.x, p4.y);
path.moveTo(p4.x, p4.y);
path.lineTo(p5.x, p5.y);
path.moveTo(p5.x, p5.y);
path.lineTo(p2.x, p2.y);
path.moveTo(p2.x, p2.y);
canvas.drawPath(path, mPaint);
It appears it is being caused by slope is always an integer so when it is < 1 it is 0 which is not good...
Please review the algebra below:
Define
x = x2-x1
and
y = y2-y1
Then
m * x = y
and
d^2 = x^2 + m^2 * x^2 = (1 + m^2) * x^2
Therefore
x = sqrt(d^2 / (1 + m^2))
then
x2 - x1 = sqrt(d^2 / (1 + m^2))
so
x2 = sqrt(d^2 / (1 + m^2) + x1
Similarly
y = sqrt(d^2 / (1 + m^2)) * m
y2 = sqrt(d^2 / (1 + m^2)) * m + y1
So the answer is:
x2 = sqrt(d^2 / (1 + m^2)) + x1
y2 = sqrt(d^2 / (1 + m^2)) * m + y1
the "library" you're looking for is called mathematics :)
you can ask wolfram alpha:
http://www.wolframalpha.com/input/?i=solve+d+%3D+sqrt%28+%28x2+-+x1%29%5E2+%2B+%28y2+-+y1%29%5E2+%29%2C+m+%3D+%28y2+-+y1%29+%2F+%28x2+-+x1%29+over+the+reals
(don't ask me why it knows x2 and y2 are interresting)
you can do such things by hand, but be very careful not to drop signs. even though this stuff is taught in school they have little respect for detail. note that in this case there are two possible solutions and you need ensure that d > 0 in all cases!
I have written this code but it doesn't compute ((((bY - aY) / (maxX - minX)) * (p.getX() - minX)) + aY) for me.please help me.
a part of code :(I have four points which aY means the "y" of point "a")
int aY = minXY[0];
int bY = maxXY[0];
int cY = minXY[minXY.length - 1];
int dY = maxXY[maxXY.length - 1];
for (Point p : pointList) {
if ((p.getY() > ((((bY - aY) / (maxX - minX)) * (p.getX() - minX)) + aY)) && (p.getY() < ((((dY - cY) / (maxX - minX)) * (p.getX() - minX)) + cY))) {
list.add(p);
} else if (p.getY() < ((((bY - aY) / (maxX - minX)) * (p.getX() - minX)) + aY)) {
upperHull.add(p);
int m = ((((bY - aY) / (maxX - minX)) * (p.getX() - minX)) + aY);
System.out.println(m);
} else if (p.getY() > ((((dY - cY) / (maxX - minX)) * (p.getX() - minX)) + cY)) {
lowerHull.add(p);
}
}
the output will be an integer which is the "y" of point "a".
totally ,my specific arithmetic statement doesn't work.please help me why?also I have checked each value in the arithmetic statement and they are OK but can not compute the result for me.
specific arithmetic statement : ((((bY - aY) / (maxX - minX)) * (p.getX() - minX)) + aY)
It would be more helpful if you explained what result you are getting and what you don't like about it. "can not compute the result" implies you are getting an exception of some kind, but I don't think that's what you mean.
What you probably mean is that the result it is getting is not what you expect, and the most likely reason for this is that all your variables are int so it is doing integer arithmetic, but you probably want to get floating-point results from your divisions.
I suggest changing your local variables to float or double, so the ints will be automatically converted before doing the arithmetic.
Also, it looks like you have two complex arithmetic expressions in there multiple times. I would calculate them once and assign them to local variables (within the loop, before the if).