Sampling an osgEarth::Geometry correctly

classic Classic list List threaded Threaded
8 messages Options
Blanky Blanky
Reply | Threaded
Open this post in threaded view
|

Sampling an osgEarth::Geometry correctly

Hello,

I'm currently trying to use an osgEarth::Symbology::GeometryFactory to create an arc with its provided function. However, when I supplied it originally I didn't give the factory itself a spatial reference and eventually figured out a way to parent it with to a GeoTransform to handle it for me.

What I wanted was an arc to be calculated correctly for its position on the map, but because I didn't want to use a FeatureNode and Features because of their expense I originally attempted the following:

1. Create an osgEarth::Symbology::GeometryFactory variable with no parameters

2. Create an osgEarth::Symbology::Geometry from the osgEarth::Symbology::GeometryFactory::createArc(...) function with the center point of the first argument at (0,0,0)

3. Extracted the points from it using the osgEarth::Symbology::Geometry::createVec3dArray()

4. Reconstructed an osg::Geometry from these points

5. Added these points to an osg::Drawable

6. Added the osg::Drawable to an osg::Geode

7. Added the osg::Geode as a child to an osgEarth::Annotations::GeoTransform

Now I wanted to simulate the effect that the osgEarth::Annotations::FeatureNodes have when they move on the map. For example as something moves closer to the poles, its shape should elongate a bit, like a perfect circle by the equator should become rather egg shaped when closer to the poles. Or a square will start to look like a tall rectangle as it also approaches the poles. I need this effect to work for the sake of accuracy since the distance is very different from the poles on a Mercator projection especially, so I attempted the following after learning a bit:

1. Create an osgEarth::Symbology::GeometryFactory variable with the projected map's getGeographicSRS function

2. Create an osgEarth::Symbology::Geometry from the osgEarth::Symbology::GeometryFactory::createArc(...) function with the center point of the first argument at (lon, lat, 0)

3. Extracted the points from it using the osgEarth::Symbology::Geometry::createVec3dArray()

4. Converted the points to a Mercator projection using some tangent/logarithm math and the map's extent width

5. Added the points to an osg::Drawable

6. Added the osg::Drawable to an osg::Geode

7. Directly added the osg::Geode to the root scene graph/ osgEarth::MapNode*

Now, this had a slightly different effect. The radius of the circle seemed to grow proportionally instead of elongating as it approached the poles. I looked into the osgEarth::GeometryCompiler and the build() functionality for polygons specifically but got confused by the many different options and each options' specific class implementations and didn't understand how osgEarth itself managed to simulate the correct effects. Am I missing one step to get the desired effect I'm looking for, because the fact that it grows as it moved north/south now implies I'm on to something. Thanks for any help!

gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Sampling an osgEarth::Geometry correctly

GeometryFactory just makes geometries in a local cartesian coordinate system centered on the geospatial center point you provide.

In other words: GF will apply its SRS to the center point of your object, but it only [properly] supports linear units for the other parameters (radius, width, etc.).

What exactly are you trying to render? The idea of a circle (or an arc) with its radius measured in degrees seems a strange use case and somewhat ill-defined.
Glenn Waldron / Pelican Mapping
Blanky Blanky
Reply | Threaded
Open this post in threaded view
|

Re: Sampling an osgEarth::Geometry correctly

I'm not trying to alter the radius in degrees. For example If I just made an osgEarth::Features::Feature and made a circular polygon and added it to an osgEarth::FeatureNode and positioned it near the equator, it'll have a relatively perfectly round shape. Now, if I reposition this same FeatureNode north/south toward the poles it starts to gain an egg/oval shape because of the latitudinal stretch caused by latitudes not having the same height as it does at the equator. This is the behavior I received in a 3D map, but I'm developing for both a 2D and 3D environment simultaneously using a mirror scene graph for both and need them to be accurate for both projection types. After some investigating, I may actually be getting the correct behavior:

