CS 134 Homework Laboratory # 3
Working on the Chain Gang

Objective: To gain experience implementing classes and methods.
Note that you must bring a program design to lab this week!

The Scenario.

For this lab, we would like you to write a program that simulates the motion of the links of a peculiar type of chain known as a Gunter's or surveyor's chain. While most chains are made by interlocking links that are shaped like ovals, each link of a Gunter's chain is actually a bar with a small hook at each end. Such chains were used by surveyors to measure land from their invention by Edmund Gunter in 1620 until the development of steel measuring tapes in the mid 1800's. A handle was connected to each end of the chain to make it easy to stretch the chain over the distance to be measured and markers were attached at regular intervals to facilitate measurement. The first image below is a picture of an actual surveyor's chain.

To give you a better sense of how it is constructed, a chain composed of just two segments is shown below:

The goal of this lab will be to write a program that will draw a simplified picture of such a chain on the screen and then simulate the way the chain would move as someone pulled on its individual links. In the drawing your program displays, each link should be drawn by connecting two small FilledOvals with a Line connecting their centers. Thus, your program's representation of the two links shown above will look something like:

Your program's simulation of the motion of the links should be based on the assumption that when one end of a link is moved, the other end will move to a new position that is as close to its old position as possible such that the two ends of the link are as far apart as they were before either end was moved. The figure shown below illustrates the geometry of this motion.

In this diagram, the ends of the link are labeled "A" and "B". The original position of the link is shown in gray while its position after the move is complete is shown in black. The figure depicts how the link would move if hook "A" was dragged from its original position along the arrow to the new position shown in black. The circle around the new position of "A" represents all the points that are separated from A's position by the length of the link. B must move to a position on this circle. The closest point on this circle from B's original position will fall on the line from B's original position to A's new position as shown. Given this figure and the patience to do a bit of algebra, you should be able to derive a formula for the new position of B as a function of the length of the link, the new position of A, and the original position of B (note that the original position of A will not be used in this formula).

Program organization

Your solution to this exercise should be completed by writing three classes:

Hook
- The Hook class will simulate the behavior of one of the hooks at the end of a Link.
Link
- The Link class will simulate the behavior of a single link. Each Link will be composed of two Hooks and a Line.
ChainController
- The ChainController class will extend WindowController. It will handle mouse actions by deciding which Hook (if any) is being dragged by the mouse and invoking the appropriate method to move such Hooks.

Constructors

The constructor for the Link class should take three parameters: the x and y coordinates of the center of one of the Link's Hooks and the drawing canvas. The Link created should have one Hook located so that its center is at the point whose coordinates are provided as parameters. The other Hook should be placed so that the Link initially appears horizontally on the screen. The length of each Link should be determined by a constant (final) variable defined in the Link class.

The constructor for the Hook class will take four parameters: the Link to which it belongs, the x and y coordinates of its center and the drawing canvas. Each Hook will need to know the Link to which it belongs because when a Hook is moved it will need to tell the Link that its other components (the Hook at the other end and the Line connecting them) may need to be moved as well. The radius of each Hook should be determined by a constant defined in the Hook class.

Methods

The Hook class will implement several methods whose names are identical to methods associated with graphical objects including moveTo, contains, getLocation, getX, and getY. The contains method should work exactly as it would if the Hook were just the FilledOval that represents it on the screen. The behavior of the other methods, however, will be slightly different from those associated with a simple FilledOval. The getLocation, getX, and getY methods should return the location and coordinates of the center of the oval rather than of the point at the upper left corner of the bounding rectangle.

Your version of moveTo should expect a Location as a parameter (rather than separate x and y coordinates). The moveTo method should move the oval so that its center falls at the Location provided as a parameter. In addition, if the Location to which the Hook is moved is significantly different from its former position, the code of the moveTo method should invoke a method of the Link object named adjustTo which repositions the remaining components of the Link to reflect the new position of the Hook.

