More efficient way to calculate direction on both axis? - geometry

I have a Vector3 defined like so {x,y,z};
I want to get the angles of the point relative to the y axis and the origin.
I do:
float tilt = atan2( point.z(), point.y() );
float pan = atan2( point.x(), point.y() );
Now, I need the directions so the dot product is not interesting.
Is there a better way to get those values in one go?
Thanks

Expression
angle = acos(x / length(x,y,z))
gives angle between vector and OX axis. Range is 0..Pi.
Perhaps you want -Pi/2..Pi/2 range between OYZ plane and vector - in this case use Pi/2-angle

Related

Turning a circle collision function into a 3d cylinder function

I've got a function to return any points at which a line segment intersects a circle (up to two results, but potentially zero):
bool Math::GetLineCircleIntersections(Point theCenter, float theRadius, Point theLineA, Point theLineB, Array<Point>& theResults)
{
theResults.Reset();
Point aBA=theLineB-theLineA;
Point aCA=theCenter-theLineA;
float aA=aBA.mX*aBA.mX+aBA.mY*aBA.mY;
float aBBy2=aBA.mX*aCA.mX+aBA.mY*aCA.mY;
float aC=aCA.mX*aCA.mX+aCA.mY*aCA.mY-theRadius*theRadius;
float aPBy2=aBBy2/aA;
float aQ=aC/aA;
float aDisc=aPBy2*aPBy2-aQ;
if (aDisc<0) return false;
float aTmpSqrt=(float)sqrt(aDisc);
float aABScalingFactor1=-aPBy2+aTmpSqrt;
float aABScalingFactor2=-aPBy2-aTmpSqrt;
int aRSpot=0;
if (aABScalingFactor1<=0.0f && aABScalingFactor1>=-1.0f) theResults[aRSpot++]=Point(theLineA.mX-aBA.mX*aABScalingFactor1,theLineA.mY-aBA.mY*aABScalingFactor1);
if (aDisc==0) return true;
if (aABScalingFactor2<=0.0f && aABScalingFactor2>=-1.0f) theResults[aRSpot++]=Point(theLineA.mX-aBA.mX*aABScalingFactor2,theLineA.mY-aBA.mY*aABScalingFactor2);
return true;
}
I want to convert this to a 3D line, with an infinite cylinder-- with the added complication that the 3D cylinder has a tilt axis. I understand that what I'm really doing is intersecting with a sphere that is centered on the cylinder center where the plane of the line cuts it... but... how do I do that? How do I choose the best point to center the sphere, and then having done that, what's my change to turn line->circle intersections into line->sphere?
(I have a vector class that is exactly like the point class)
(Edit) I did manage to convert to a sphere function, only to discover that duh, no, a sphere won't work because a line that's tilted will not enter and exit the same way it would enter and exit a cylinder.
So, question is the same-- how can I convert this to collide with an infinite cylinder given an origin and axis for the cylinder?
I do not think sphere is usable for this...
However why not convert your 3D line into 2D by projecting it on to plane paralel with the cylinder base.
So you got 3D line in form of 2 endpoint p0,p1 and cylinder in form any point on its axis p , its radius r and axis unit direction vector d.
You need 2 unit basis vectors u,v describing cylinder base
so exploit cross product and cylinder axis for example:
// set u as any unit and non paralel vector to d
u = (1,0,0)
if (abs(dot(u,d))>0.75) u=(0,1,0)
// v set as perpendicular to u,d
v = cross(d,u)
// and make u perpendicular to v,d too
u = cross(v,d)
Project the problem into 2D
p0' = vec2( p0*dot(p0,u) , p0*dot(p0,v) )
p1' = vec2( p1*dot(p1,u) , p1*dot(p1,v) )
p' = vec2( p *dot(p ,u) , p *dot(p ,v) )
Solve the problem
now you just use 2D points p0',p1',p' and solve your problem using function you already have...

How to find the orientation of a plane?

