Convert standard 360-degree to atan2 - math

I need to reverse calculation of standard 360 angle to atan2.
It's my standard angle calulation
Standard angle = (int) Math.toDegrees(Math.atan2(y,x));
if(angle < 0)
angle += 360;
I need Math.atan2 value from angle how to achieve that.

To translate degrees range 0..360 into radians range -Pi..Pi:
if(angle > 180)
angle -= 360;
angle_radians = Math.toRadians(angle);
If your angle may be beyond standard range (you did not mentioned this), use integer modulo instead of loops
angle = angle % 360
(check how modulo operator works with negative numbers in your language)

Though your question is not very clear, it seems that you want to retrieve the angle before the statement
if (angle < 0)
angle += 360;
As atan2 returns a value in the range [-π,π), i.e. [-180°,180°), the subrange [-180°,0°) is mapped to [180°,360°). Then you invert with
if (angle >= 180°)
angle-= 360;
You also need to convert back to radians.

A general solution with O(1) performance:
double generalModulus(double value, double modulus, double offset) {
return value - Math.floor((value-offset)/modulus) * modulus + offset;
}
double normalizeAngleDegrees(double angleInDegrees, double offset) {
return generalModulus(angleInDegrees, 360.0, offset);
}
double normalizeAngleRadians(double angleInRadians, double offset) {
return generalModulus(angleInRadians, 2.0*Math.PI, offset);
}
To use:
double normDeg = normalizeAngleDegrees(angle, -180); // produces angle in range [-180, 180)
double normRad = normalizeAngleRadians(angle, 0); // produces angle in range [0, 2*Pi)

My Own answer
int normalizeAngle(int angle)
{
int newAngle = angle;
while (newAngle <= -180) newAngle += 360;
while (newAngle > 180) newAngle -= 360;
return newAngle;
}

Related

Radius of a box in a given direction

Let's say I have an axis-aligned box. I also have a location outside that box.
How do I get the point on the boundaries of the box that is along the line from the center of the box to that point? (And thus, know how far the box extends in that direction).
EDIT: preferably, if the point is inside the box, it should just return the point... but that's something I could easily calculate myself.
2D diagram (Though the answer will preferably work in 3D as well):
point3d getIntersection(point3d topfrontleft, point3d backbottomright, point3d externpt)
{
//find the middle
point3d middle(topfrontleft/2+backbottomright/2);
//slide box and source as if the "middle" was at the origin
topfrontleft -= middle;
backbottomright-= middle;
externpt-= middle;
//scale source as if the box is the unit square
externpt/= topfrontleft;
//find the largest magnitude of the source offset
point3d mag = abs(externpt);
auto max = std::max(mag.x,std::max(mag.y,mag.z));
//if it's inside the box, don't scale
if (max < 1)
max = 1;
//scale the source so that it touches the box
externpt/= max;
//then scale and slide that touching point back to original coordinates
externpt= externpt* topfrontleft + middle;
return externpt;
}
http://coliru.stacked-crooked.com/a/9d9504964bc650bb
I'm not experienced with 3d math, so there's probably faster and more effective ways. No idea.
As a bonus, this algorithm doesn't make any reference to the number of dimensions except for finding the largest magnitude, so should work in both 2d, 3d, and any other theoretical number of dimensions.
Here is some code that does what I said in comments modified for rectangular boxes.
#include <stdio.h>
#include <math.h>
// Find intersection p between line A->B and box.
// Point A must be the box center.
// The box is [x_left, y_bottom, x_right, y_top].
void find_box_intersect(double *box, double *a, double *b, double *p)
{
double dx = b[0] - a[0];
double dy = b[1] - a[1];
if (fabs(dx * (box[3] - box[1])) > fabs(dy * (box[2] - box[0]))) {
p[0] = dx > 0 ? box[2] : box[0];
p[1] = a[1] + dy * (p[0] - a[0]) / dx;
} else {
p[1] = dy > 0 ? box[3] : box[1];
p[0] = a[0] + dx * (p[1] - a[1]) / dy;
}
}
int main(void) {
double box[] = { 1, 2,
2, 4 };
double p[2], a[] = { 0.5 * (box[0] + box[2]),
0.5 * (box[1] + box[3]) };
int i, n = 16;
for (i = 0; i < n; i++) {
double theta = 2 * 3.14159 * i / n;
double b[] = { a[0] + cos(theta), a[1] + sin(theta) };
find_box_intersect(box, a, b, p);
printf("%.2f, %.2f\n", p[0], p[1]);
}
return 0;
}
The 3d generalization of this is straightforward. Rather than the if statement that determines only 2 cases, there will be a 3 case if-else chain that determines 3: left-right, top-bottom, front-back.
Output:
2.00, 3.00
2.00, 3.21
2.00, 3.50
1.91, 4.00
1.50, 4.00
1.09, 4.00
1.00, 3.50
1.00, 3.21
1.00, 3.00
1.00, 2.79
1.00, 2.50
1.09, 2.00
1.50, 2.00
1.91, 2.00
2.00, 2.50
2.00, 2.79
Short answer: Intersect the line with the (right) border of the box.
Longer answer:
x is easy: It's at the right border of the box.
for y, solve this: y/line_height = (line_width - box_width/2) / line_width
then add the y of the line lower point
This is assuming the line intersects the right border, as in your picture.
To figure which border the line intersects, compare the ratio of line_height/line_width, and the signs, to the ratio of box_height/box_width.
If the box is square and you're only interested in the radius, and not the intersection point, you can throw away the signs of line_width and line_height, sort them, and just solve one case.
If the box is not square, you can still throw away the signs, but need to compare the ratios to pick one of two remaining cases (in 2D).
Assuming that you know the length and width of the rect, if the angle is pointing left or right, then x is known, so you only need to solve for y (r * sin(angle)); if the angle is pointing up or down, then y is known so you solve for x (r * cos(angle)).
// where the center of the rect = 0, 0 and angles are in degrees 0..360
// determine the 45's first
if (angle in (45, 135, 225, 315)) {
return { x:cos(angle) * (width / 2), y:sin(angle) * (height / 2) };
}
if (angle < 45 || angle > 315) {
// pointing right
return { x:(width / 2), y:sin(angle) * (height / 2) };
}
if (angle > 45 && angle < 135) {
// pointing up
return { x:cos(angle) * (width / 2), y:(height / 2) };
}
if (angle > 135 && angle < 225) {
// pointing left
return { x:(width / -2), y:sin(angle) * (height / 2) };
}
if (angle > 225 && angle < 315) {
// pointing down
return { x:cos( angle ) * (width / 2), y:(height / -2) };
}
There are undoubtedly more elegant mathematical solutions to this problem, but this one works for me--understandable, testable, etc.

