Announcement

Collapse
No announcement yet.

IllegalArgException when using Lat/Lon grid

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • IllegalArgException when using Lat/Lon grid

    There appears to be a bug in GeographicTextRenderer's OrderedText class. I think the OrderedText comparator violates its contract.

    I encountered the bug by turning on the geographic grid, moving the camera very close to the terrain, and pitching the camera up toward the horizon.

    Here's the trace:

    Apr 22, 2014 4:25:05 PM gov.nasa.worldwind.render.GeographicText Renderer$OrderedText render
    SEVERE: generic.ExceptionWhileRenderingText
    java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.ComparableTimSort.mergeHi(Unkn own Source)
    at java.util.ComparableTimSort.mergeAt(Unkn own Source)
    at java.util.ComparableTimSort.mergeCollaps e(Unknown Source)
    at java.util.ComparableTimSort.sort(Unknown Source)
    at java.util.ComparableTimSort.sort(Unknown Source)
    at java.util.Arrays.sort(Unknown Source)
    at java.util.Collections.sort(Unknown Source)
    at gov.nasa.worldwind.render.GeographicText Renderer$OrderedText.render(Unknown Source)
    at gov.nasa.worldwind.AbstractSceneControll er.draw(Unknown Source)
    at gov.nasa.worldwind.StereoOptionSceneCont roller.draw(Unknown Source)
    at gov.nasa.worldwind.BasicSceneController. doRepaint(Unknown Source)
    at gov.nasa.worldwind.AbstractSceneControll er.repaint(Unknown Source)
    at gov.nasa.worldwind.WorldWindowGLAutoDraw able.doDisplay(Unknown Source)
    at gov.nasa.worldwind.WorldWindowGLAutoDraw able.display(Unknown Source)
    at jogamp.opengl.GLDrawableHelper.displayIm pl(GLDrawableHelper.java:373)
    at jogamp.opengl.GLDrawableHelper.display(G LDrawableHelper.java:358)
    at javax.media.opengl.awt.GLCanvas$7.run(GL Canvas.java:983)
    at jogamp.opengl.GLDrawableHelper.invokeGLI mpl(GLDrawableHelper.java:655)
    at jogamp.opengl.GLDrawableHelper.invokeGL( GLDrawableHelper.java:594)
    at javax.media.opengl.awt.GLCanvas$8.run(GL Canvas.java:996)
    at javax.media.opengl.Threading.invoke(Thre ading.java:193)
    at javax.media.opengl.awt.GLCanvas.display( GLCanvas.java:449)
    at javax.media.opengl.awt.GLCanvas.paint(GL Canvas.java:499)
    at javax.media.opengl.awt.GLCanvas.update(G LCanvas.java:688)
    at sun.awt.RepaintArea.updateComponent(Unkn own Source)
    at sun.awt.RepaintArea.paint(Unknown Source)
    at sun.awt.windows.WComponentPeer.handleEve nt(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unk nown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Un known Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivile ged(Native Method)
    at java.security.ProtectionDomain$1.doInter sectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doInter sectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivile ged(Native Method)
    at java.security.ProtectionDomain$1.doInter sectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknow n Source)
    at java.awt.EventDispatchThread.pumpOneEven tForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsF orFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsF orHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents( Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents( Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

  • #2
    Thanks for reporting this. We've filed an issue: http://issues.worldwind.arc.nasa.gov...browse/WWJ-475

    Comment


    • #3
      Proposed solution for this issue

      Hi! I'm the developer in charge of integrating WorldWind into our product, and I've come across this issue myself. This problem only occurs in Java 1.7 and later, and is indeed because of a comparison method that is violating its general contract. Earlier versions of Java used a different algorithm in Collections.sort() that was insensitive to degenerate cases with comparisons around zero. The problem is found in the class gov.nasa.worldwind.render.GeographicText Renderer, in the inner class OrderedText, which has the following compareTo method:

      Code:
              public int compareTo(OrderedText t)
              {
                  if (t.text.getPriority() - this.text.getPriority() == 0)
                  {
                      return (int) (this.eyeDistance - t.eyeDistance);
                  }
                  else
                      return (int) (t.text.getPriority() - this.text.getPriority());
              }
      The differences calculated in this method are doubles which when cast to int can return zero when sufficiently small, and the third requirement of the general contract of Comparable fails (and TimSort, the Java 1.7 sorting algorithm which was ported from Python, implicitly checks this). Here's a bit of code that shows the general problem:

      Code:
      		System.out.println((int) (1.0 - 0.5)); // prints 0, implying (in pseudocode) sgn(BadComparator(1.0).compareTo(z)) == sgn(BadComparator(0.5).compareTo(z)) for all z. (Third part of Comparable contract.)
      		System.out.println((int) (1.0 - 0.0)); // prints 1 
      		System.out.println((int) (.5 - 0.0));  // prints 0; sgn(BadComparator(1.0).compareTo(z)) != sgn(BadComparator(0.5).compareTo(z)) for z=BadComparator(0.0), therefore violating the contract of Comparable.
      I would suggest using the method Math.signum(double) (available since Java 1.5) before casting to int. My suggested replacement for the compareTo() method is as follows:

      Code:
              public int compareTo(OrderedText t)
              {
                  if (t.text.getPriority() - this.text.getPriority() == 0)
                  {
                      return (int) Math.signum(this.eyeDistance - t.eyeDistance);
                  }
                  else
                      return (int) Math.signum(t.text.getPriority() - this.text.getPriority());
              }
      Since the magnitude of the difference is not being used in any way by the surrounding code, this change should have no side effects.

      Regards,

      Jeremy Nickell
      Software Developer, Technology Service Corporation

      Comment

      Working...
      X