Lab 2: Dot 2 Dot Generator

Learning Outcomes

• Demonstrate competency in many prerequisite areas including:
• Graphical User Interfaces with JavaFX
• Implement a specified algorithm
• Text file input
• Handle exceptions in a robust and meaningful fashion

Overview

Prior to smartphones and tablets, parents resorted to flattened wood pulp and sticks of colored wax to occupy their kids' attention. One popular App for paper and crayons was called "Connect the Dots" or "Dot to Dot." The "screen" consisted of a collection of numbered dots. The user was required to draw lines between consecutive dots. If the user worked the App correctly, a piece of art emerged. In this assignment you will create a generator for dot-to-dot games. The subsequent laboratory assignment will build on this one, allowing you to improve your initial submission based on feedback from your instructor and expand the program's functionality.

Assignment

You must create a program that will read a picture from a .dot file and graphically display the picture stored in the file.

• File
• Open — Loads a .dot file and displays the dots in the file and connects neighboring dots with lines.
• Close — Exits the program (use Platform.exit()).
• Save — Saves a .dot file with the contents of the picture currently being dispalyed.
• Draw
• Lines Only — Redraws the loaded picture drawing only lines (no dots).
• Dots Only — Redraws the loaded picture drawing only dots (no lines).
• Number of Dots — Asks use for number of dots to retain and redraws with fewer dots.

The Draw menu items should only be active when a picture has been loaded.

You may use FXML but are not required to do so.

You will need to add files to the project that implement the GUI for this program. Be sure to add those files to the repo and commit them with the rest of your submission.

Details

Class Structure

You must implement two classes:

• Dot — Represents a dot in the picture.
• Picture — Holds a list of Dots that describe a picture.

The Picture Class

The Picture class must implement the following public instance methods:

• void load(Path path) — Loads all of the dots from a .dot file.
• void save(Path path) — Saves all of the dots to a .dot file.
• void drawDots(Canvas canvas) — Draws each dot in the picture onto the canvas.
• void drawLines(Canvas canvas) — Draws lines between all neighboring dots in the picture on the canvas.
• void removeDots(int numberDesired) — removes all but the numberDesired most criticval dots in the picture. (The critival value of each dot is defined below.)
• If the picture does not have more than numberDesired dots, the method returns without changing the picture.
• If numberDesired < 3, an IllegalArgumentException is thrown

.dot File Format

Your program must be able to read dot files that contain a list of dots. The file is formatted such that each dot is on a separate line. A dot consists of a horizontal and vertical component separated by a comma. Each component is a floating point value between zero and one. For example, square.dot looks like this:

0.1, 0.1
0.1,0.9
0.9,0.9
0.9, 0.1


You can find example .dot files in the data folder in the GitHub repo.

If you'd like to make your own graphic files, you can use the GraphicFileGenerator.jar. The program begins with a file chooser dialog that can be used to select a background image (which you can then trace). Hit cancel if you'd rather just have a black background. To draw, press and hold the mouse down. When you're done, release the mouse. You'll then need to save the points to a file (use the menu).

Drawing Dots

A dot can be drawn on a Canvas by first obtaining the GraphicsContext and then calling the fillOval() method. Be sure to set an appropriate fill color and center the dot over its coordinate location.

Drawing Lines

Lines should be drawn between all neighboring dots, including a line from the last dot back to the first dot. The lines can be drawn on a Canvas by first obtaining the GraphicsContext and then creating a path. To do this:

1. Call beginPath()
2. Move to the location of the first dot by calling moveTo()
3. Draw a line to the next dot by calling lineTo()
4. Repeat the previous step for all dots
5. Call closePath()
6. Call stroke() to draw the path

The Dot Class

The Dotclass class must implement the following methods:

• double static private distance(Dot a, Dot b) that returns the distance between the two dots.
• A public instance method criticalValue(Dot previous, Dot next) that returns the critical value of the dot as defined below.

removeDots() Implementation

Your implementation of the removeDots() method must be consistent with this flowchart:

Calculating the Critical Value of a Dot

The critical value of a dot depends on the relative proximity of it and its immediate neighbors. Consider three dots, labeled 1, 2, and 3, on a straight line. If dot 2 is removed, the connect the dots version of the line from 1 to 3 will look exactly the same. Therefore, we can conclude that the dot is not critical. If dot 2 is significantly far from the line connecting dot 1 and 3, then error would be introduced if dot 2 is eliminated, as shown in Figure 3.

The critical value of dot 2 is calculated as the sum of the distances from dot 2 to dot 1 and from dot 2 to dot 3 minus the distance from dot 1 to dot 3, i.e., $$cv_2 = d_{12} + d_{23} - d_{13}$$

where $$cv_y$$ is the critical value for dot $$y$$ and $$d_{xz}$$ are the distances illustrated below.

Note that in the case of a straight line between dots 1 and 3, $$cv_2 = 0$$

Your program should assume that the first and the last dots are connected so they should be treated as neighbors when calculating their critical values.

Exception Handling

There are a number of situations that could cause your program to throw an exception. For example, if the file is not found, cannot be opened, or contains incorrectly formatted data, it is likely that an exception will be thrown. In these cases, the program should display an useful message in an Alert.

Just For Fun

Ambitious students may wish to:

• Try replacing lineTo() with quadraticCurveTo() or bezierCurveTo().
• Add number annotations next to each dot.
• Use shades of colors to indicate the order in which to connect the dots.
• Overlay the reduced-dot picture on top of the picture with all of the dots in the file. You may wish to display the original picture in a lighter color.
• Toggle between the original and reduced-dot pictures with a key press or mouse click.
• Use levels of gray to indicate the critical value of each dot.
• Create a print to PDF option.
• Create an animation that shows the progression of dots being removed from the picture.
• Add a third dimension (x, y, z) to each dot, develop an algorithm for calculating the critical value in 3D, and create a 3D viewer to allow viewing the object from different perspectives.

Acknowledgment

This laboratory assignment, developed by Dr. Chris Taylor, is motivated by the eighth programming project in chapter 2 of our textbook which is based on the paper: L. J. Latecki and R. Lakamper, "Convexity Rule for Shape Decomposition Based on Discrete Contour Evolution," Computer Vision and Image Understanding (CVIU) 73(1999), pp. 441-454.

See your professor's instructions for details on submission guidelines and due dates.