NASAWorldWind / WorldWindJava

The NASA WorldWind Java SDK (WWJ) is for building cross-platform 3D geospatial desktop applications in Java.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Surface line rendering degrades further from equator

dacunni1 opened this issue · comments

I'm working on a project that uses WorldWindJava to render surface shapes out at sea.
We're running into issues where shape outlines degrade the further from the equator you get, starting around 60 degrees latitude.
The degradation is especially noticeable with stippled outlines, but even solid lines don't look great, and north/south lines nearly disappear.

Below is a Minimal Reproducible Example with a couple screenshots that show the rendering differences.
The first "good" image was taken at 40 degrees latitude, the second "bad" image at 75 degrees latitude.
You can clearly see the vastly different manner in which the same line attributes are rendered.
I would expect to see the same line thickness and stipple/dash pattern regardless of where the line is rendered on the globe.
Instead, further from the equator, the lines appear to be squeezed from an east/west perspective. North/south lines become thinner, while east/west lines have their dashed pattern squeezed into dots.
The behavior is the same on Windows 10 and RHEL 7 environments, and at least from version 2.0.0 to the latest.

package worldwind;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.Arrays;

import javax.swing.JFrame;

import gov.nasa.worldwind.Model;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.awt.WorldWindowGLJPanel;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.BasicShapeAttributes;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.SurfacePolyline;
import gov.nasa.worldwind.terrain.ZeroElevationModel;

public class Main {

   public static void main(String[] args) {
      EventQueue.invokeLater(Main::swing);
   }

   private static void swing() {
      WorldWindowGLJPanel ww = new WorldWindowGLJPanel();
      Model model = (Model) WorldWind.createConfigurationComponent(AVKey.MODEL_CLASS_NAME);
      model.getLayers().add(setupLayer());
      model.getGlobe().setElevationModel(new ZeroElevationModel());
      ww.setModel(model);
      ww.setPreferredSize(new Dimension(999, 666));
      JFrame frame = new JFrame();
      frame.setContentPane(ww);
      frame.pack();
      frame.setVisible(true);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      ww.getView().setEyePosition(Position.fromDegrees(75, 3, 10000));
   }

   private static RenderableLayer setupLayer() {

      BasicShapeAttributes attr = new BasicShapeAttributes();
      attr.setDrawInterior(false);
      attr.setEnableAntialiasing(true);
      attr.setOutlineMaterial(new Material(Color.ORANGE));
      attr.setOutlineOpacity(1);
      attr.setOutlineStippleFactor(1);
      attr.setOutlineStipplePattern((short) 0x0F0F);
      attr.setOutlineWidth(2);

      SurfacePolyline line = new SurfacePolyline();
      line.setAttributes(attr);
      line.setLocations(Arrays.asList(//
            LatLon.fromDegrees(75, 1), //
            LatLon.fromDegrees(40, 1), //
            LatLon.fromDegrees(40, 3), //
            LatLon.fromDegrees(75, 3), //
            LatLon.fromDegrees(75, 2)));

      RenderableLayer layer = new RenderableLayer();
      layer.addRenderable(line);
      return layer;
   }
}

surfaceline40-1 surfaceline75-3