Render Part C Assignment
In this studio we will evolve our code from Render_Part_B_Assignment to add new methods and a new class.
Continue editing files in the drawings directory.
Contents
Background
Bounds Calculation
We will add support for calculating a bounding box for each of our drawable objects.
We will implement a BoundingBox class (via Struct, if desired) to store the min and max points of a box which bounds the object.
Transformable objects will split the responsibility into two methods, untransformed_bounds and bounds. On the subclasses the untransformed_bounds method will return its object's bounds in the same untransformed space that untransformed_render acts: that is, about its origin. On the Transform superclass, the bounds method will transform the untransformed_bounds by the x and y location (akin to how render transforms the affine matrix via glTranslate to transform the space untransformed_render operates in). The bounds method will not be able to rely on glTranslate. It will need to create a new transformed BoundingBox.
For example, an Ellipse created with an x_radius of 0.3, a y_radius of 0.4, an x location of 0.1, and a y location of 0.2 would produce an untransformed_bounds with a min of (-0.3, -0.4) and a max of (0.3, 0.4). The bounds calculation inherited from Transform would transform the untransformed bounds with the x and y locations, producing a bounding box with a min of (-0.2, -0.2) and a max of (0.4, 0.6).
Code to Implement
BoundingBox
file: | src/main/ruby/drawings/bounding_box.rb | |
class: | BoundingBox | |
superclass: | Object | |
methods: | initialize(min,max) min() min=(min) max() max=(max) |
Note: be sure to require_relative 'point2'.
Note: min and max should be instances of Point2
.
Note: You may wish to use Ruby's convenient Struct construct.
Transform
file: | src/main/ruby/drawings/transform.rb | |
class: | Transform | |
superclass: | Object | |
methods to evolve: | Ø | |
methods to add: | move(direction,amount) bounds() |
|
methods to remove: | Ø |
move
the move method will accept two parameters: direction and amount and change the x,y position as appropriate.
direction can be one of four symbols
:left :right :up :down
- left corresponds to translating along the negative x axis
- right corresponds to translating along the positive x axis
- down corresponds to translating along the negative y axis
- up corresponds to translating along the positive y axis
any other value for direction should raise an ArgumentError.
Note: do NOT call glTranslate here. simply update your instance fields so that later when you are rendering, you will glTranslate the updated amounts.
bounds
invoke untransformed_bounds
and transform the returned bounds by x and y.
NOTE: untransformed_bounds
is abstract. it must be defined by the subclasses.
Rectangle
file: | src/main/ruby/drawings/rectangle.rb | |
class: | Rectangle | |
superclass: | ColorTransform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Returns an instance of Bounds specified by min and max instances of Point2
.
NOTE: this method must be private.
bounding box decoration rendering
Note: the bounding box and minimum and maximum points are only for demonstration here. The should not be drawn in your solution.
Ellipse
file: | src/main/ruby/drawings/ellipse.rb | |
class: | Ellipse | |
superclass: | ColorTransform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Returns an instance of Bounds specified by min and max instances of Point2
.
NOTE: this method must be private.
bounding box decoration rendering
Note: the bounding box and minimum and maximum points are only for demonstration here. The should not be drawn in your solution.
EquilateralTriangle
file: | src/main/ruby/drawings/equilateral_triangle.rb | |
class: | EquilateralTriangle | |
superclass: | ColorTransform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Returns an instance of Bounds specified by min and max instances of Point2
.
NOTE: this method must be private.
bounding box decoration rendering
Note: the bounding box and minimum and maximum points are only for demonstration here. The should not be drawn in your solution.
BezierCurve
file: | src/main/ruby/drawings/bezier_curve.rb | |
class: | BezierCurve | |
superclass: | ColorTransform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Contemplate for a moment how you would build this method and then raise an error and move on.
NOTE: this method must be private.
def untransformed_bounds raise StandardError.new("not yet implemented") end
Text
file: | src/main/ruby/drawings/text.rb | |
class: | Text | |
superclass: | ColorTransform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Contemplate for a moment how you would build this method and then raise an error and move on.
NOTE: this method must be private.
def untransformed_bounds raise StandardError.new("not yet implemented") end
CircularSegment
file: | src/main/ruby/drawings/circular_segment.rb | |
class: | CircularSegment | |
superclass: | ColorTransform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Contemplate for a moment how you would build this method and then raise an error and move on.
NOTE: this method must be private.
def untransformed_bounds raise StandardError.new("not yet implemented") end
Image
file: | src/main/ruby/drawings/image.rb | |
class: | Image | |
superclass: | Transform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Contemplate for a moment how you would build this method and then raise an error and move on.
NOTE: this method must be private.
def untransformed_bounds raise StandardError.new("not yet implemented") end
CompositeTransform
file: | src/main/ruby/drawings/composite_transform.rb | |
class: | CompositeTransform | |
superclass: | Transform | |
methods to evolve: | Ø | |
methods to add: | untransformed_bounds | |
methods to remove: | Ø |
untransformed_bounds
Returns an instance of Bounds specified by min and max instances of Point2
.
NOTE: this method must be private.
bounding box decoration rendering
Note: the bounding box and minimum and maximum points are only for demonstration here. The should not be drawn in your solution.
Scene
file: | src/main/ruby/drawings/scene.rb | |
class: | Scene | |
superclass: | Object | |
methods to evolve: | bounds() | |
methods to add: | Ø | |
methods to remove: | Ø |
bounds
NOTE: this method must be public.
bounding box decoration rendering
Note: the bounding box and minimum and maximum points are only for demonstration here. The should not be drawn in your solution.
ConvexPolygon
file: | src/main/ruby/drawings/convex_polygon.rb | |
class: | ConvexPolygon | |
superclass: | ColorTransform | |
methods: | initialize(points, x: 0, y: 0, color: nil) untransformed_render() untransformed_bounds() |
Note: You will need to add this file. Starter code:
require_relative 'color_transform' require_relative 'point2' class ConvexPolygon < ColorTransform end if __FILE__ == $0 require_relative '../core/render_app' points = [ Point2.new(0.85, 0.0), Point2.new(0.1, 0.25), Point2.new(0.0, 0.45), Point2.new(0.15, 0.7), Point2.new(0.65, 1.0), Point2.new(0.95, 0.95), Point2.new(1.1, 0.75) ] app = RenderApp.new(ConvexPolygon.new(points, x: -0.5, y: -0.5, color: Color.new(1, 0, 0))) app.main_loop end
initialize
Accept a required parameter points which is an array of Point2s.
Accept keyword parameters for x: 0, y: 0, and color: nil to the constructor and pass them to the superclass.
NOTE: Be sure to not override render. Implement the render_transformed method instead.
untransformed_render
NOTE: this method must be private.
untransformed_bounds
NOTE: this method must be private.
bounding box decoration rendering
Note: the bounding box and minimum and maximum points are only for demonstration here. The should not be drawn in your solution.
file to run: | src/main/ruby/drawings/convex_polygon.rb |
Testing Your Solution
Unit Test
Part C
file: | src/test/ruby/drawings/preliminary/part_c/*.rb | UnitTest |
note: ensure that you have removed all printing to receive credit for any assignment.
file: | src/test/ruby/drawings/more_comprehensive/part_c/*.rb | UnitTest |
note: ensure that you have removed all printing to receive credit for any assignment.
Backwards Compatibility
file: | src/test/ruby/drawings/preliminary/part_b/*.rb | UnitTest |
note: ensure that you have removed all printing to receive credit for any assignment.
file: | src/test/ruby/drawings/preliminary/part_a/*.rb | UnitTest |
note: ensure that you have removed all printing to receive credit for any assignment.
Visual Comparison
file to run: | src/main/ruby/drawings_snapshots/part_c_snapshots_web_page_generator.rb |
Somewhat Outdated Testing Demo