Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 494193

Summary: Wrong BezierCurve#getBounds() computation in some cases.
Product: [Tools] GEF Reporter: Matthias Wienand <matthias.wienand>
Component: GEF GeometryAssignee: Alexander Nyßen <nyssen>
Status: RESOLVED INVALID QA Contact:
Severity: normal    
Priority: P3 CC: nyssen
Version: 0.2.0   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:
Bug Depends on:    
Bug Blocks: 494116    
Attachments:
Description Flags
Visualization of bounds
none
Visualization of control bounds none

Description Matthias Wienand CLA 2016-05-20 12:44:30 EDT
The BezierCurve#getBounds() method does not yield correct bounds for all bezier curves.

For example, the bezier curve defined by the control polygon

  (399.05999755859375, 96.6969985961914),
  (484.6500244140625, 209.1699981689453),
  (456.27001953125, 302.8699951171875),
  (438.55999755859375, 348.239990234375)

should have bounds of

  location = (399.05999755859375, 96.6969985961914),
  size = (85.59002685546875, 251.5429916381836),

however, the BezierCurve#getBounds() method returns

  location = (399.05999755859375, 96.6969985961914)
  size = (58.60229677107219, 251.5429916381836),

i.e. the width of the bounds is wrong by ca. 22 units.
Comment 1 Alexander Nyßen CLA 2016-05-21 12:59:11 EDT
Matthias, it seems that the bounds computed by Path2D (from which you have inferred the expected values) are simply those of the control polygon. If I change the implementation of BezierCurve.getBounds() to return getControlBounds(), the added test case passes.
Comment 2 Alexander Nyßen CLA 2016-05-21 17:12:42 EDT
Created attachment 261921 [details]
Visualization of bounds

As it seems my last assumption was not correct, i.e. Path does not seem to use the control polygon. I have visualized the situation in a small example using the bounds computed by GEF4 Geometry (blue) in comparison to those computed by Path2D.Double (red).
Comment 3 Alexander Nyßen CLA 2016-05-22 02:56:25 EDT
Created attachment 261922 [details]
Visualization of control bounds

It seems that even the control bounds (green) are not exact. The end point does not seem to be included.
Comment 4 Alexander Nyßen CLA 2016-05-22 11:18:22 EDT
(In reply to Alexander Nyßen from comment #2)
> Created attachment 261921 [details]
> Visualization of bounds
> 
> As it seems my last assumption was not correct, i.e. Path does not seem to
> use the control polygon. I have visualized the situation in a small example
> using the bounds computed by GEF4 Geometry (blue) in comparison to those
> computed by Path2D.Double (red).

It seems I first looked at BezierCurve2D, which seems to use the control point bounds, whereas Path2D uses its coordinates. Interestingly, even if I change the implementation of our BezierCurve to the following, the bounds in the given example do not change, i.e. the end point does not seem to be (graphically) included. 

@Override
public Rectangle getBounds() {
  double xmin = Math.min(Math.min(getX1(), getX2()), findExtreme(xminCmp).x);
  double xmax = Math.max(Math.max(getX1(), getX2()), findExtreme(xmaxCmp).x);
  double ymin = Math.min(Math.min(getY1(), getY2()), findExtreme(yminCmp).y);
  double ymax = Math.max(Math.max(getY1(), getY2()), findExtreme(ymaxCmp).y);
  return new Rectangle(new Point(xmin, ymin), new Point(xmax, ymax));
}

As such, this could simply be a problem of different interpretation of coordinates for rendering.
Comment 5 Alexander Nyßen CLA 2016-05-22 16:09:57 EDT
I updated the test case to use CubicCurve2D.getBounds2D() for comparison of the control polygon bounds and Path2D for comparison of the tight bounds. 

The test now fails for the tight bounds case with the following difference:
java.lang.AssertionError: expected:<58.487518310546875> but was:<58.60229677107219>

As the tight bounds returned by Path2D.getBounds2D() are not guaranteed to be as tight as possible (only to enclose the shape), the question that remains is whether the bounds computed by BezierCurve are actually wrong, i.e. whether they do not fully enclose the shape, or whether bug #494116 was rather caused by a different interpretation of values on the visual side.
Comment 6 Alexander Nyßen CLA 2016-05-23 03:02:18 EDT
The following tests passes without problems:

// test bounds computation reported in bug #494193
BezierCurve c1 = new BezierCurve(
  399.05999755859375, 96.6969985961914,
  484.6500244140625, 209.1699981689453, 456.27001953125,
  302.8699951171875, 438.55999755859375, 348.239990234375);

Rectangle c1Bounds = c1.getBounds();
for (double i = 0; i <= 1; i += 1 / Math.pow(10, 6)) {
  assertTrue(c1Bounds.contains(c1.get(i)));
}

I thus assume the bounds computation of BezierCurve is consistent. I changed the test case to tolerate a difference of 0.15 to the bounds calculation of Path2D and resolve this one as invalid.

Matthias, please re-open in case you have evidence that disqualifies my judgement.