Last updated: Wed, 1 Apr 2015 21:16:04 -0400
DUE: Monday 4/6/2015, 9pm EST
Use the full Racket language to complete this assignment. Enable it by adding #lang racket (case-sensitive) at the top of the file. In addition, the Choose Language... menu located at the bottom-left of the DrRacket window must be set to Determine language from source.
Put all your solution files in a directory named set11 in your repository.
Download extras.rkt to this directory (right-click and choose "Save As"; don’t copy and paste) and commit it as well.
Use begin-for-test and rackunit to define your examples and tests.
- Don’t forget to tell us how many hours you spent working on the assignment. This should be a global variable called TIME-ON-TASK in each file. For example:
(define TIME-ON-TASK 10.5) ; hours
- So each solution file must have at least the following at the top:
(require "extras.rkt") (require rackunit) (define TIME-ON-TASK <number-of-hours-you-spent>)
- After you’ve submitted your solution, use a web browser to go to https://github.ccs.neu.edu/ and check that your repository contains the following files:
Git Commit Requirement: For this assignment, you must have at least three well-labeled git commits (including the final commit). A well-labeled git commit accurately and succinctly describes the changes since the previous commit. Something like "commit2", or "home work 3" is not an acceptable git commit label. Failure to meet this requirement will result in loss of points.
(check-location "11" "draw.rkt")
For rectangles, the point where the user begins dragging becomes one corner, and the place where the drag completes becomes the opposite corner. The user can do this in any direction, so the corners might be the "northwest and southeast" corners, or the "northeast and southwest"
For circles, the point where the drag gesture begins becomes the center of the circle and the end of the drag becomes a point on the circumference of the circle. The shape is always a true circle: an ellipse or an oval cannot be created.
For rectangles, the control regions are rectangular areas around the corners. Specifically, a "button-down" within 5 pixels in both the x and y axes of the true corner of the rectange must be considered a hit to the control region. Any of the four corners can act as the central point for such a region.
For circles, the control regions are anywhere within 2 pixels of the circumference of the circle. That means if the radius is r and the user presses the mouse button down at a distance as little as r-2 pixels from the circle’s center, or up to r+2 pixels, then the user has hit the control region.
When resizing a rectangle, the originally-selected corner moves while the opposite corner (called the "stationary corner") stays put. The corners can change their geographical relationship to one another while this is happening. For example, the user may begin by dragging the "southeast" corner of a rectange and drag it so far to the north that it becomes a "northeast" corner; the user can continue dragging until it becomes the "northwest" corner. The invariant is that there is always a corner at the spot where the mouse is (during the drag gesture) and there is always a corner at the spot where the stationary corner began.
When resizing a circle, the center of the circle remains where it is, and the radius of the circle changes so that the mouse is always on the circumference.
When resizing, the actual mouse position dictates the exact corner position (for rectangles) or circumference point (for circles). That means that if the user first presses the mouse button at a point 3 pixels away from the rectangle’s corner, the corner will snap to that position immediately. The position where the mouse button finally goes up becomes the new corner. That’s in contrast to the way moves are handled, with "smooth dragging."
The final effect of any drag gesture must ultimately be determined by the position where the "button-up" event occurs, not the final "drag" event. The shapes must, of course, be updated during the drag gesture as well.
- Don’t assume anything about the sequence of events you will receive, except as follows:
A "drag" event will always be surrounded by a preceding "button-down" event and a following "button-up" event.
You can assume that the mouse pointer stays within the canvas window at all times. It does not matter what your program does if the user moves the mouse outside the window. (Racket’s behavior is different on different platforms, like Mac, Windows and Linux.)
Do not assume anything about the x and y coordinates of the events you receive. Sequential events can differ by small or large amounts at any time; they may differ by nothing at all.
A "button-up" event may come in at a different position from the preceding "drag" event, a "drag" event can be at a different position from a preceding "button-down" event, and likewise "move" events can differ from their neighbors. Or successive events can be at the same (x, y) positions.
; A BoundingBox is a (list Coordinate Coordinate Coordinate Coordinate) ; INTERPRETATION: (list left top right bottom). ; A BoundingBox represents a box whose left x-coordinate is at "left", whose ; top y-coordinate is at "top", whose right x-coordinate is at "right", and whose ; bottom y-coordinate is at "bottom".
; INITIAL-WORLD : World ; An initial world, with no Shape<%>s. ; handle-mouse : World Coordinate Coordinate MouseEvent -> World ; GIVEN: A World, mouse coordinates, and a MouseEvent ; RETURNS: A new World, like the given one, updated to reflect the action of ; the mouse event, in the ways specified in the problem set. ; get-world-shapes : World -> ListOf<Shape<%>> ; GIVEN: A World, ; RETURNS: All the Shape<%>s which make up that world, i.e. all those that ; have been created by the user through using the tools. ; create-circle : posn Integer -> Shape<%> ; GIVEN: A center point and a radius ; RETURNS: A new Circle% object (implementing Shape<%>) with its center at ; the given point and radius as given. ; create-rectangle : BoundingBox -> Shape<%> ; GIVEN: A bounding box, ; RETURNS: A new Rectangle% object (implementing Shape<%>) which is bounded ; by the given BoundingBox.
See the demo video below, which shows the behaviors the program should exhibit. In case there is any disagreement between the video and the requirements above, the requirements take precedence.