I have three non-colinear 3D points, let's say pt1, pt2, pt3. I've computed the plane P using the sympy.Plane. How can I find the orientation of this plane(P) i.e. RPY(euler angles) or in quaternion?
I never used sympy, but you should be able to find a function to get the angle between 2 vectors (your normal vector and the world Y axis.)
theta = yaxis.angle_between(P.normal_vector)
then get the rotation axis, which is the normalized cross product of those same vectors.
axis = yaxis.cross(P.normal_vector).normal()
Then construct a quaternion from the axis and angle
q = Quaternion.from_axis_angle(axis, theta)

finding value of a point between measured points on a 2D plane

I'm trying to find the best way to calculate this. On a 2D plane I have fixed points all with an instantaneous measurement value. The coordinates of these points is known. I want to predict the value of a movable point between these fixed points. The movable point coodinates will be known. So the distance betwwen the points is known as well.
This could be comparable to temperature readings or elevation on topography. I this case I'm wanting to predict ionospheric TEC of the mobile point from the fixed point measurements. The fixed point measurements are smoothed over time however I do not want to have to store previous values of the mobile point estimate in RAM.
Would some sort of gradient function be the way to go here?
This is the same algorithm for interpolating the height of a point from a triangle.
In your case you don't have z values for heights, but some other float value for each triangle vertex, but it's the same concept, still 3D points.
Where you have 3D triangle points p, q, r and test point pt, then pseudo code from the above mathgem is something like this:
Vector3 v1 = q - p;
Vector3 v2 = r - p;
Vector3 n = v1.CrossProduct(v2);
if n.z is not zero
return ((n.x * (pt.x - p.x) + n.y * (pt.y - p.y)) / -n.z) + p.z
As you indicate in your comment to #Phpdevpad, you do have 3 fixed points so this will work.
You can try contour plots especially contour lines. Simply use a delaunay triangulation of the points and a linear transformation along the edges. You can try my PHP implementations https://contourplot.codeplex.com for geographic maps. Another algorithm is conrec algorithm from Paul Bourke.

Finding internal angles of polygon

I have some lines that their intersection describes a polygon, like this:
I know the order of the lines, and their equations.
To find the internal angles, I found each lines orientations. But I've got confused as subtracting two lines orientation would give two different angles, even if I do it in the order of polygon's sides.
For example, in the following image, if I just subtract the orientation of the lines, I would get any of the following angles:
What made me more confused, is when the polygon is not convex, I will have angles greater than 180, and using my approach I don't get the correct angle at all:
And I found out that this way of approaching the problem is wrong.
So, What is the best way of finding the internal angles using just the lines? I know for a convex polygon, I may find vectors and then find the angle between them, but even for P6 in my example the vector approach fails.
Anyway, I prefer a method that won't include a conditional case for solving that concavity problem.
Thanks.
With ordered lines it is possible to find points of intersection (polygon vertexes) in clockwise order. Then you can calculate internal angles:
Angle[i] = Pi + ArcTan2(V[i] x V[i+1], V[i] * V[i+1])
(crossproduct and dotproduct of incoming and outgoing vectors for every vertex)
or
Angle[i] = Pi + ArcTan2( dx_in*dy_out-dx_out*dy_in, dx_in*dx_out+dy_in*dy_out2 )
Note: change plus sign after Pi to minus for anti-clockwise direction.
Edit:
Note that crossproduct and dotproduct are scalars, not vectors.
Example for your data:
dx1 = 5; dy1 = -15; dx2 = -15; dy2 = 5
Angle = Pi + ArcTan2(5*5-15*15, -5*15-5*15) = Pi - 2.11 radians ~ 59 degrees
Example for vectors:
(0,-1) (1,0) (L-curve)
Angle = Pi + ArcTan2(1, 0) = 270 degrees

shade border of 2D polygon differently

