How to compute Aspect angle - c++

I have many 3D planes. The thing that I need to know is the way of computing aspect angle.
I hope, I can compute the aspect angle by using the projected normal vector of each plane (my plane equation is ax+by-z+c=0; so normal vector of this plane is a,b,-1) to the XY plane. Then, from the Y axis I can compute the aspect angle. But, I don’t know how to get the projected Normal vector after I projected to XY plane. Then, can I apply the equation which gives angle between two vectors to compute angle of my desired vector from the y axis.
On the other hand, I found, aspect angle is defined as the angle between any line which passes along the steepest slope of the plane and north direction (here, Y axis). Does this definition will follow, with my proposed way that is taking normal vectors? I mean, does the projected normal vector always given along the steepest slope of the plane? Also, some one told me, that this problem should consider as a 2D problem.
Please comment me and send me the relevant formulae in order to compute aspect angle. Thank you.

Some quick googling reveals the definition of the aspect angle.
http://www.answers.com/topic/aspect-angle
It's the angle between the geographic north on the northern hemisphere and the geographic south on the southern hemisphere. So basically it's a measure how much a slope faces the closest pole.
If your world is planar as opposed to spherical it will simplify things, so yes - A 2D problem. I'll make this assumption having the following implications:
In a spherical world the north pole is a point on the sphere. In a planar world the "pole" is a plane at infinity. Think about a plane somewhere far away in your world denoting "north". Only the normal of this plane is important in this task. The unit normal of this plane is N(nz,ny,nz).
Up is a vector pointing up U(ux,uy,yz). This is the unit normal vector of the ground plane.
The unit normal vector of the plane V(a,b,c) can now be projected onto a vector P on the ground plane as usual: P = V - (V dot U) U
Now it's easy to measure the aspect angle of the plane - It's the angle between the "pole"-plane N and the projected plane normal P given by acos(P dot N).
Since north is positive Y-axis for you we have N = (0, 1, 0). And then I guess you have up is U = (0, 0, 1), positive Z. This will simplify things even more - To project on the ground plane we just strip the Z-part. The aspect angle is then the angle between (a,b) and (0,1).
aspectAngle = acos(b / sqrt(a*a + b*b))
Note that planes parallell with the ground plane does not have a well-defined aspect angle since there is no slope to measure the aspect angle from.

What kind of surfaces are you working with? TINS (Triangular Irregular Networks) or DEMs (Digital Elevation Models)?
If you are using raster imagery to create your surfaces, the algorithm for calculating aspect is basically a moving window, which checks a central pixel plus the 8 neighbors.
Compare the central one with each neighbor and check for difference in elevation over distance (rise over run). You can parametrize the distance checks (north, south, east and west neighbors are at distance = 1 and northwest, southwest, southeast and northeast are at distance = sqrt(2)) to make it faster.
You can ask this question on gis.stackexchange also. Many people will be able to help you there.
Edit:
http://blog.geoprocessamento.net/2010/03/modelos-digitais-de-elevacao-e-hidrologia/
this website, altought in portuguese, will help you visualize the algorithm. After calculating the highest slope between a central cell and it's eight neighbors, you assign 0, 2, 4, 8, 16, 32, 64 or 128, depending on the location of the cell that presented highest slope between center and neighboors.

Related

Convert a bounding box in ECEF coordinates to ENU coordinates