The fact that moveTo may call adjustTo is what makes the phrase "significantly different from its former position" critical. When you move the Hook at one end of a Link, its moveTo method will call adjustTo to reposition the other components of the Link. The adjustTo method will (among other things) invoke the moveTo method on the Hook at the other end of the Link. This Hook will in turn invoke the adjustTo method of the Link to reposition the Hook at the other end, which is, of course, the Link we moved in the first place. The two Hooks would keep trying over and over again to reposition one another if it were not for the fact that we stated that moveTo should only invoke adjustTo if the new position of the Hook is significantly different from it's former position. Here, "significantly different" means big enough to be apparent on the screen. As a result, if the distance from the Hook's old position to its new position is less that 1/2 pixel, we can safely say this is not significant. The distanceTo method of the Location class can be used to perform this check.

Finally, the Hook class should implement a hookUp method that can be used to connect two Hooks from different Links to form a chain. The hookUp method will take another Hook as a parameter. It will move the other Hook to the position of the Hook on which the method was invoked. It will also set an instance variable so that the Hook on which it was invoked can remember the other Hook and refer to it later. In particular, whenever the moveTo method invokes adjustTo it should also invoke moveTo on the Hook (if any) to which it has been connected by the hookUp method.

To connect two Hooks, your ChainController will need to invoke hookUp on each Hook. That is, if a and b are the names of two Hooks, to connect them you would execute the pair of invocations:

 a.hookUp(b);
 b.hookUp(a);
 

In summary, the Hook class should provide the following methods. Note that we give complete method headers below, illustrating how you should define the methods in your own class.

  • public double getX()

  • public double getY()

  • public void moveTo( Location destination )

  • public boolean contains( Location point )

  • public Location getLocation()

The Link class should implement three methods named contains, touchedHook, and, as mentioned above, adjustTo.

The adjustTo method will take the Hook that invokes it as a parameter. This will be the Hook that has just moved and will enable the Link to figure out which of its two Hooks is the one that may need to have its position adjusted.

The contains method should take a Location parameter and return true only if one of the Link's two Hooks contains that Location. The contains method should therefore ignore the Line connecting the two Hooks.

The touchedHook method should take a Location parameter and return the Hook (if any) that contains that Location. Your program should be designed to use contains to ensure that one of the Hooks that belong to the Link will contain the Location before invoking this method.

The methods to be included in the Hook class are summarized below:

Design document

This week, you should bring a design for your program with you to lab. The design should show us how you plan to organize your three classes to accomplish the actions required. We have told you what methods each class should have and the behavior that they should provide. You should write (in English, not Java) your plan for how each method will provide the necessary behavior. You should also describe (in English) what variables you feel are necessary for each class. This level of preparation will allow you to progress much more quickly in lab so that you can take better advantage of the presence of the instructors and TAs. For this lab, we will give you feedback on the design. In later labs, we will grade those designs as well.

To give you a better sense of what we mean by a written design, you can see a sample design for the first part of the laundry lab.

Development Plan

Rather than attempting to implement all the features described above at once, you should first work on implementing the methods required to get a single Link constructed and moving properly. In particular this will enable you to

You can use the mouse to manipulate the links shown below to see how this final version of your program should behave.



Once you have a single Link moving correctly:

You can use the mouse to manipulate the links shown below to see how this final version of your program should behave.



Extra Credit

If you get bored playing with a chain with only two links, you could try to build a WindowController for this program that manipulates a longer chain. To do this, you will probably want to add methods name getStart and getEnd to the Link class which will return the Hooks at the ends of the Link. This will make it easier to connect Links as you create them by hooking the end of one link to the start of the next.

If you try this, to keep things simple don't try to make it possible to grab any Hook along the whole chain. Just keep track of two links as we had you do in the "standard" version of the program and only let the user grab the Hooks on these Links. The first and the last Links on the chain are the obvious choices.

We have created such a program for you to play with. Our program lets you make the chain as long as you like. Each time you click the mouse, a new Link is added to the end of the chain. As we suggested, however, you can only drag the chain by grabbing either the first or last Link.



Debugging Tip

