JDK-4486670 : Arc2D.Double may not draw correctly for tiny angular extents
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2001-08-01
  • Updated: 2003-04-03
  • Resolved: 2003-04-03
Related Reports
Duplicate :  
Relates :  
Description

Name: ddT132432			Date: 07/31/2001


Java(TM) 2 Runtime Environment, Standard Edition (build Blackdown-1.3.1-FCS)
Java HotSpot(TM) Client VM (build Blackdown-1.3.1-FCS, mixed mode)


//file: Ikebana.java
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

/** The following program exhibits a Bug in Arc2D.Double
 * It creates an arc with a very small angular extent.
 * Then the arc is drawn with different strokes.
 * One time the result is wrong (red),
 * one time it is o.k. (blue)
 *
 * My conjecture for the bug's source: deep inside the implementation
 * an inverse trig function (like Math.acos or Math.asin)
 * returns NaN (instead of 0, or Math.PI, or so)
 * because its argument is NOT IN [-1,1].
 * Theoretically it should be, but practically (due to roundoff errors)
 * its absolute value is greater than 1.
 *
 * Platform: JDK1.3 under Linux(i386) (Display: 17", 1024x768)
 * Reproduciblity may depend on the screen's resolution.
 */

public class Ikebana extends JComponent {

  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;

    // ==== create an arc with a very small angular extent ========

    Arc2D.Double s=new Arc2D.Double(100.0, 100.0, 240.0, 240.0, -180.0, 1.e-15, Arc2D.PIE);

    g2.setPaint(Color.red);           // BAD CASE
    g2.setStroke(new BasicStroke(1)); // draw the arc, thickness 1
    g2.draw(s);

    g2.setStroke(new BasicStroke(2)); // GOOD CASE
    g2.setPaint(Color.blue);           // g2.draw((Arc2D.Double)s);
    g2.draw(s);

    // ============================================================
  }

    // ==== almost literally from Niemeyer & Knudsen

  public static void main(String[] args) {
    JFrame f = new JFrame("Ikebana");
    Container c = f.getContentPane(  );
    c.setLayout(new BorderLayout(  ));
    c.add(new Ikebana(), BorderLayout.CENTER);
    f.setSize(400, 400);
    f.setLocation(100, 100);
    f.addWindowListener(new WindowAdapter(  ) {
      public void windowClosing(WindowEvent e) { System.exit(0); }
    });
    f.setVisible(true);
  }
}
// =========== END of Sample Program ====================
(Review ID: 128180) 
======================================================================

Comments
EVALUATION Name: spR10137 Date: 03/27/2003 As described in bugId 4836495, tiny angular extentions give us NaNs in cubic segment of PathIterator due to implementation of ArcIterator.btan() method. Examples in testcase are drawing by different ways. These ways treat NaNs in different manner. First case goes to draw method of X11Renderer, case of STROKE_THIN. We get flattened path iterator for arc, then add segments to new Polygon with addPoint(int, int) call. Of course, we have NaNs in coordinates, but NaN casted to int becomes zero in java. So we can see line to (0, 0) point. Second case goes to the same method, but not STROKE_THIN case. It's case of (sg2d.strokeState < sg2d.STROKE_CUSTOM). We use devFillSpans() method for our arc. Way to fix problem is to avoid NaN appearance in ArcIterator.btan() implementation. So, I propose to close this bug as duplicate of 4836495. This bug is earlier than 4836495, but it's not a crasher. ======================================================================
11-06-2004

WORK AROUND Name: ddT132432 Date: 07/31/2001 Check for extremely small angular extents in your code, replace them by 0. Impact on User: None of the ones given below. The situation where the bug occurs is exceptional, so it is unlikely to run into the problem very often. But one should not force the user to test for these rare circumstances. ======================================================================
11-06-2004