I have a geometry with its vertices in cartesian coordinates. These cartesian coordinates are the ECEF(Earth centred earth fixed) coordinates. This geometry is actually present on an ellipsoidal model of the earth using wgs84 corrdinates.The cartesian coordinates were actually obtained by converting the set of latitudes and longitudes along which the geomtries lie but i no longer have access to them. What i have is an axis aligned bounding box with xmax, ymax, zmax and xmin,ymin,zmin obtained by parsing the cartesian coordinates (There is no obviously no cartesian point of the geometry at xmax,ymax,zmax or xmin,ymin,zmin. The bounding box is just a cuboid enclosing the geometry).
What i want to do is to calculate the camera distance in an overview mode such that this geometry's bounding box perfectly fits the camera frustum.
I am not very clear with the approach to take here. A method like using a local to world matrix comes to mind but its not very clear.
#Specktre I referred to your suggestions on shifting points in 3D and that led me to another improved solution, nevertheless not perfect.
Compute a matrix that can transfer from ECEF to ENU. Refer this - http://www.navipedia.net/index.php/Transformations_between_ECEF_and_ENU_coordinates
Rotate all eight corners of my original bounding box using this matrix.
Compute a new bounding box by finding the min and max of x,y,z of these rotated points
compute distance
cameraDistance1 = ((newbb.ymax - newbb.ymin)/2)/tan(fov/2)
cameraDistance2 = ((newbb.xmax - newbb.xmin)/2)/(tan(fov/2)xaspectRatio)
cameraDistance = max(cameraDistance1, cameraDistance2)
This time i had to use the aspect ratio along x as i had previously expected since in my application fov is along y. Although this works almost accurately, there is still a small bug i guess. I am not very sure if it a good idea to generate a new bounding box. May be it is more accurate to identify 2 points point1(xmax, ymin, zmax) and point(xmax, ymax, zmax) in the original bounding box, find their values after multiplying with matrix and then do (point2 - point1).length(). Similarly for y. Would that be more accurate?
transform matrix
first thing is to understand that transform matrix represents coordinate system. Look here Transform matrix anatomy for another example.
In standard OpenGL notation If you use direct matrix then you are converting from matrix local space (LCS) to world global space (GCS). If you use inverse matrix then you converting coordinates from GCS to LCS
camera matrix
camera matrix converts to camera space so you need the inverse matrix. You get camera matrix like this:
camera=inverse(camera_space_matrix)
now for info on how to construct your camera_space_matrix so it fits the bounding box look here:
Frustrum distance computation
so compute midpoint of the top rectangle of your box compute camera distance as max of distance computed from all vertexes of box so
camera position = midpoint + distance*midpoint_normal
orientation depends on your projection matrix. If you use gluPerspective then you are viewing -Z or +Z according selected glDepthFunc. So set Z axis of matrix to normal and Y,X vectors can be aligned to North/South and East/West so for example
Y=Z x (1,0,0)
X = Z x Y
now put position, and axis vectors X,Y,Z inside matrix, compute inverse matrix and that it is.
[Notes]
Do not forget that FOV can have different angles for X and Y axis (aspect ratio).
Normal is just midpoint - Earth center which is (0,0,0) so normal is also the midpoint. Just normalize it to size 1.0.
For all computations use cartesian world GCS (global coordinate system).

Any method to calculate the distance between an infinite line and an axis-aligned arc?

I have a infinite line in 3D, let's say its end points as A and B(long distance between A and B), and an axis-aligned arc, let's say its center as C, start point as S and end point as E. How do we calculate the distance between them?
Or the arc may be a helix?
Here is a picture for my question.
Arc or helix is on xy plane as the picture shows.
The line direction is show by the xyz axes.
The red point represent the line perpendicular to the screen.
The left and center picture show arc condition and the right one is helix.
if your arc is elliptic arc than it is quite simple:
create transformation that convert your elliptic arc to circle arc. this is done by combination of rotation and scaling transform matrix. rotation must rotate your arc so its a,b axises are aligned to x,y axises (rotation angle value is usually directly known or you can compute it with arctan of one of the a,b axis) . Then apply scale to x or y coordinate so after scaling both axises a,b will have the same length.
compute min distance between circle and point (it lies on line from circle center and your point of interest and the circle outline) I thing thats it. you can compute the formula by your self or google it or if you have still trouble with it write here and i will compute it.

Orientation of figures in space

I have a sphere in my program and I intend to draw some rectangles over at a distance x from the centre of this sphere. The figure looks something below:
The rectangles are drawn at (x,y,z) points that I have already have in a vector of 3d points.
Let's say the distance x from centre is 10. Notice the orientation of these rectangles and these are tangential to an imaginary sphere of radius 10 (perpendicular to an imaginary line from the centre of sphere to the centre of rectangle)
Currently, I do something like the following:
For n points vector<vec3f> pointsInSpace where the rectnagles have to be plotted
for(int i=0;i<pointsInSpace.size();++i){
//draw rectnagle at (x,y,z)
}
which does not have this kind of tangential orientation that I am looking for.
It looked to me of applying roll,pitch,yaw rotations for each of these rectangles and using quaternions somehow to make them tangential as to what I am looking for.
However, it looked a bit complex to me and I wanted to ask about some better method to do this.
Also, the rectangle in future might change to some other shape, so a kind of generic solution would be appreciated.
I think you essentially want the same transformation as would be accomplished with a LookAt() function (you want the rectangle to 'look at' the sphere, along a vector from the rectangle's center, to the sphere's origin).
If your rectangle is formed of the points:
(-1, -1, 0)
(-1, 1, 0)
( 1, -1, 0)
( 1, 1, 0)
Then the rectangle's normal will be pointing along Z. This axis needs to be oriented towards the sphere.
So the normalised vector from your point to the center of the sphere is the Z-axis.
Then you need to define a distinct 'up' vector - (0,1,0) is typical, but you will need to choose a different one in cases where the Z-axis is pointing in the same direction.
The cross of the 'up' and 'z' axes gives the x axis, and then the cross of the 'x' and 'z' axes gives the 'y' axis.
These three axes (x,y,z) directly form a rotation matrix.
This resulting transformation matrix will orient the rectangle appropriately. Either use GL's fixed function pipeline (yuk), in which case you can just use gluLookAt(), or build and use the matrix above in whatever fashion is appropriate in your own code.
Personally I think the answer of JasonD is enough. But here is some info of the calculation involved.
Mathematically speaking this is a rather simple problem, What you have is a 2 known vectors. You know the position vector and the spheres normal vector. Since the square can be rotated arbitrarily along around the vector from center of your sphere you need to define one more vector, the up vector. Without defining up vector it becomes a impossible solution.
Once you define a up vector vector, the problem becomes simple. Assuming your square is on the XY-plane as JasonD suggest above. Then your matrix becomes:
up_dot_n_dot_n.X up_dot_n_dot_n.Y up_dot_n_dot_n.Z 0
n.X n.y n.z 0
up_dot_n.x up_dot_n.x up_dot_n.z 0
p.x p.y p.z 1
Where n is the normal unit vector of p - center of sphere (which is trivial if sphere is in the center of the coordinate system), up is a arbitrary unit vector vector. The p follows form definition and is the position.
The solution has a bit of a singularity at the up direction of the sphere. An alternate solution is to rotate first 360 around up, the 180 around rotated axis dot up. Produces same thing different approach no singularity problem.