correct glsl affine texture mapping

i'm trying to code correct 2D affine texture mapping in GLSL.
Explanation:
...NONE of this images is correct for my purposes. Right (labeled Correct) has perspective correction which i do not want. So this: Getting to know the Q texture coordinate solution (without further improvements) is not what I'm looking for.
I'd like to simply "stretch" texture inside quadrilateral, something like this:
but composed from two triangles. Any advice (GLSL) please?
This works well as long as you have a trapezoid, and its parallel edges are aligned with one of the local axes. I recommend playing around with my Unity package.
GLSL:
varying vec2 shiftedPosition, width_height;
#ifdef VERTEX
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
shiftedPosition = gl_MultiTexCoord0.xy; // left and bottom edges zeroed.
width_height = gl_MultiTexCoord1.xy;
}
#endif
#ifdef FRAGMENT
uniform sampler2D _MainTex;
void main() {
gl_FragColor = texture2D(_MainTex, shiftedPosition / width_height);
}
#endif
C#:
// Zero out the left and bottom edges,
// leaving a right trapezoid with two sides on the axes and a vertex at the origin.
var shiftedPositions = new Vector2[] {
Vector2.zero,
new Vector2(0, vertices[1].y - vertices[0].y),
new Vector2(vertices[2].x - vertices[1].x, vertices[2].y - vertices[3].y),
new Vector2(vertices[3].x - vertices[0].x, 0)
};
mesh.uv = shiftedPositions;
var widths_heights = new Vector2[4];
widths_heights[0].x = widths_heights[3].x = shiftedPositions[3].x;
widths_heights[1].x = widths_heights[2].x = shiftedPositions[2].x;
widths_heights[0].y = widths_heights[1].y = shiftedPositions[1].y;
widths_heights[2].y = widths_heights[3].y = shiftedPositions[2].y;
mesh.uv2 = widths_heights;
I recently managed to come up with a generic solution to this problem for any type of quadrilateral. The calculations and GLSL maybe of help. There's a working demo in java (that runs on Android), but is compact and readable and should be easily portable to unity or iOS: http://www.bitlush.com/posts/arbitrary-quadrilaterals-in-opengl-es-2-0
In case anyone's still interested, here's a C# implementation that takes a quad defined by the clockwise screen verts (x0,y0) (x1,y1) ... (x3,y3), an arbitrary pixel at (x,y) and calculates the u and v of that pixel. It was originally written to CPU-render an arbitrary quad to a texture, but it's easy enough to split the algorithm across CPU, Vertex and Pixel shaders; I've commented accordingly in the code.
float Ax, Bx, Cx, Dx, Ay, By, Cy, Dy, A, B, C;
//These are all uniforms for a given quad. Calculate on CPU.
Ax = (x3 - x0) - (x2 - x1);
Bx = (x0 - x1);
Cx = (x2 - x1);
Dx = x1;
Ay = (y3 - y0) - (y2 - y1);
By = (y0 - y1);
Cy = (y2 - y1);
Dy = y1;
float ByCx_plus_AyDx_minus_BxCy_minus_AxDy = (By * Cx) + (Ay * Dx) - (Bx * Cy) - (Ax * Dy);
float ByDx_minus_BxDy = (By * Dx) - (Bx * Dy);
A = (Ay*Cx)-(Ax*Cy);
//These must be calculated per-vertex, and passed through as interpolated values to the pixel-shader
B = (Ax * y) + ByCx_plus_AyDx_minus_BxCy_minus_AxDy - (Ay * x);
C = (Bx * y) + ByDx_minus_BxDy - (By * x);
//These must be calculated per-pixel using the interpolated B, C and x from the vertex shader along with some of the other uniforms.
u = ((-B) - Mathf.Sqrt((B*B-(4.0f*A*C))))/(A*2.0f);
v = (x - (u * Cx) - Dx)/((u*Ax)+Bx);
Tessellation solves this problem. Subdividing quad vertex adds hints to interpolate pixels.
Check out this link.
https://www.youtube.com/watch?v=8TleepxIORU&feature=youtu.be
I had similar question ( https://gamedev.stackexchange.com/questions/174857/mapping-a-texture-to-a-2d-quadrilateral/174871 ) , and at gamedev they suggested using imaginary Z coord, which I calculate using the following C code, which appears to be working in general case (not just trapezoids):
//usual euclidean distance
float distance(int ax, int ay, int bx, int by) {
int x = ax-bx;
int y = ay-by;
return sqrtf((float)(x*x + y*y));
}
void gfx_quad(gfx_t *dst //destination texture, we are rendering into
,gfx_t *src //source texture
,int *quad // quadrilateral vertices
)
{
int *v = quad; //quad vertices
float z = 20.0;
float top = distance(v[0],v[1],v[2],v[3]); //top
float bot = distance(v[4],v[5],v[6],v[7]); //bottom
float lft = distance(v[0],v[1],v[4],v[5]); //left
float rgt = distance(v[2],v[3],v[6],v[7]); //right
// By default all vertices lie on the screen plane
float az = 1.0;
float bz = 1.0;
float cz = 1.0;
float dz = 1.0;
// Move Z from screen, if based on distance ratios.
if (top<bot) {
az *= top/bot;
bz *= top/bot;
} else {
cz *= bot/top;
dz *= bot/top;
}
if (lft<rgt) {
az *= lft/rgt;
cz *= lft/rgt;
} else {
bz *= rgt/lft;
dz *= rgt/lft;
}
// draw our quad as two textured triangles
gfx_textured(dst, src
, v[0],v[1],az, v[2],v[3],bz, v[4],v[5],cz
, 0.0,0.0, 1.0,0.0, 0.0,1.0);
gfx_textured(dst, src
, v[2],v[3],bz, v[4],v[5],cz, v[6],v[7],dz
, 1.0,0.0, 0.0,1.0, 1.0,1.0);
}
I'm doing it in software to scale and rotate 2d sprites, and for OpenGL 3d app you will need to do it in pixel/fragment shader, unless you will be able to map these imaginary az,bz,cz,dz into your actual 3d space and use the usual pipeline. DMGregory gave exact code for OpenGL shaders: https://gamedev.stackexchange.com/questions/148082/how-can-i-fix-zig-zagging-uv-mapping-artifacts-on-a-generated-mesh-that-tapers
I came up with this issue as I was trying to implement a homography warping in OpenGL. Some of the solutions that I found relied on a notion of depth, but this was not feasible in my case since I am working on 2D coordinates.
I based my solution on this article, and it seems to work for all cases that I could try. I am leaving it here in case it is useful for someone else as I could not find something similar. The solution makes the following assumptions:
The vertex coordinates are the 4 points of a quad in Lower Right, Upper Right, Upper Left, Lower Left order.
The coordinates are given in OpenGL's reference system (range [-1, 1], with origin at bottom left corner).
std::vector<cv::Point2f> points;
// Convert points to homogeneous coordinates to simplify the problem.
Eigen::Vector3f p0(points[0].x, points[0].y, 1);
Eigen::Vector3f p1(points[1].x, points[1].y, 1);
Eigen::Vector3f p2(points[2].x, points[2].y, 1);
Eigen::Vector3f p3(points[3].x, points[3].y, 1);
// Compute the intersection point between the lines described by opposite vertices using cross products. Normalization is only required at the end.
// See https://leimao.github.io/blog/2D-Line-Mathematics-Homogeneous-Coordinates/ for a quick summary of this approach.
auto line1 = p2.cross(p0);
auto line2 = p3.cross(p1);
auto intersection = line1.cross(line2);
intersection = intersection / intersection(2);
// Compute distance to each point.
for (const auto &pt : points) {
auto distance = std::sqrt(std::pow(pt.x - intersection(0), 2) +
std::pow(pt.y - intersection(1), 2));
distances.push_back(distance);
}
// Assumes same order as above.
std::vector<cv::Point2f> texture_coords_unnormalized = {
{1.0f, 1.0f},
{1.0f, 0.0f},
{0.0f, 0.0f},
{0.0f, 1.0f}
};
std::vector<float> texture_coords;
for (int i = 0; i < texture_coords_unnormalized.size(); ++i) {
float u_i = texture_coords_unnormalized[i].x;
float v_i = texture_coords_unnormalized[i].y;
float d_i = distances.at(i);
float d_i_2 = distances.at((i + 2) % 4);
float scale = (d_i + d_i_2) / d_i_2;
texture_coords.push_back(u_i*scale);
texture_coords.push_back(v_i*scale);
texture_coords.push_back(scale);
}
Pass the texture coordinates to your shader (use vec3). Then:
gl_FragColor = vec4(texture2D(textureSampler, textureCoords.xy/textureCoords.z).rgb, 1.0);
thanks for answers, but after experimenting i found a solution.
two triangles on the left has uv (strq) according this and two triangles on the right are modifed version of this perspective correction.
Numbers and shader:
tri1 = [Vec2(-0.5, -1), Vec2(0.5, -1), Vec2(1, 1)]
tri2 = [Vec2(-0.5, -1), Vec2(1, 1), Vec2(-1, 1)]
d1 = length of top edge = 2
d2 = length of bottom edge = 1
tri1_uv = [Vec4(0, 0, 0, d2 / d1), Vec4(d2 / d1, 0, 0, d2 / d1), Vec4(1, 1, 0, 1)]
tri2_uv = [Vec4(0, 0, 0, d2 / d1), Vec4(1, 1, 0, 1), Vec4(0, 1, 0, 1)]
only right triangles are rendered using this glsl shader (on left is fixed pipeline):
void main()
{
gl_FragColor = texture2D(colormap, vec2(gl_TexCoord[0].x / glTexCoord[0].w, gl_TexCoord[0].y);
}
so.. only U is perspective and V is linear.

box2d difference between angles of two bodies

Working with box2d and cocos2d, I've calculated two vectors:
one is the vector pointing in the direction the car is travelling. (center of the vehicle to it's north point).
two is the vector pointing in the direction of the target. (center to the vehicle to the target center.)
I need to rotate the vehicle to also point in the direction of the target. This is done by setting the vehicle's steering either 90 degrees to turn right or -90 to turn left.
At the moment i'm querying the box2d body of the vehicle for its angle, then calculating the angle of the target direction vector using:
if(vector.y == 0){ vector.y = 0.000001f; }
float baseRadians = atan(vector.x/vector.y);
if(vector.y < 0){ baseRadians += PI_CONSTANT; } //Adjust for -Y
return -1 * baseRadians;
The following is crude and where I need help...!
I then compare the angle of the vehicle against the angle returned from the direction vector and set the steering as follows:
if(vehicleAngle < targetAngle)
{
steeringInput = -90.0;
}
else if(vehicleAngle > targetAngle)
{
steeringInput = 90.0;
}
else
{
steeringInput = 0.0;
}
The problem is two fold:
The target angle jumps from -4.71 to 1.57 radians, causing the vehicle to switch to the wrong direction
The vehicle angle is continous and keeps increasing rather than staying within a range.
Is there a way to get both the target vector and the vehicle angle in a set range where, for example, if the target angle is 0-360 and the van angle is 0-360, i can then compare them accurately?
Any other way to do this...? Any help appreciated!
Use atan2 instead of atan in your code. It gets the angle from one object to another.
Using the atan2f function instead I managed to get the vehicle vector angle and target vector angle.
my new implementation is as follows:
//get the direction the vehicle is facing and the direction the target is facing
CGPoint vehicleDirectionVector = ccpNormalize(ccpSub(ccp(vehicleBonnetTip.x*PTM_RATIO, vehicleBonnetTip.y*PTM_RATIO), ccp(vehicleCenter.x*PTM_RATIO, vehicleCenter.y*PTM_RATIO)));
CGPoint targetDirectionVector = ccpNormalize(ccpSub(ccp(origTarget.x, origTarget.y), ccp(vehicleCenter.x*PTM_RATIO, vehicleCenter.y*PTM_RATIO)));
vehicleAngle = atan2f(vehicleDirectionVector.x,vehicleDirectionVector.y);
targetAngle = atan2f(targetDirectionVector.x,targetDirectionVector.y);
if ( targetAngle < -M_PI / 2 && vehicleAngle > M_PI / 2 ) targetAngle += M_PI * 2;
if ( targetAngle > M_PI / 2 && vehicleAngle < -M_PI / 2 ) targetAngle -= M_PI * 2;
if ( vehicleAngle < -M_PI / 2 && targetAngle > M_PI / 2 ) vehicleAngle += M_PI * 2;
if ( vehicleAngle > M_PI / 2 && targetAngle < -M_PI / 2 ) vehicleAngle -= M_PI * 2;
CCLOG(#"vehicle angle is %f, target angle is %f", vehicleAngle, targetAngle);
Then to set my steering, crudely (i'm still working on this one..) i do:
if(vehicleAngle < targetAngle)
{
steeringDegrees = 90.0;
}
else if(vehicleAngle > targetAngle)
{
steeringDegrees = -90.0;
}
else
{
steeringDegrees = 0.0;
}

Finding roll, yaw and pitch of a camera, having it's position, target and up vectors

I'm trying to find the yaw, pitch and roll angles of a camera, assuming that I have the position of the camera, it's look_at point (target point) and it's up vector. My best try was by using the following code
zaxis = lookat-position
xaxis = cross(up, xaxis)
yaxos = cross(zxis, xaxis)
Then I find the angles between each axis and the normal vectors (1,0,0) (0,1,0) and (0,0,1)
and assign them to roll, yaw and pitch, but it doesn't seem to work
Any ideas, what I'm doing wrong?
Thanks in advance :)
You won't be able to get the roll angle - as that could be anything, but you can get the elevation and azimuth (pitch and yaw). I've found some old C code which I'll translate to pseudo code, so assuming that your vector isn't zero length:
Vector3 v = lookat - position;
double length = v.Length();
double elevation = asin(v.y / length);
double azimuth;
if (abs(v.z) < 0.00001)
{
// Special case
if (v.x > 0)
{
azimuth = pi/2.0;
}
else if (v.x < 0)
{
azimuth = -pi/2.0;
}
else
{
azimuth = 0.0;
}
}
else
{
azimuth = atan2(v.x, v.z);
}

How to determine ring points' orientation correctly?

Based on How to determine if a list of polygon points are in clockwise order?
I've come up with the following code:
bool PointsClockwise(const std::vector<MyPoint>& points)
{
double sum = 0.0;
for(size_t i = 0; i < points.size() - 1; ++i)
sum += (points[i+1].x()-points[i].x()) * (points[i+1].y()+points[i].y());
return sum > 0.0;
}
However, this seems to have wrong result in certain cases. Take for example the following ring:
LINESTRING(0 119,0 60,694 70,704 72,712 77,719 83,723 92,725 102,723 111,719 120,712 126,703 130)
It is in counter-clockwise order, but the function returns true.
Thanks!
You missed one of the line segments from your summation - namely the one connecting the last point with the first.
Try that:
bool PointsClockwise(const std::vector<MyPoint>& points)
{
double sum = 0.0;
for(size_t i = 0; i < points.size() - 1; ++i)
sum += (points[i+1].x()-points[i].x()) * (points[i+1].y()+points[i].y());
sum += (points[0].x()-points[points.size()-1].x()) * (points[0].y()+points[points.size()-1].y());
return sum > 0.0;
}
You need to include the case i == points.size() - 1, but to do that, you need to do some modular arithmetic in the loop, or else separate out the last iteration. Actually, just initialize sum to the last iteration:
double sum = (points[0].x() - points[points.size() - 1].x())
* (points[0].y() + points[points.size() - 1].y());
and end the iteration at i < points.size() - 1

Resources