[Apologies in advance if this has been discussed up here before ...]
Grumble grumble grumble grumble. Grrr! Consider the case of rectangle a and rectangle b where a happens to be "degenerate" in the sense that it has 0 area -- let's say that a origin y = a corner y -- i.e. if you draw a it looks like a horizontal line. And let's say that if you draw these two rectangles, a "goes inside the area of" b. Do they intersect? I'd sure say yes. Squeak 3.8 says yes. Squeak 4.3 says no. *BUT* a intersect: b in Squeak 4.3 *does return* the part of a that's inside b. Looking at the code for Rectangle >> intersect: in 4.3, it sure looks to me like this behavior was introduced rather explicitly and deliberately. But is it correct? I'd say no. I'd say no-brainer no. I guess maybe somebody is thinking that Rectangle >> intersects: should produce an answer that agrees with the question: does a possible intersection have area greater than 0? Well, sorry, but I don't think that's the right question. The right question is: do the two rectangles have points in common? I have code that was very mysteriously broken by this; I've created a degenerate rectangle out of a line *on purpose* just to be able to get the intersection of a line and a rectangle. I don't see any reason why I shouldn't be able to do this. Set theory says I can do it. Geometry says I can do it. Squeak 3.8 says I can do it. So: whichever committer out there decided that a degenerate rectangle can't intersect, what exactly will I break if I put back the [correct, ahem ...] 3.8 behavior of Rectangle >> intersect: in 4.3? I say: put the old behavior back. It wasn't wrong. The new behavior is wrong. -Thanks, Jim |
Well, the old behavior of intersects: was wrong with respect to intersect:
This is because intersect: answer an "empty" rectangle (negative width or height). Such intersection HAS TO BE EMPTY, and thus cannot intersects: anything... To accomodate the degenerated case (one null dimension, the other positive or null) we can change the final tests to strict inequalities. OK? Nicolas 2013/1/15 Jim Rosenberg <[hidden email]>: > [Apologies in advance if this has been discussed up here before ...] > > Grumble grumble grumble grumble. Grrr! > > Consider the case of rectangle a and rectangle b where a happens to be > "degenerate" in the sense that it has 0 area -- let's say that a origin y = > a corner y -- i.e. if you draw a it looks like a horizontal line. And let's > say that if you draw these two rectangles, a "goes inside the area of" b. Do > they intersect? I'd sure say yes. Squeak 3.8 says yes. Squeak 4.3 says no. > *BUT* a intersect: b in Squeak 4.3 *does return* the part of a that's inside > b. > > Looking at the code for Rectangle >> intersect: in 4.3, it sure looks to me > like this behavior was introduced rather explicitly and deliberately. > > But is it correct? I'd say no. I'd say no-brainer no. I guess maybe somebody > is thinking that Rectangle >> intersects: should produce an answer that > agrees with the question: does a possible intersection have area greater > than 0? Well, sorry, but I don't think that's the right question. The right > question is: do the two rectangles have points in common? > > I have code that was very mysteriously broken by this; I've created a > degenerate rectangle out of a line *on purpose* just to be able to get the > intersection of a line and a rectangle. I don't see any reason why I > shouldn't be able to do this. Set theory says I can do it. Geometry says I > can do it. Squeak 3.8 says I can do it. > > So: whichever committer out there decided that a degenerate rectangle can't > intersect, what exactly will I break if I put back the [correct, ahem ...] > 3.8 behavior of Rectangle >> intersect: in 4.3? > > I say: put the old behavior back. It wasn't wrong. The new behavior is > wrong. > > -Thanks, Jim > |
--On Tuesday, January 15, 2013 01:49:26 +0100 Nicolas Cellier
<[hidden email]> wrote: > Well, the old behavior of intersects: was wrong with respect to intersect: > > This is because intersect: answer an "empty" rectangle (negative width > or height). > Such intersection HAS TO BE EMPTY, and thus cannot intersects: anything... > > To accomodate the degenerated case (one null dimension, the other > positive or null) we can change the final tests to strict > inequalities. OK? Hmm ... I guess changing to strict inequality would be OK with *me* -- as far as not breaking any of my own code -- but I'm still wondering whether silently returning false from Rectangle >> intersects: in the case of "negative height" or "negative width" is the right behavior. The issue here, as I understand it, is that a "rectangle" where the origin and corner are not top-left and bottom-right is "incorrectly specified". So, if Rectangle >> intersects: can't really handle an incorrectly specified rectangle, should it return false, or throw an error? Of course changing the behavior to throw an error could break somebody else's code, which I wouldn't want to do. What should Rectangle origin: (25@250) corner: (100@100) produce? A rectangle starting from (25@250) and ending at (100@100) certainly makes semantic sense. But it's "incorrectly specified". Should it throw an error? Should it produce the same thing as Rectangle origin: (25@100) corner: (100@250)? Should there be a new class method, say Rectangle from: (25@250 to: (100@100) which would be guaranteed to produce the rectangle with origin (25@100) and corner (100@250)? Should Rectangle >> intersects: "normalize" both the receiver and argument before calculating whether things intersect? What "is" a rectangle? How is the Squeak user supposed to know? There are at least two interpretations of what "rectangle" might mean: (1) a 4-sided polygon where all 4 sides are strictly horizontal or strictly vertical, determined by two diagonally opposite points. (2) a 4-sided polygon where all 4 sides are strictly horizontal or strictly vertical, determined by the top-left point ("origin") and bottom-right point ("corner"). Maybe I'm being unfair, but it seems to me things aren't really clear from one method to the next what the semantics are supposed to be. I'm getting the idea that the intent is that the semantics of "rectangle" are supposed to be (2). Well, OK, as long as we all know that; but in this case, shouldn't Rectangle origin: (25@250) corner: (100@100) throw an error? But then that's almost certain to break *somebody's* code ... It's a puzzle. |
In reply to this post by Nicolas Cellier
I understand how brittle it may seem...
But that's how #intersect: works, when there is no intersection, it answers a Rectangle with negative width and/or height So we have not that many options... (unless we go in tons of rewrites and broken compatibility). I took above feature as granted, rationalized the implementation stating that rectangle with negative width/height is empty, and documented it with SUnit TestCase That's the minimum change that can possibly work. I just was a bit too zealous, there is a thin line between empty and empty, thanks for raising your voice, it's now corrected in trunk :) If you change #origin:corner: to either answer a correct Rectangle or raise an Error, you'll break #intersect: and maybe other senders who knows... There is a #vertex:vertex: creation message in Visualworks for exactly that purpose... In Squeak, it seems we never had the need/idea of it, but you can also write it ^Rectangle encompassing: {vertex1. vertex2}. Note that #intersect: #intersects: and #areasOutside: are essential for Morphic redrawing for example... Nicolas 2013/1/17 Jim Rosenberg <[hidden email]>: > --On Tuesday, January 15, 2013 01:49:26 +0100 Nicolas Cellier > <[hidden email]> wrote: > >> Well, the old behavior of intersects: was wrong with respect to intersect: >> >> This is because intersect: answer an "empty" rectangle (negative width >> or height). >> Such intersection HAS TO BE EMPTY, and thus cannot intersects: anything... >> >> To accomodate the degenerated case (one null dimension, the other >> positive or null) we can change the final tests to strict >> inequalities. OK? > > > Hmm ... > > I guess changing to strict inequality would be OK with *me* -- as far as not > breaking any of my own code -- but I'm still wondering whether silently > returning false from Rectangle >> intersects: in the case of "negative > height" or "negative width" is the right behavior. > > The issue here, as I understand it, is that a "rectangle" where the origin > and corner are not top-left and bottom-right is "incorrectly specified". So, > if Rectangle >> intersects: can't really handle an incorrectly specified > rectangle, should it return false, or throw an error? > > Of course changing the behavior to throw an error could break somebody > else's code, which I wouldn't want to do. > > What should Rectangle origin: (25@250) corner: (100@100) produce? A > rectangle starting from (25@250) and ending at (100@100) certainly makes > semantic sense. But it's "incorrectly specified". Should it throw an error? > Should it produce the same thing as > Rectangle origin: (25@100) corner: (100@250)? Should there be a new class > method, say Rectangle from: (25@250 to: (100@100) which would be guaranteed > to produce the rectangle with origin (25@100) and corner (100@250)? Should > Rectangle >> intersects: "normalize" both the receiver and argument before > calculating whether things intersect? > > What "is" a rectangle? How is the Squeak user supposed to know? There are at > least two interpretations of what "rectangle" might mean: > > (1) a 4-sided polygon where all 4 sides are strictly horizontal or strictly > vertical, determined by two diagonally opposite points. > > (2) a 4-sided polygon where all 4 sides are strictly horizontal or strictly > vertical, determined by the top-left point ("origin") and bottom-right point > ("corner"). > > Maybe I'm being unfair, but it seems to me things aren't really clear from > one method to the next what the semantics are supposed to be. I'm getting > the idea that the intent is that the semantics of "rectangle" are supposed > to be (2). Well, OK, as long as we all know that; but in this case, > shouldn't Rectangle origin: (25@250) corner: (100@100) throw an error? > > But then that's almost certain to break *somebody's* code ... > > It's a puzzle. > |
Free forum by Nabble | Edit this page |