projected surface normal vector onto xy plane

i have a plane whose equation is ax+by-z+d=0. hence, its normal vector (a,b-1). Now, i need to project my vector to xy plane in order to compute direction of it from the North axis (i guess it is Y axis in here. please help me to get projected vector. thank you.
I think what you're looking for is the dot product. Finding the direction the plane is facing is pretty easy that way.
// generic code, actual code depends on your engine.
// BasePlane.GetNormal() would equal to (0,0,1) for the X/Y plane
float dir = YourPlane.GetNormal().Dot(BasePlane.GetNormal());
If it equals to 1, your plane faces the same direction as the plane you're testing against. If it equals to -1, it's facing the the plane. Equalling to 0 would mean the plane stands orthogonal to the tested plane. Hope this helps.

3d Camera Position given some points

Heyo,
I'm currently working on a project where I need to place the camera such that the full motion of a character would be viewable without moving the camera. I have the position where the character starts, as well as the maximum distance that the character will travel in all three directions (X,Y, & Z). I also have the field of view (which is 90 degrees).
Is there an equation that'll figure out where I need to place the camera so it won't have to move to see the full motion?
Note: this is using OpenGL.
Clarification: The camera should be "in front" of the character that's in the motion, not above.
It'll also be moving along a ground plane.
If you make a bounding sphere of the points, all you need to do is keep the camera at a distance greater than or equal to the radius of the bounding sphere / sin(FOV/2).
For example, if you have a bounding sphere with radius Radius, and a specified Field of View FOV, your camera just needs to be at a point "Dist" away, pointing towards the center of the bounding sphere.
The equation for calculating the distance is:
Dist = Radius / sin( FOV/2 );
This will work in 3D, for a camera at any orientation.
Simply having the maximum range of (X, Y, Z) is not on its own sufficient, because the viewing port is essentially pyramid shaped, with the apex of the pyramid being at the eye position.
For the sake of argument, let's assume that all movement is in the (X, Z) plane (i.e. the ground), and the eye is directly above the origin 10m along the Y axis.
Assuming a square viewport, with your 90˚ field of view you'd be able to see from ±10m along both the X and Z axis, but only for objects who are on the ground (Y = 0). As soon as they come off the ground your view is reduced. If it's 1m of the ground then your (X, Z) extent is only ±9m.
Clearly a real camera could be placed anyway in the scene, facing any direction. Even the "roll" angle of the camera could change how much is visible. There are actually infinitely many such camera points, so you will need to constrain your criteria somewhat.
Take the line segment from the startpoint to the endpoint. Construct a plane orthogonal to this line segment through the midpoint of the line segment. Then position the camera somewhere in this plane at an distance of more than the following from the intersection point of plane and line looking at the intersection point. The up vector of the camera must be in the plane and the horizontal field of view must be 90 degrees.
distance = sqrt(dx^2 + dy^2 + dz^2) / 2
This camera positions will all have the startpoint and the endpoint on the left or right border of the view port and verticaly centered.
Another solution might be to write a function that takes the startpoint, the endpoint, and the desired position of both points on the screen. Then just solve the projection equation for the camera transformation.
It depends, for example, if the object is gonna move in a plane, you can just place the camera outside a ball circumscribed its movement area (this depends on the fact that FOV is 90, which is a fortunate angle).
If the object is gonna move in 3D, it's much more difficult. It would help if you'd specify the region where the object moves (cube vs. ball...) and the direction you want to see it from.