[plt-dev] 2htdp/image: Where oh where have my pinholes gone?

From: Carl Eastlund (carl.eastlund at gmail.com)
Date: Wed Jan 13 11:42:20 EST 2010

On Wed, Jan 13, 2010 at 11:23 AM, Robby Findler
<robby at eecs.northwestern.edu> wrote:
> Generally sounds like a good idea to me (not for this release, tho).

Thanks.  And I certainly wouldn't expect a change like this by the
upcoming release.

> As a minor variation on this, the pinhole property of an image could
> either be #f or a pair of numbers and the existence of a pinhole could
> trigger drawing it (always). So your animation code would strip the
> pinhole at the end, via a remove-pinhole function. Drawing a pinhole
> would probably be a matter of drawing a horizontal and a vertical
> black line with 50% opacity going thru the whole image that intersects
> the coordinates of the pinhole. Something like that.

Exactly what I had in mind.  Except for the part about always drawing
the pinhole, and removing it for animations.  I hadn't thought of that
-- it's a clever addition.  I like it.

I wouldn't want the default pinhole drawing to pass through the image.
 That makes it harder to see if the contents of the image are the
same, for any pixels that fall under that black line.  Single pixels
can matter.  I'd rather have something just at the edges.  I recognize
that for a large image, that can become hard to interpolate the
pinhole point, which is why I suggested the numeric display.

Maybe we can make the display more interactive, like syntax snips are.
 Give right-click options for show pinhole / hide pinhole / numeric
pinhole, etc.

> This would also make it easier to explain (thinking of the docs) since
> you could put all pinhole-related discussion at the end.

Yes, certainly.  Shapes are "Beginner Image"; overlays are
"Intermediate Image"; pinholes come in "Intermediate Image with
Pinholes".  Don't discuss the advanced stuff until you graduate to
that language... er, image level.

> Oh, and probably it would be nice to have a function called
> center-pinhole that takes an image and puts the pinhole in the middle,
> since I imagine it would get used a lot (in favor of the more verbose
> (align-pinhole i 'center 'center)).

Plenty of room for abbrevations: center-pinhole, remove-pinhole, etc.

> And to repeat what I wrote before, I think you want to have the
> current overlay/underlay/beside/above functions "pinhole" as x-place
> and/or y-place arguments instead of adding the overlay/pinhole
> function.

I wouldn't want to separate the x- and y-coordinates of a pinhole.
That seems a very strange thing to me.  I would at least want
overlay/pinhole as a shorthand.

--Carl

> On Wed, Jan 13, 2010 at 10:12 AM, Carl Eastlund <carl.eastlund at gmail.com> wrote:
>> Okay, I'll make a proposal that hopefully gives us enough cake to both
>> eat and have.
>>
>> Add the following primitives to 2htdp/image (some are, of course, familiar):
>>
>> (put-pinhole i x y) ;; produce an image with i's appearance, and
>> pinhole at (x,y)
>> (move-pinhole i dx dy) ;; for i with pinhole (x,y), produce i with
>> pinhole (x+dx,y+dy)
>> (align-pinhole i ax ay) ;; align pinhole of i at top/middle/bottom,
>> left/middle/right, etc.
>> (image-pinhole-x i) ;; get pinhole x coord
>> (image-pinhole-y i) ;; get pinhole y coord
>> (overlay/pinhole i1 i2 is ...) ;; overlay images on their pinholes
>>
>> The above allows arbitrary "pinhole math" to line up images.  It also
>> allows someone who has "graduated" to using pinholes to achieve all
>> the non-pinhole combinations using just the pinholes.
>>
>> Preserve the following equalities for the existing combination functions:
>>
>> (overlay is ...) =
>>  (put-pinhole (overlay/pinhole (put-pinhole i 0 0) ...) 0 0)
>> (overlay/xy i1 x y i2) =
>>  (put-pinhole (overlay/pinhole (put-pinhole i1 x y) (put-pinhole i2 0 0)) 0 0)
>> (overlay/align ax ay is ...) =
>>  (put-pinhole (overlay/pinhole (align-pinhole is ax ay) ...) 0 0)
>>
>> They don't need to be implemented that way, but the behavior should be
>> like that: the normal over/underlay functions (a) always ignore the
>> pinhole of the source images, and (b) always produce an image with
>> pinhole at (0,0).
>>
>> Most importantly, though, any program that doesn't use the explicit
>> "pinhole" primitives should never produce an image with a pinhole
>> anywhere other than (0,0).
>>
>> Once a program gets around to using pinholes, they are important and
>> should be respected by equality.  Otherwise you can combine two sets
>> of images that are pairwise "equal" but get different result images.
>> However, for the reasons Matthias described below, an image with a
>> pinhole on it should be visually distinguishable from one without, or
>> with a different pinhole.  So I propose that, at the REPL or in
>> check-expect dialogs, a pinhole should be given an explicit rendering.
>>  There should be a box around the image, and it should either have
>> sort of "targeting" marks at the x and y positions of the pinhole, or
>> it should just have text similar to "pinhole = (10,-30)".  On an
>> animation canvas, of course, this should not show up.
>>
>> This raises the question of whether "with a pinhole" recognizes images
>> with an explicit pinhole of (0,0) from images with no pinhole at all;
>> it is not the most critical thing, but I think for a program that sets
>> pinholes consistently, it would be nice to always have the border, and
>> thus distinguish "no pinhole" from "pinhole at (0,0)", if only in this
>> one place.
>>
>> I think this proposable is implementable, and I think it addresses the
>> issues I have seen, both for people who want pinholes and for people
>> who want pinhole-free image programming.
>>
>> How does this sound?  Do we like it?  Do we think pinholes are useful
>> enough to try to fit them into the 2htdp design constraints?
>>
>> Carl Eastlund
>>
>> On Wed, Jan 13, 2010 at 10:23 AM, Matthias Felleisen
>> <matthias at ccs.neu.edu> wrote:
>>>
>>> To clarify:
>>>
>>> Say you run a test like this:
>>>
>>>  (check-expect (image-producing-function 1 "true")
>>> expression-that-creates-expected-image)
>>>
>>> and it fails. Naturally, you do this in the REPL:
>>>
>>>> (image-producing-function 1 "true")
>>> some-image
>>>> expression-that-creates-expected-image
>>> an-image-that-looks-exactly-like-some-image
>>>
>>> ;; you're confused and you run an equality check:
>>>
>>>> (equal? (image-producing-function 1 "true")
>>>> expression-that-creates-expected-image)
>>> false
>>>
>>> Now you're really confused, and you're angry, because clearly there must be
>>> a bug in this damn software that your instructor imposes on you even though
>>> everyone knows that in a first course you should learn Java or at least C++,
>>> well may be Basic. So you stomp into your professors office and yell. At
>>> that point he pulls out a standard function -- not in the released library
>>> mind you -- and shows you're just not thinking properly:
>>>
>>>> (image+pinhole (image-producing-function 1 "true"))
>>> some-image
>>>> (image+pinhole expression-that-creates-expected-image)
>>> an-image-that-looks-different-from-some-image
>>>
>>> So now that you have been shown off again, you know what's going on. This
>>> guy is just trying to humiliate you. You are going to write a bad eval for
>>> him and you're going to bad-mouth this stupid software wherever you can.
>>>
>>> ;; ---
>>>
>>> The above account is fictional. All possible connections between the
>>> characters and real-life people is coincidence.

--Carl


Posted on the dev mailing list.