Please refer to the text of assignment 0 if you're unsure how to clone a repository. On the command line, you can achieve this using the following command:
$ git clone https://gitlab.cs.dartmouth.edu/cs77-fa17/assignment2_basecode.git
For visual tools such as SourceTree the process is slightly different, but the URL will be the same.
Before you start, open
firstname-lastname-report.html in your browser. This html file will be both your report and your submitted assignment. Check the developer console of your browser for any error messages (check the x-hour slides for how to open the console).
Note: If there are any compatibility issues with your browser/platform, let us know as soon as possible
The report contains 5 tasks which you need to implement (Undergrads are required to implement only 4). Each task has its own simple curve editing UI that allows you to add and modify control points. You can add control points by clicking anywhere in the drawing area and a control polygon is drawn between each successive control vertex. The curve functionality is encapsulated within the
resources/catmullromspline.js files. The
resources/node.js file contains code that manages the control vertex data and its drawing routine. The
resources/drawutils.js file contains utility code that allows to draw lines, circles and text easily within a canvas element. Please go through these files to get a better understanding of all the functionality that is available to you. Each task builds upon the previous task so we encourage you to proceed in a sequential order while completing the assignment.
For undergraduates, the point break down is as follows.
- Task 1 - 2 pts
- Task 2 - 1 pts
- Task 4 - 1 pt
- Task 5 - 2 pts
For graduate students, the point break down is as follows.
- Task 1 - 1.5 pts
- Task 2 - 0.5 pt
- Task 3 - 1.5 pts
- Task 4 - 0.5 pt
- Task 5 - 2 pts
In this task you will implement the De Casteljau's recursive curve split algorithm for Bezier curves of degree 2 and 3. You will implement your code in the
beziercurve.js file within the
BezierCurve.deCasteljauSplit() function that takes in an input parameter value
t. Make sure to write appropriate code for degree 2 and 3 curves (by checking the current number of nodes in the
BezierCurve.nodes array). Hint: you may find the node.lerp() function useful for the interpolation steps needed in the de Casteljau algorithm. This function should populate the nodes of the left and right child curves, and return them in the
right return values.
Once you have finished implementing the split code, you can then employ it within the
BezierCurve.drawTask1() function to draw the two split curves. You can play around with the paramter value
t by using the slider present below the canvas element in Task 1 in the report html file.
In this task, you will build upon the split routine from task 1 to draw the actual Bezier curves. You will have to add your implementation within the
BezierCurve.deCasteljauDraw() function that takes in an input argument of the maximum recursion
depth. The recursion depth determines the number of splits employed to draw the control vertices. The depth parameter is decremented with each recursion and when the recursion reaches a depth of 0, the curve can be approximated as its control polygon. You should use the
BezierCurve.drawControlPolygon() function to draw just the control polygon of the curve.
Once you've implemented this function, you can employ it within
BezierCurve.drawTask2() which would enable you to test your code within the task 2 canvas in the report file. You can play around with the recursion depth using the slider. With increasing recursion depth, the curve should more closely resemble the actual smooth curve.
Task 3 (Only Grad Students)
This task is for grad student credit only. In the previous task, you implemented a fixed depth Bezier subdivision scheme. This scheme does not consider the curvature of the curve to determine how many recursions are required to represent the curve faithfully. In case of highly curved curves, using a low subdivision depth will result in a faceted appearance due to the individual segments of the curve approximation. Moreover, some regions of a curve are flat and could be well approximated by only a few segments, while other regions may have high curvature, requiring fine subdivision to avoid faceted artifacts. A more sophisticated approach would be to adaptively decide during recursion (using some measure of local "flatness") whether further subdivision is required or whether the current control polygon approximates its portion of the curve sufficiently well. You should implement a scheme which uses either the pixel extent of the control points, or the deviation of the interior control points from the line connecting the endpoints (as discussed in lecture) as a termination criterion. To visualize the adaptive subdivision, you should include a checkbox to visualize the endpoints of the drawn subdivided curves as small circles (so we can see that the points are spaced unevenly. Implement this scheme in the
Once you've coded up this adaptive subdivision scheme, you can test it by using the task 3 curve editor which calls the
BezierCurve.drawTask3() function from the
draw() function in the main page.
In this task, you will start adding functionality for drawing Catmull-Rom splines. You will be writing all your code within the
catmullromsplines.js file. The file contains starter code that allows you to store an arbitrary number of control points. The nodes are stored within the
CatmullRomSpline.nodes array. The provided base code already draws linear line segments between control points chosen within the canvas area. In this task, you need to compute the tangents at each control vertex (computed by looking at the next and previous control vertices) within the list of control vertices. You should implement this functionality within
Once you've implemented the tangent computation code, you can test it within the curve editor in the Task 4 section in the report page. The
CatmullRomSpline.drawTangents() is automatically called within the
CatmullRomSpline.drawTask4() that is called by the
draw() function in the main page. The following figure shows the tangents that are drawn at the control vertices. Note that tangents are not available at the first and the last control vertices (since computing tangents requires a previous and next vertex which are not available at these vertices).
Note: This task has separate requirements for graduate and undergraduate students. Read the instructions carefully before working on this task.
Once you have implemented the tangent computation task, you can implement the actual spline drawing code within the
CatmullRomSpline.draw(). You can evaluate the curve locations using the De Casteljau's recursive draw routine that you've coded earlier (using the tangents computed in the previous step) or you can explicitly evaluate the curve at fixed parameter intervals to draw the curve. Once you've implemented the
draw() routine, you can test the functionality in the task 5 curve editor area. The
CatmullRomSpline.draw() function is automatically called within the
CatmullRomSpline.drawTask5() function that is inturn called within the
draw() function in the main page. The provided report page has a slider for controlling the
CatmullRomSpline.numSegments value. You can use that value to compute the number of segments that you use to split the parametric interval equally. If you choose to draw the spline using the de Casteljau algorithm, you will have to modify the code appropriately to add a separate field to the
CatmullRomSpline class (For example, add a field called
depth) and then write appropriate code that modifies this value when the slider value is changed. This procedure is a very minor operation and can be easily implemented. The following image shows the curve being drawn along with the control polygon and tangents at every control vertex.
You will notice that the UI contains a 'tension' slider. This slider controls the
CatmullRomSpline.tension value. If you are an undergraduate student, you can safely ignore this value and implement the general spline drawing code. In case you are a grad student, you will have to implement the spline drawing function that takes this
tension parameter into account. The
tension parameter controls how sharply the curve bends at the interpolated control points. You can refer to section 15.5.3 in the textbook for more details.
What to submit
You should submit a zip file containing the entire folder for this assignment (including all js files, html files and the
resources folder). Rename
firstname-lastname-report.html to contain your name. Fill in the report with any problems encountered and comments about the assignment.
Note that we will grade the assignments in person. You will still need to come to office hours for grading. However, you should also submit the zip file so we know you completed your assignment on time, and that you didn't copy source code from others.