编程辅导 C C++ Java Python MIPS Processing 网络家教 在线辅导

编程家教 远程写代码 Debug 讲解答疑 课后答疑 不是中介,本人直接答疑

微信: ittutor QQ: 14061936 Email: ittutor@qq.com

导航

Composites and Adaptors

The main goals of this assignment are to gain experience with the composite and adaptor patterns.

2 Getting Started

Before writing code of your own, you will likely want to look over the code that is provided. Most of this you should have seen before, either in the previous problem set or in lecture, but there are a few things that are different or new:

  • Grade08 is similar to the file that I will use with the autograder. It should not compile right now, as it mentions code that you haven’t written yet. However, if you problem set is completed correctly then Grade08.java should compile and the tests should pass.

  • AffineTransformation (Javadoc) defines a class for 2-D affine transformations, which include scaling, rotation, translation, and shearing. Affine transformations can be specified as a matrix using the AffineTransformation.matrix static factory method. There are additional static factories for more specific kinds of transformations.

  • Transformable (Javadoc) defines an interface for objects that affine transformations can be applied to. This includes points, bounding boxes, and Sampleables.

  • Renderable (Javadoc) defines an interface for objects that know how to render themselves to a raster. When rendering, the client may provide an affine transformation to map from the Renderables internal coordinates to the physical coordinates of the raster.

  • AbstractRenderable (Javadoc) defines a skeleton class for implementing Renderables. It provides the getBoundingBox() and transform(AffineTransformation) methods, so that subclasses need only define a rendering method.

  • Renderables (Javadoc) defines a static factory method for making circle Renderables and a static factory method that adapts a Sampleable for use as a Renderable.

  • The CirclesDemo class contains some commented-out code that will exercise the code you need to write, once it’s ready. (But this is no substitute for actual testing.)

  • This problem set builds on the previous problem set—it depends on the IntegerPointDoublePoint, and Colors classes that you implemented. You are free to use your implementations of these classes, but if you prefer to use mine, compiled binary class files are available in pset08.jar.

2.1 Renderables

In lectures and the previous problem sets we represented scalable graphics using the Sampleable interface, which provides a way for a renderer to query such an object about its color at different points to nearly arbitrary precision. This provides a lot of control over how Sampleables are composed, because Sampleable decorators can wrap a Sampleable in order to modify the points of queries, to modify the resulting color, or even to turn a single color query into multiple queries on the decorated object. This is flexible, but also inefficient. In this problem set, we will explore another approach, the Renderable interface for objects that know how to render themselves to a Raster.

Renderable objects, like Sampleable objects, know their bounding box, but unlike Sampleables they take an active role in rendering. Renderable has a void method render(Raster) that renders the object to the given Raster. The Renderable is rendered using a direct mapping of its internal coordinate system to the Raster’s pixels, just as SimpleSampler does for Sampleables. To support scaling, rotation, and other tranformation, Renderable also provides a more generalrender(AffineTransformation, Raster) method that allows providing an affine transformation to map the Renderable’s coordinates to the Raster. See the implementation of Sampleables.circle(Point<Double>, double, Color) for an example of how this works.

3 Your Task

3.1 The OverlayRaster Class

The first part of your task is to implement a class OverlayRaster, which modifies the behavior of the setRGBA(Point<Integer>, int) method to handle alpha in the color being set. In particular, rather than replacing the value of the given pixel, it overlays the given color over the existing color of the pixel. This enables rendering (partially) transparent objects directly to a raster that already contains whatever background should show through them.

Note that the setRGBA method takes an int color value, not a Color object, so there is no direct way to overlay two colors. However, it can be done by temporarily converting the int representation into Color objects.

In addition to implementing the Raster interface, OverlayRaster must have two public constructors:

  • public OverlayRaster(Raster base) constructs an OverlayRaster that stores its pixels in the given Raster. In particular, setting pixels in base should affect the corresponding pixels as viewed via the resulting OverlayRaster, and vice versa.

  • public OverlayRaster(int width, int height) uses a new ArrayRaster of the given dimensions to store its pixel data.

These constructors are documented in the OverlayRaster Javadoc.

  1. Implement the OverlayRaster class, as described above. Be sure to test your code thoroughly.

3.2 Overlaying Renderables

In the last problem set, you wrote a static method Sampleable overlay(Sampleable... layers) that builds composite Sampleable nodes by overlaying any number of other Sampleable components (which may be leaves or composites themselves).

We need a similar method for constructing composite Renderables by stacking several Renderables as layers. The Renderables.overlay(Renderable...) static factory method takes any number of Renderables and stacks them front to back, which means that when they are rendered the front of the array is rendered on top of the back of the array.

  1. In class Renderables, write a public static method Renderable overlay(Renderable... layers) that overlays the layers front-to-back. Rendering to an OverlayRaster should result in transparency in the layers being displayed properly. Be sure to test your code.

  2. Modify the CirclesDemo class to use your OverlayRaster by uncommenting line 16, and by changing the circles() method to return the overlaid circles using your overlay method. Running the program should demonstrate the partial transparency enabled by OverlayRaster.

3.3 Rendering Rectangles

So far we have rendered only circles and combinations of circles. Time for something different: Rectangles! Renderables.rectangle is a static factory method that constructs a renderable rectangle with its sides at the given coordinates. (See the implementation of Renderables.circle to get the idea of how to do this.)

  1. In class Renderables, write a public static method Renderable rectangle(double top, double bottom, double left, double right, Color color) that returns a Renderable to render the specified rectangle in the specified color. Be sure to test your code.

3.4 Adapting between Sampling and Direct Rendering

Sampleable and Renderable distinctly different approaches to representing scalable, composable graphics. They are not equivalent, but close enough that it is generally possible to adapt a graphic element represented using one interface to be usable via the other. For example, see the static factor method Renderables.renderable(Sampleable), which takes a Sampleable and adapts it for use as a Renderable. Its render method works by sampling the Sampleable and rendering the resulting pixel colors to the given Raster.

For this last part, you will implement an adaptor that works in the other direction, allowing a Renderable to be used as a Sampleable. Probably the most straightforward way to do this is to allocate a private OverlayRaster large enough to fit the Renderables bounding box and render into it. Then use the colors in the Raster to answer getColorAt requests. Note that the resolution of the Raster determines what resolution can be distinguished by getColorAt. Your adaptor should use a Raster with one pixel per 1.0 units in the Renderable’s coordinates.

  1. In class Sampleables, write a public static method Sampleable sampleable(Renderable) that adapts the given Renderable to be used as a Sampleable. Be sure to test your code.

Try the following experiment in CirclesDemo.java. In the CirclesDemo.render method, create a Sampleable that contains an adapted Renderable circle using your adaptor. Then scale up the resulting Sampleable (see Transformable.scale(double)) by a factor of four and sample it to the raster parameter. You should see pixelation because the Raster used in your adaptor doesn’t contain enough information to sample when scaled up. However, this can be fixed by forcing the Renderable to be rendered at a higher resolution.

  1. In class Sampleables, uncomment method sampleable(double, Renderable), which uses your sampleable method from the previous item to create Sampleables that adapt the Renderable at a higher resolution.

Repeat the above experiment, but this time adapt the Renderable to a Sampleable using sampleable(double, Renderable) with a factor of 4.0. The pixelation should be eliminated.

 

  1.  

相关推荐