NASAWorldWind / WebWorldWind

The NASA WorldWind Javascript SDK (WebWW) includes the library and examples for creating geo-browser web applications and for embedding a 3D globe in HTML5 web pages.
874 stars 375 forks source link

Strange behavior for polygon surface on the globe when longitude is larger than 180 degree #823

Open bangph opened 4 years ago

bangph commented 4 years ago

I want to draw a simply rectangle on WebWorldWind globe with min and max latitudes and longitudes. The simplified code is below:

` ymin = -60; ymax = 60; xmin = -180; xmax = 0;

            var boundaries = [];
            boundaries[0] = []; // outer boundary
            boundaries[0].push(new WorldWind.Position(ymin, xmin));
            boundaries[0].push(new WorldWind.Position(ymin, xmax));
            boundaries[0].push(new WorldWind.Position(ymax, xmax));
            boundaries[0].push(new WorldWind.Position(ymax, xmin)); 

`

It works well as the polygon is drawn on the left-hand side (over America) as in the image: https://imgur.com/a/cN8QDNa

However, when I increase the longitude value, e.g:

ymin = -60; ymax = 60; xmin = -180; xmax = 30; Instead the polygon is drawn on the right-hand side (over Eastern Europe and Asia) as in the image: https://imgur.com/a/VLy5Q4B

I expect with the valid value for longitudes should be [-180:180] and in the second example, the polygon should be drawn over America and Western Europe instead.

mol3earth commented 3 years ago

hi @bangph,

I took at look at the code base, specifically the equation for the azimuthal distance.

This equation comes from Map Projections - A Working Manual", page 30, equation 5-4b and explicitly states that the equation will not work for points >180° apart.

The lacking functionality you are seeking is not a bug. It is due to the nature of the trigonometric functions.

I found a few work arounds.

Option 1

You can add points to the polygon to ensure it is drawn in the direction you want.

        var boundary = [];
        boundary.push(new WorldWind.Location(60, -180));
        boundary.push(new WorldWind.Location(60, -75));
        boundary.push(new WorldWind.Location(60, 30));
        boundary.push(new WorldWind.Location(-60, 30));
        boundary.push(new WorldWind.Location(-60, -75));
        boundary.push(new WorldWind.Location(-60, -180));

Option 2

You can simply plot two rectangles, and make the border transparent, so that they appear to be one.

the two sets of boundary coordinates,
ymin = -60; ymax = 60; x1min = -180; x1max = -75; ymin = -60; ymax = 60; x2min = -75; x2max = 30;

and the transparent outline,
attributes.outlineColor = new WorldWind.Color(0, 0, 0, 0);

In either case you will not have a smooth line connecting the -180 and 30 edges, instead you will have a triangle cutout there, if you want only 4 edges on your polygon, you can plot two triangles. e.g.

        boundary.push(new WorldWind.Location(60, -180));
        boundary.push(new WorldWind.Location(60, -75));
        boundary.push(new WorldWind.Location(60, 30));

If you don't care about the straight connection, you can set the pathType variable of the SurfacePolgyon to 'Linear' or 'RHUMB_LINE' and the line will be smooth and curved about the 60° and -60° Latitudes.

Hopefully this helps you.