Bug in Rectangle.union?
Is is just me, or is this wrong. I'm guessing there's some sort of zero-area-based optimization that's causing rectangles to be improperly unioned.
import flash.geom.Rectangle;
var r1:Rectangle = new Rectangle( 0, 0, 40, 23 ); //non-zero area plus
var r2:Rectangle = new Rectangle( 0, 0, 100, 0 ); //zero-area but non-zero height
trace( r1.union( r2 ) ); //(x=0, y=0, w=40, h=23) WRONG!!! no-effect
var r3:Rectangle = new Rectangle( 0, 0, 40, 23 ); //non-zero area plus
var r4:Rectangle = new Rectangle( 0, 0, 0, 100 ); //zero-area but non-zero height
trace( r3.union( r4 ) ); //(x=0, y=0, w=40, h=23) WRONG!!! no-effect
var r5:Rectangle = new Rectangle( 0, 0, 40, 0 ); //zero-area but non-zero height plus
var r6:Rectangle = new Rectangle( 0, 0, 0, 100 ); //zero-area but non-zero height
trace( r5.union( r6 ) ); //(x=0, y=0, w=0, h=100) WHAT??? height is added?? and width is removed??
It sure doesn't fit, for example, this Java reference implementation:
/**
* Computes the union of this <code>Rectangle</code> with the
* specified <code>Rectangle</code>. Returns a new
* <code>Rectangle</code> that
* represents the union of the two rectangles
* @9397041 r the specified <code>Rectangle</code>
* @Return the smallest <code>Rectangle</code> containing both
* the specified <code>Rectangle</code> and this
* <code>Rectangle</code>.
*/
public Rectangle union(Rectangle r) {
int x1 = Math.min(x, r.x);
int x2 = Math.max(x + width, r.x + r.width);
int y1 = Math.min(y, r.y);
int y2 = Math.max(y + height, r.y + r.height);
return new Rectangle (x1, y1, x2 - x1, y2 - y1);
}
That's how I would expect a union operation to work. Add this to the previous chunk of AS3 to see the difference:
trace( union( r1, r2 ) ); //(x=0, y=0, w=100, h=23) //CORRECT
trace( union( r2, r3 ) ); //(x=0, y=0, w=100, h=23) //CORRECT
trace( union( r4, r5 ) ); //(x=0, y=0, w=40, h=100) //CORRECT
function union(r0:Rectangle, r:Rectangle ):Rectangle
{
var x1 = Math.min(r0.x, r.x);
var x2 = Math.max(r0.x + r0.width, r.x + r.width);
var y1 = Math.min(r0.y, r.y);
var y2 = Math.max(r0.y + r0.height, r.y + r.height);
return new Rectangle (x1, y1, x2 - x1, y2 - y1);
}
This bug was completely messing up my Flex-like framework and took forever to track down. I would have never expected such a core and basic math operation like Rectangle.union to be failing. This was causing my autoHeight calculations for custom GUIControls to fail.
The union is supposed to be the smallest rectangle containing both rectangles. If either of the rectangles has zero width and/or zero height, it is a point or a line, but the final rectangle must still contain it. As you can see, Rectangle.union is not working correctly.
