[squeak-dev] intersect: when intsersects: is false

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Sun Jun 20 13:02:50 UTC 2010


I forgot one property (probably unwanted) :

((100 at 100 corner: 50 at 50) rotateBy: #pi centerAt: 0 at 0) area -> 2500.
Rotating an empty rectangle does not preserve its emptyness.

Nicolas

2010/6/20 Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>:
> Playing with empty rectangles:
> (I'll try to not get caught by a premature gmail send shortcut)
>
> (0 at 0 corner: 0 at 0) containsPoint: 0 at 0 -> false.
> Thus, yes, it is an empty rectangle.
>
> (0 at 0 corner: -1 @ -1) = (0 at 0 corner: 0 at 0) -> false.
> Two empty rectangles can be different though...
>
> (100 @ 100 corner: 50 @ 50) center -> (75 at 75).
> Des not have the same center as (0 at 0 corner: 0 at 0).
>
> ((0 at 0 corner: 0 at 0) merge: (100 @ 100 corner: 50 @ 50)) -> (0 at 0 corner: 50 at 50).
> Merging two empty rectangles can result in a non empty rectangle.
>
>  (100 @ 100 corner: 50 @ 50) area -> 0.
>
> ((0 at 0 corner: 0 at 0)  pointNearestTo: 50 at 100) -> (0 at 0).
> ((0 at 0 corner: -1 @ -1)  pointNearestTo: 50 at 100) -> (-1 at -1).
> ((100 @ 100 corner: 50 @ 50) pointNearestTo: 50 at 100) -> (50 at 50).
>
> ((100 at 100 corner: 50 at 50) intersects: (40 at 40 corner: 110 at 110)) -> true.
> ((100 at 100 corner: 50 at 50) intersect: (40 at 40 corner: 110 at 110)) ->
> (100 at 100 corner: 50 at 50).
> An empty rectangle can intersect a non empty one, though the
> intersection is an empty rectangle. Funny...
>
> All in all, it may not be a good idea to return (0 at 0 corner: 0 at 0) in
> all cases...
> It is just another empty rectangle, maybe not the one you want.
> Maybe we could just implement #isEmpty...
> Oh wait, it is just named #hasPositiveExtent.
>
> Nicolas
>
> 2010/6/20 Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>:
>> 2010/6/20 Joachim Geidel <joachim.geidel at onlinehome.de>:
>>> Whatever is thought to be the "correct" answer, please have a look at the
>>> result of this method in other Smalltalk dialects. I recently had the
>>> unpleasant experience of having to work around minor incompatibilities
>>> between VisualWorks, Squeak and Pharo. Please don't add another one. OTOH,
>>> if it is already different, that would a chance for unification.
>>>
>>> >From the point of view of correctness: There is no such thing as a Rectangle
>>> which is the intersection of non-intersecting rectangles. The "correct"
>>> answer could be to raise an exception, similar to what happens for a
>>> division by zero, or to answer nil. Both would certainly break a lot of
>>> existing code. (0 at 0) corner: (0 at 0) is completely wrong IMO. While it is
>>> empty in a mathematical sense, it would give you answers for #origin and
>>> #corner and many other messages which are complete nonsense. One could just
>>> leave it as it is, because the precondition for answering a "correct"
>>> rectangle is that the receiver and the argument intersect. If the don't, the
>>> answer is undefined, which means that whatever is answered is correct in a
>>> mathematical sense. So the third option besides nil and an exception would
>>> be to document the precondition in the method's comment.
>>>
>>> Whatever you do, please keep it compatible with other Smalltalk dialects!
>>>
>>> Just my 2c.
>>> Joachim Geidel
>>>
>>> Am 20.06.10 10:36 schrieb Frank Shearar:
>>>
>>>> On 2010/06/20 00:58, Jim Rosenberg wrote:
>>>>> [Using Squeak 3.8; apologies if more current versions "fix" this ... ]
>>>>>
>>>>> This expression yields false:
>>>>>
>>>>> ((0 at 0) corner: (50 at 50)) intersects: ((100 at 100) corner: (150 at 150))
>>>>>
>>>>> So, what should this yield?:
>>>>>
>>>>> ((0 at 0) corner: (50 at 50)) intersect: ((100 at 100) corner: (150 at 150))
>>>>>
>>>>> I was expecting perhaps nil. Instead I got (100 at 100) corner: (50 at 50).
>>>>> This is "a surprise". It's certainly not right mathematically ...
>>>>
>>>> It's still that way in trunk, at any rate.
>>>>
>>>> I do think that the current behaviour's wrong.
>>>>
>>>> In the interest of keeping the result of a #intersect: uniform, we could
>>>> return Rectangle origin: (0 at 0) corner: (0 at 0) instead of nil. (And we can
>>>> put that long expression inside a new method,
>>>> Rectangle>>emptyRectangle.) Then we could compose multiple #intersect:s
>>>> without special-casing anything.
>>>>
>>>> I think we just need a guard clause like
>>>>
>>>>      | aPoint left right top bottom |
>>>>      (self intersects: aRectangle) ifFalse: [^ self emptyRectangle].
>>>>
>>>>      "Rest of #intersect goes here."
>>>>
>>>> but I'm sure Nicolas Cellier will weigh in with a definitive answer :)
>>>>
>>>> frank
>>>>
>>>
>>>
>>>
>>>
>>
>> Well, I never have a definitive answer - though I pedantically may seem to :)...
>> What I usually suggest is to put enough brain storming to help
>> reaching an answer that is least surprising indeed.
>> To me, least-surprising includes:
>> - uniform thru the library
>> - mathematically well grounded
>> The other rationale to be taken into account is simplicity.
>> And of course, cross-dialect compatibility is another pragmatic POV.
>>
>> Nicolas
>>
>



More information about the Squeak-dev mailing list