we are programming a 2D game in XNA. Now we have polygons which define our level elements. They are triangulated such that we can easily render them. Now I would like to write a shader which renders the polygons as outlined textures. So in the middle of the polygon one would see the texture and on the border it should somehow glow.
My first idea was to walk along the polygon and draw a quad on each line segment with a specific texture. This works but looks strange for small corners where the textures are forced to overlap.
My second approach was to mark all border vertices with some kind of normal pointing out of the polygon. Passing this to the shader would interpolate the normals across edges of the triangulation and I could use the interpolated "normal" as a value for shading. I could not test it yet but would that work? A special property of the triangulation is that all vertices are on the border so there are no vertices inside the polygon.
Do you guys have a better idea for what I want to achieve?
Here A picture of what it looks right now with the quad solution:
You could render your object twice. A bigger stretched version behind the first one. Not that ideal since a complex object cannot be streched uniformly to create a border.
If you have access to your screen buffer you can render your glow components into a rendertarget and align a full-screen quad to your viewport and add a fullscreen 2D silhouette filter to it.
This way you gain perfect control over the edge by defining its radius, colour, blur. With additional output values such as the RGB values from the object render pass you can even have different advanced glows.
I think rendermonkey had some examples in their shader editor. Its definetly a good starting point to work with and try out things.
Propaply you want calclulate new border vertex list (easy fill example with triangle strip with originals). If you use constant border width and convex polygon its just:
B_new = B - (BtoA.normalised() + BtoC.normalised()).normalised() * width;
If not then it can go more complicated, there is my old but pretty universal solution:
//Helper function. To working right, need that v1 is before v2 in vetex list and vertexes are going to (anti???) cloclwise!
float vectorAngle(Vector2 v1, Vector2 v2){
float alfa;
if (!v1.isNormalised())
v1.normalise();
if (!v2.isNormalised())
v2.normalise();
alfa = v1.dotProduct(v2);
float help = v1.x;
v1.x = v1.y;
v1.y = -help;
float angle = Math::ACos(alfa);
if (v1.dotProduct(v2) < 0){
angle = -angle;
}
return angle;
}
//Normally dont use directly this!
Vector2 calculateBorderPoint(Vector2 vec1, Vector2 vec2, float width1, float width2){
vec1.normalise();
vec2.normalise();
float cos = vec1.dotProduct(vec2); //Calculates actually cosini of two (normalised) vectors (remember math lessons)
float csc = 1.0f / Math::sqrt(1.0f-cos*cos); //Calculates cosecant of angle, This return NaN if angle is 180!!!
//And rest of the magic
Vector2 difrence = (vec1 * csc * width2) + (vec2 * csc * width1);
//If you use just convex polygons (all angles < 180, = 180 not allowed in this case) just return value, and if not you need some more magic.
//Both of next things need ordered vertex lists!
//Output vector is always to in side of angle, so if this angle is.
if (Math::vectorAngle(vec1, vec2) > 180.0f) //Note that this kind of function can know is your function can know that angle is over 180 ONLY if you use ordered vertexes (all vertexes goes always (anti???) cloclwise!)
difrence = -difrence;
//Ok and if angle was 180...
//Note that this can fix your situation ONLY if you use ordered vertexes (all vertexes goes always (anti???) cloclwise!)
if (difrence.isNaN()){
float width = (width1 + width2) / 2.0; //If angle is 180 and border widths are difrent, you cannot get perfect answer ;)
difrence = vec1 * width;
//Just turn vector -90 degrees
float swapHelp = difrence.y
difrence.y = -difrence.x;
difrence.x = swapHelp;
}
//If you don't want output to be inside of old polygon but outside, just: "return -difrence;"
return difrence;
}
//Use this =)
Vector2 calculateBorderPoint(Vector2 A, Vector2 B, Vector2 C, float widthA, float widthB){
return B + calculateBorderPoint(A-B, C-B, widthA, widthB);
}
Your second approach can be possible...
mark the outer vertex (in border) with 1 and the inner vertex (inside) with 0.
in the pixel shader you can choose to highlight, those that its value is greater than 0.9f or 0.8f.
it should work.

Resources