Mercator and circle example

In the Wikipedia image above, it is showing the deformation of a Mercator projection's circles. This is essentially what I'm getting right now. I'm not quite sure I intuitively understand this because the radius against the longitude seems to grow, but the radius against the latitude seems to stay proportionate to the latitudinal stretch. Like the middle circles at the equator look like they have 2.5 degree latitude radii (I know I shouldn't measure in degrees, but for the sake of visual simplicity), but as it reaches the poles it starts to become visibly 5. I know for a fact that the distance between longitude lines are equidistant, so can you explain why this occurs? Is this just because the vertical stretch makes the positional coordinates approach in a logarithmic (or whatever accurate term) fashion, thus explaining the deformation? I just want to make sure if I sample the longitude on the edge of the circle at the equator, such that if I sample the same edge when it's near +/-80 N/S that the edge of it on its left/right will still gives me the same longitude sample.

I'm essentially trying to make a circle/arc that had a line thickness of x meters. If the circle is filled / has no line thickness, then the radii of the inner circle will just be 0. Both the inner and outer arcs will have the same degrees start and end(have nothing to do with latitude). To stitch them together I iterate over the points from the createVec3DArray function from both osgEarth::Symbology::Geometrys. They always have the same amount of points to sample, so that makes it easy for me to stitch together the points like such:

Based on the above image, I'm actually receiving the correct output, but just don't understand how/why.

    //Code to create the osgEarth::Symbology::Geometry from the Factory
    ...
   
    osg::ref_ptr<osg::Vec3Array> outerArray = outerArcGeom->createVec3Array();
    osg::ref_ptr<osg::Vec3Array> innerArray = innerArcGeom->createVec3Array();
    osg::ref_ptr<osg::Vec3Array> diskArray;
   
    for(int i = 0; i < outerArray->size(); ++i){
        //Do an inline Mercator conversion on each Vec3
        ...
        diskArray.push_back(outerPointConverted);
        diskArray.push_back(innerPointConverted);
    }

    //Code to add the diskArray as a primitive set to an osg::Drawable and the rest of the code

gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Sampling an osgEarth::Geometry correctly

Mercator is a conformal projection meaning that, for "small" objects, the object's shape will be preserved.

Your linked image shows the Mercator Tissot Indicatrix -- which only represents distortion at a single point (the circle's center) -- and it not exactly what a circle transformed into the Mercator projection will look like. Drawing a large circle and converting each point on its arc to Mercator will still incur visible distortion when the circle gets too large or too close to the poles.

Anyway, converting each point to Mercator is the correct approach... just bear in mind the limitations of the projection!
Glenn Waldron / Pelican Mapping
Blanky Blanky
Reply | Threaded
Open this post in threaded view
|

Re: Sampling an osgEarth::Geometry correctly

Okay, so I was testing everything with mercator points with the included equirectungular world.tif you include in the build. I finally wanted to verify that it lines up all correctly in a mercator projection. I remember in 2.9 that I could make a spherical-mercator profile for the same image and it would look right. However, in 2.10 I just tried with the same Earthfile setup and it just appears white. Any idea what's going on with that? I also tried to do a gdal_warp on it to convert from EPSG:4326 to an EPSG:3395 and it spit out some errors about being unable to do the conversion and output nothing. Is this why I'm getting a blank white map? Thanks.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Sampling an osgEarth::Geometry correctly

Hmm. That looks like a bug indeed. I'll look into it.
Glenn Waldron / Pelican Mapping
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Sampling an osgEarth::Geometry correctly

I pushed a fix for this to master/2.10.
Thanks for pointing this out.

https://github.com/gwaldron/osgearth/commit/e7c5f192f8b730abf00c30794e1c31b5ecdaa7b0
Glenn Waldron / Pelican Mapping
Blanky Blanky
Reply | Threaded
Open this post in threaded view
|

Re: Sampling an osgEarth::Geometry correctly

Thanks Glenn!