I have been practicing some openSceneGraph examples provided by OSG. One of the example, I came across text on the ellipsoid.
osgText::Text* createText(osg::EllipsoidModel* ellipsoid, double latitude, double longitude, double height, const std::string& str)
{
double X, Y, Z;
ellipsoid->convertLatLongHeightToXYZ(osg::DegreesToRadians(latitude), osg::DegreesToRadians(longitude), height, X, Y, Z);
This works well in my case.then I thought to do the same with the sphere. In this example, the ellipsoid drawn basing on the lat, long and height. I want to draw the sphere with radius which depends on the window size / screen size. Unfortunately I failed to see which converts the screen coordinates to sphere size in the osg::Sphere class.
Some one can help me, to solve this. There might be some thing which converts this, may be i did not come across because of my less experience.
Cheers,
Inna.
osg::Sphere is not a geospatial model like osg::EllipsoidModel.
Just create an osg::EllipsoidModel with both Radii (equator and polar) the same as the sphere radius you wish, and use osg::EllipsoidModel.
Related
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.
I want to write a transformer for converting svg basic types into worldwind shapes like polyline, polygon etc.
Since svg gives coordinates on canvas and I need to convert them to position, I am looking for a method in the api which can do this.
I see there is Vec4 for point but I am not sure how it relates to canvas coordinates.
Will it be a correct representation if for say point x=100,y=100, I do the following
Vec4 vec=new Vec4(x,y,0.0f);
Globe g=view.getGlobe();
Position p=g.computePositionFromPoint(vec);
Will this correspond position will be the position at point(x=100,y=100) on the screen. If i bring my mouse to x=100 and y=100 for the current view the position should be p.
Globe.computePositionFromPoint(vec) takes Cartesian coordinates as input, not screen coordinates. To go from screen coordinates to position you want something like this:
Vec4 screenCoords = new Vec4(x,y);
Vec4 cartesian = view.unProject(screenCoords);
Globe g=view.getGlobe();
Position p=g.computePositionFromPoint(cartesian);
A better way to do this would be:
Point screenPoint = dragContext.getPoint();
View view = dragContext.getView();
double latitude = view.computePositionFromScreenPoint(screenPoint.getX(), screenPoint.getY()).getLatitude().degrees;
double longitude = view.computePositionFromScreenPoint(screenPoint.getX(), screenPoint.getY()).getLongitude().degrees;
Position objectPosition = new Position(LatLon.fromDegrees(latitude, longitude), 0);
Then you can set the position of the object to objectPosition.
If you want to go from canvas to 3D, you're probably looking for View#computeRayFromScreenPoint(double, double). This will give you a ray (in Vec4 format) from the eye through the given pixel on the canvas. You'll have to intersect this ray with something to generate a meaningful 3D point, since each pixel is an infinite line in space.
about the Globe#computePointFromPosition:
Position - A latitude, longitude, altitude position, with the altitude being in MSL (alt above sea level)
Vec4 - Just a directional vector (often used for Cartesian coordinates). For the Cartesian coordinate system, the z-axis comes out of the earth through 0deg/0deg lat/lon, x-axis through 0deg/90deg, and y-axis through the north pole.
As Chris mentioned, The Globe#computePointFromPosition() and Globe#computePointFromPosition() switch from a Position to a Cartesian Vec4 and vice versa, using your globe as the reference frame.
I have a problem with creating 3D cylinders (without OpenGL). I understand that a mesh is used to create the cylinder surface and triangle fans are used to create the top and bottom caps. I have already implemented the mesh but not the planar triangle fans, so currently my 3D object looks like a cylinder without the bottom and top cap.
I believe this is what I need to do in order to create the bottom and top caps. First, find the center point of the cylinder mesh. Second, find the vertices of the mesh. Third, using the center point and the 2 vertex points, create the triangle. Fourth, repeat the steps until a planar circle is created.
Are the above steps a sufficient way of creating the caps or is there a better way? And how do I find the vertices of the mesh so I can create the triangle fans?
First some notes:
you did not specify your platform
gfx interface
language
not enough info about your cylinder either
is it axis aligned?
what coordinate system (Cartesian/orthogonal/orthonormal)?
need additional dimensions like color or texture coordinates?
So I can provide just generic info then
Axis aligned cylinder
choose the granularity N
number of points along your cap's circle
usually 20-36 is OK but if you need higher precision then sometimes you need even 1000 points or more
all depends on the purpose,zoom, angle and distance of view ...
and performance issues
for now let N=32
you need BR (boundary representation)
you did not specify gfx interface but your text implies BR model (surface polygons)
also no pivot point position so I will choose middle point of cylinder to be (0,0,0)
z axis will be the height of cylinder
and the caps will be coplanar with xy plane
so for cylinder is enough set of 2 rings (caps)
so the points can be defined in C++ like this:
const int N=32; // mesh complexity
double p0[N][3],p1[N][3]; // rings`
double a,da,c,s,r,h2; // some temp variables
int i;
r =50.0; // cylinder radius
h2=100.0*0.5; // half height of cyliner
da=M_PI/double(N-1);
for (a=0.0,i=0;i<N;i++,a+=da)
{
c=r*cos(a);
s=r*sin(a);
p0[i][0]=c;
p0[i][1]=s;
p0[i][2]=+h2;
p1[i][0]=c;
p1[i][1]=s;
p1[i][2]=-h2;
}
the ring points are as closed loop (p0[0]==p0[N-1])
so you do not need additional lines to handle it...
now how to draw
cant write the code for unknown api but
'mesh' is something like QUAD_STRIP I assume
so just add points to it in this order:
QUAD_STRIP = { p0[0],p1[0],p0[1],p1[1],...p0[N-1],p1[N-1] };
if you have inverse normal problem then swap p0/p1
now for the fans
you do not need the middle point (unless you have interpolation aliasing issues)
so similar:
TRIANGLE_FAN0 = { p0[0],p0[1],...p0[N-1] };
TRIANGLE_FAN1 = { p1[0],p1[1],...p1[N-1] };
if you still want the middle point then:
TRIANGLE_FAN0 = { (0.0,0.0,+h2),p0[0],p0[1],...p0[N-1] };
TRIANGLE_FAN1 = { (0.0,0.0,-h2),p1[0],p1[1],...p1[N-1] };
if you have inverse normal problem then reverse the points order (middle point stays where it is)
Not axis aligned cylinder?
just use transform matrix on your p0[],p1[] point lists to translate/rotate to desired position
the rest stays the same
I'm trying to find the best way to get the most distant point of a circle from a specified point in 2D space. What I have found so far, is how to get the distance between the point and the circle position, but I'm not entirely sure how to expand this to find the most distant point of the circle.
The known variables are:
Point a
Point b (circle position)
Radius r (circle radius)
To find the distance between the point and the circle position, I have found this:
xd = x2 - x1
yd = y2 - y1
Distance = SquareRoot(xd * xd + yd * yd)
It seems to me, this is part of the solution. How would this be expanded to get the position of Point x in the below image?
As an additional but optional part of the question: I have read in some places that it would be possible to get the distance portion without using the Square Root, which is very performance intensive and should be avoided if fast code is necessary. In my case, I would be doing this calculation quite often; Any comments on this within the context of the main question would be welcome too.
What about this?
Calculate A-B.
We now have a vector pointing from the center of the circle towards A (if B is the origin, skip this and just consider point A a vector).
Normalize.
Now we have a well defined length (the length is 1)
If the circle is not of unit radius, multiply by radius. If it is unit radius, skip this.
Now we have the correct length.
Invert sign (can be done in one step with 3., just multiply with the negative radius)
Now our vector points in the correct direction.
Add B (if B is the origin, skip this).
Now our vector is offset correctly so its endpoint is the point we want.
(Alternatively, you could calculate B-A to save the negation, but then you have to do one more operation to offset the origin correctly.)
By the way, it works the same in 3D, except the circle would be a sphere, and the vectors would have 3 components (or 4, if you use homogenous coords, in this case remember -- for correctness -- setting w to 0 when "turning points into vectors" and to 1 at the end when making a point from the vector).
EDIT:
(in reply of pseudocode)
Assuming you have a vec2 class which is a struct of two float numbers with operators for vector subtraction and scalar multiplicaion (pretty trivial, around a dozen lines of code) and a function normalize which needs to be no more than a shorthand for multiplying with inv_sqrt(x*x+y*y), the pseudocode (my pseudocode here is something like a C++/GLSL mix) could look something like this:
vec2 most_distant_on_circle(vec2 const& B, float r, vec2 const& A)
{
vec2 P(A - B);
normalize(P);
return -r * P + B;
}
Most math libraries that you'd use should have all of these functions and types built-in. HLSL and GLSL have them as first type primitives and intrinsic functions. Some GPUs even have a dedicated normalize instruction.
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.