If your formula for determining how to adjust the position of one end of a Link when the other is dragged is incorrect, your program may behave very badly. The problem relates to the idea that moveTo should only invoke the adjustTo method of a Hook's Link if the Hook's position has changed significantly. When the correct formula is used to position Hooks, the adjustTo method will quickly discover that both Hooks have been moved to compatible positions (i.e. the are separated by one length of a Link) and no further "signficant" motion will occur. If the formula is wrong, however, the Hooks at either end may end up trying to adjust each other's position forever. In this case, your program will quickly report a "StackOverflowException" but provide no other useful feedback on how your formula is in error.

A simple change to your program will help you correct the error in this situation:

If your formula is incorrect, this version of the program will still not work correctly, but you should be able to get a clue what is wrong with your formula since you will now be able to see Hooks moving to unexpected position. Once you do get the formula correct, change adjustTo so that it uses moveTo again since this will be required to make things work when you link Hooks together to form chains.

Creating your project and classes

The process of creating an Eclipse project for this lab and the ChainController class will be roughly the same as the process you followed while completing the laundry lab:

  1. Open the File Menu. Select New and then Project.
  2. Select Java, then select Java Project, and then Next.
  3. Enter "Chains" as the Project name.
  4. Select the Libraries tab.
  5. Click Add variable.
  6. Select OBJECTDRAW from the list and click OK.
  7. Click Finish.
You now have an empty project to which you should add a Java file for your WindowController class:
  1. Click on "Chains" in the Package Explorer panel on the left side of the Eclipse window.
  2. Open the File Menu. Select New and then Class.
  3. Enter "ChainController" as the Name of the class.
  4. Enter "WindowController" as the Superclass.
  5. Click Finish.
  6. You should now have a ChainController.java file inside the Chains project. Be sure to modify the file so that it starts with import objectdraw.*;
In addition, you will need to create the two other classes required to complete this assignment:
  1. Click on "Chains" in the Package Explorer panel on the left side of the Eclipse window.
  2. Open the File Menu. Select New and then Class.
  3. Enter "Link" as the Name of the class.
  4. Click Finish.
  5. Open the File Menu. Select New and then Class.
  6. Enter "Hook" as the Name of the class.
  7. Click Finish.
  8. You should now have Hook.java and Link.java files inside the Chains project. Be sure to modify these files so that they start with import objectdraw.*;

Due Dates

This assignment is due at 11 pm on Wednesday for students in the Monday lab. It is due at 11 pm on Thursday for those in the Tuesday lab.

Submitting Your Work

Before submitting your work, make sure that each of the .java files includes a comment containing your name. Also, before turning in your work, be sure to double check both its logical organization and your style of presentation. Make your code as clear as possible and include appropriate comments describing major sections of code and declarations. Use the Format command in the Source menu to make sure your indentation is all consistent.

Turn in your project the same as in past weeks. Use the Export command from the File menu. Check that the Chains project is being exported to a new folder whose name includes your name and identifies the lab. Then quit Eclipse, connect to Cortland, and drag your folder to the appropriate dropoff folder on Cortland.

Grading Point Allocations

Value
Feature
Style (8 pts total)
2 pts. Descriptive comments
2 pts. Good names
2 pts. Good use of constants
2 pts. Appropriate formatting
Logical Organization (4 pts total)
2 pts. Good use of boolean expressions
1 pt. Not doing more work than necessary
1 pt. Using most appropriate methods
Correctness (8 pts total)
1 pt. Drawing links correctly at startup
1 pt. Ability to move any of the Hooks independently
2 pt. Keeping parts of a Link together as Hook is moved
2 pt. Able to connect two hooks together
2 pt. No other problems

 

Sample Design

This section shows the sample design for the first part of the laundry lab. Use this to help you understand what to include in your own sample design.

The laundry lab includes constants for the following values:

The program contains the following instance variables:

begin method - creates the display and initializes the correct basket. It does this as follows:

onMouseClick method - checks if the user clicks the mouse in the correct basket, and then changes the color of the laundry. It does this as follows:


Computer Science 134
Department of Computer Science
Williams College