CS-321 Lab 5:
Transformations in 2 dimensions
& Bezier Curves

Overview
 

This is a 2-week lab.

In this lab, you will be adding an additional shape - Bezier Curve - to your collection. This activity can be deferred to the second week of the lab.

Additionally, you'll be integrating the transformation methods you have learned about in class recently into your existing GUI application (from Lab 4). Once you incorporate 2-D transformations into the program, you will be able to rotate, pan (translate), and scale (zoom/unzoom) the shapes you create and display.

The transformations will be carried out via a ViewContext object that you create and manage from within your derived shell. Based on user input to your modified GUI, the you'll call methods of ViewContext to internally set up the necessary transformation that applies rotation, translation, and scaling for converting from one set of coordinates to another (from model coordinates to window coordinates). Furthermore, the ViewContext object must support the inverse transform as well: converting from window coordinates to model coordinates.

In addition to the usual DrawArea pointer, you will now also pass a pointer to the ViewContext object to your image, and subsequently to all the shapes, as part of the Draw sequence. Each derived shape will then use the transformation methods of the ViewContext object to convert it's local modelling coordinates into window coordinates, such that the shape appears in the window in the desired transformed position.

In a similar fashion, when you create new shapes via mouse input, you will have to convert mouse coordinates (which are natively generated in window coordinates) to model coordinates, so that the shape is initialized with model coordinates rather than window coordinates.

Here is the UML class diagram illustrating the relationship between the classes, including the new ViewContext class:

 

Activities

  1. If you haven't done so already, implement the capability in your image class to Read and Write your shape collection to and from a file. This will be similar to what you had done in Lab 2, but now you must add the color and line style attributes to your file format so that the information is saved during a file write. You will also have to create a format for representing polygons with their variable vertex count. Also, keep in mind that your shapes must save their constituent coordinates as model coordinates, not window coordinates.
     
  2. Add more UI controls to the mainLayout of your derived shell. such that you implement a UI for panning (translating) right, left, up, and down, as well as rotating CW and CCW. The Pan buttons, when pressed, should cause the image to move by an amount which is 10% of the window extent. The Rotate buttons should rotate 5 degrees with each button press. You can get 10 extra credit points by implementing this using controls other than buttons. More information below.
     
  3. Develop the ViewContext class built around a matrix class. It is recommended that you use this matrix class class, which is free for educational use, as the transformation "engine" of your ViewContext class. The recommended matrix class makes it very easy for you to perform operations such as matrix multiplication or matrix inversion (see the accompanying documentation and this sample code). Your ViewContext class should contain two matrix objects - one (S) for scaling and one (T) for the combined translation-rotation. You may want a third matrix member that contains the matrix product T*S; similarly, you may want a fourth matrix member that contains the inverse of the matrix product.

    Note: The constructor of the ViewContext class should be written such that, initially, the transformation parameters are neutral; that is, no rotation, no translation, and no scaling. (T=I and S=I). This implies that the model and windows coordinate systems are coincident to start out with.

    Provide the setXXX() mutator methods indicated in the UML class diagram to the ViewContext class that allow you, via the derived shell UI, to manipulate the transformation parameters of the ViewContext object. Whenever one of the mutator methods is invoked, the internal transformation matrix of the ViewContext object should be re-formed.

    Whenever it is time to update the display, your derived shapes' Draw methods should invoke the ViewContext ModelToWindow() method to compute the window coordinates corresponding to each constituent model coordinate. These computed window coordinates are then the ones passed into the QPainter drawXXX() methods. Note that you must never modify the stored coordinates of the derived shapes; once a shape is created, its model coordinates remain invariant - only the computed window coordinates (used for drawing purposes) change.

    Similarly, when you are creating a new shape with via mouse input, use the ViewContext WindowToModel() method to convert mouse coordinates to model coordinates, which you use to initialize the shape.
     

  4. Implement the virtual functions inherited from Shell for Zoom, Unzoom, and Reset.

    The Zoom and Unzoom button should apply a scale factor of 2 to the transformation each time the button is pressed. Conversely, Unzoom should halve the scaling factor with each button press.

    2nd week activities:

    The Reset button in the Shell UI should perform an "auto-scale" of the shapes in your image collection such that a scale factor is computed which causes the image to fill the screen to the fullest extent possible. A consequence of this is that the translational offsets of the transformation must be adjusted as well, as discussed in lecture. The rotation values should be left unmodified.

     
  5. (A-level grade) Implement support for Bezier Curves, including a UI element for putting the program into "Bezier" mode. Include Read/Write support, which is very easy to do since it is nearly the same functionality as for the Polygon class (particularly if you put most of that functionality into the VariableShape base class).

    Extra Credit Activity

    1. (10 pts) Rather than using buttons to extend your program's GUI, implement the rotation CW/CCW, pan up/down, and pan left/right functionality using three separate QSlider, QSpinbutton or QDial controls. All code implementing the extra credit functionality must be (as usual) well-commented and discussed in your lab report.

    Hints

  1. Work in phases. For example:
  1. #include <matrix.h> // you might want to place it in /usr/local/include on your computer
  2. The constructors for the matrix class do not guarantee that any particular values are in the matrix. Use .Null() for a matrix of zeros. Use .Unit() for an identity matrix
  3. The easiest way to allow programs using matrix.h to work with Qt is to disable exceptions in the matrix class. To do this, update your .pro file to include DEFINES *= _NO_EXCEPTION
  4. For UI modification, look up QHBoxLayout, QHButtonGroup, QPushButton, and QLabel. You may also want to experiment with the dial, slider or spinbox controls.

Demonstration (during week 8 lab)

You will need to demonstrate the following to me during the week 8 lab meeting:

This milestone must be reached by the week 8 lab; otherwise, late points will begin to incur.

You will need to demonstrate your completed project to me during the week 9 lab meeting.

Lab assignment (due the day of Lab 6)

This is a 2 week lab.

Fix all errors from your previous lab!

Submit your assignment following these instructions:
  1. In addition to your Word report file, I want all .pro, .cpp, and .h files.
    Use webCT to submit your assignment ("Lab 5"). Zip the files for ease of submission (but be sure to use the zip format).
  2. Record the time (in minutes) you spent on this lab in the FAST system for weeks 7 and 8.
Be sure to keep copies of all your files, in case something gets lost.

Your lab grade will be determined by the following factors:

Program quality Report quality

If you have any questions, consult me.