Vector Graphics
A Simplified Approach with Examples in Java |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
setPaperColor(name:String)
setInkColor(name:String)
setPenWidth(pixels:int)
setLineType(name:String)
moveTo(p:Point)
drawTo(p:Point)
Coordinates
Drafter
Point
Class:
getCoordinate(i:int):double
Point
objectsConcreteDrafter
import java.util.Enumeration; /** * A concrete child of the Drafter class that draws * a "hard coded" floor plan */ public class FloorPlanExample extends Drafter { protected LineSegment wall; protected PiecewiseLinearCurve[] rooms; /** * Default Constructor */ public FloorPlanExample() { double[] p, q; // Create a single wall p = new double[2]; q = new double[2]; p[0] = 330.0; p[1] = 210.0; q[0] = 390.0; q[1] = 210.0; wall = new LineSegment(new Point(p), new Point(q)); // Create all of the rooms rooms = new PiecewiseLinearCurve[5]; rooms[0] = new PiecewiseLinearCurve(); addTo(rooms[0], 490, 40); addTo(rooms[0], 390, 40); addTo(rooms[0], 390, 210); addTo(rooms[0], 490, 210); addTo(rooms[0], 490, 40); rooms[1] = new PiecewiseLinearCurve(); addTo(rooms[1], 390, 60); addTo(rooms[1], 350, 60); addTo(rooms[1], 350, 100); addTo(rooms[1], 390, 100); addTo(rooms[1], 390, 60); rooms[2] = new PiecewiseLinearCurve(); addTo(rooms[2], 350, 60); addTo(rooms[2], 290, 60); addTo(rooms[2], 290, 120); addTo(rooms[2], 330, 120); addTo(rooms[2], 350, 110); addTo(rooms[2], 350, 60); rooms[3] = new PiecewiseLinearCurve(); addTo(rooms[3], 330, 120); addTo(rooms[3], 240, 120); addTo(rooms[3], 240, 210); addTo(rooms[3], 260, 220); addTo(rooms[3], 310, 220); addTo(rooms[3], 330, 210); addTo(rooms[3], 330, 120); rooms[4] = new PiecewiseLinearCurve(); addTo(rooms[4], 240, 120); addTo(rooms[4], 170, 120); addTo(rooms[4], 170, 210); addTo(rooms[4], 240, 210); addTo(rooms[4], 240, 120); } /** * A convenience method for adding a point to a * PiecewiseLinearCurve * * @param line The curve being added to * @param x The x-coordinate of the new point * @param y The y-coordinate of the new point */ private void addTo(PiecewiseLinearCurve line, double x, double y) { double[] v; v = new double[2]; v[0] = x; v[1] = y; line.add(new Point(v)); } /** * Draw the floor plan * * This method is called by the parent Drafter whenever * the floor plan needs to be drawn. * * @param max The upper-right corner of the paper */ public void draw(Point max) { Enumeration e; Point p; // Draw the wall e = wall.points(); p = (Point)e.nextElement(); moveTo(p); while (e.hasMoreElements()) { p = (Point)e.nextElement(); drawTo(p); } // Draw the rooms for (int i=0; i<rooms.length; i++) { e = rooms[i].points(); p = (Point)e.nextElement(); moveTo(p); while (e.hasMoreElements()) { p = (Point)e.nextElement(); drawTo(p); } } } }
LineSegment
protected void drawLineSegment(LineSegment segment) { Enumeration points; Point p; // Get an Enumeration of the Point objects points = segment.points(); // Get one end point p = (Point)points.nextElement(); // Move the pen to the end point moveTo(p); // Get the other end point p = (Point)points.nextElement(); // Draw a line to the other end point drawTo(p); }
PiecewiseLinearCurve
protected void drawCurve(PiecewiseLinearCurve curve) { Enumeration points; Point p; // Get an Enumeration of the Point objects points = curve.points(); // Get one end point p = (Point)points.nextElement(); // Move the pen to the end point moveTo(p); // Get and draw a line to each of the remaining break points while (points.hasMoreElements()) { // Get the other end Point p = (Point)points.nextElement(); // Draw a line to the other end Point drawTo(p); } }
Polygon
protected void drawPolygon(Polygon polygon) { Enumeration points; Point p; // Get an Enumeration of the Point objects points = polygon.points(); // Get one end point p = (Point)points.nextElement(); // Move the pen to the end point moveTo(p); // Get and draw a line to each of the remaining break points while (points.hasMoreElements()) { // Get the other end Point p = (Point)points.nextElement(); // Draw a line to the other end Point drawTo(p); } }
PiecewiseLinearCurve
and
Polygon
are identical.
LineSegment
can be modified
to work the same way.
Point
.
Feature
protected void drawFeature(Feature feature) { Enumeration points; Point p; points = feature.points(); p = (Point)e.nextElement(); moveTo(p); if (!e.hasMoreElements()) // The Feature is a Point { drawTo(p); } else // The Feature is a LineSegment, etc... { while (e.hasMoreElements()) { p = (Point)e.nextElement(); drawTo(p); } } }
Point
in the
Feature
by a scalarPoint
in the
Feature
Coordinates
Point
:
Point
objectsPoint
?
Point
Point
:
Point
objectPoint
objectsPoint
?
Point
objects,
the component-by-component minimum and maximumPoint
object or another RectangularHull
objectPoint
?
Point
objectsFeature
:
getRectangularHull():RectangularHull
LineSegment
,
PiecewiseLinearCurve
, etc...) may be able to
do it more efficiently
/** * The smallest rectangle containing a set of Point objects (represented * as two Point objects, one containing the minimal coordinates and * one containing the maximal coordinates). * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class RectangularHull { private Point max, min; /** * Explicit Value Constructor */ public RectangularHull(Point min, Point max) { double[] v; int n; n = min.getDimension(); v = new double[n]; for (int i=0; i<n; i++) v[i] = min.getCoordinate(i); this.min = new Point(v); for (int i=0; i<n; i++) v[i] = max.getCoordinate(i); this.max = new Point(v); } /** * Adjust this RectangularHull (if necessary) * so that it includes the given Point * * @param p The new Point */ public void adjustFor(Point p) { min = Point.min(p, min); max = Point.max(p, max); } /** * Adjust this RectangularHull (if necessary) * so that it includes another RectangularHull * * @param other The other RectangularHull */ public void adjustFor(RectangularHull other) { min = Point.min(other.getMin(), min); max = Point.max(other.getMax(), max); } /** * Get the maximal Point (e.g., the upper right corner) * * @return The maximal point */ public Point getMax() { return max; } /** * Get the minimal Point (e.g., the lower left corner) * * @return The minimal point */ public Point getMin() { return min; } }
// The RectangularHull of all of the Feature objects protected RectangularHull hull; // The coordinate-by-coordinate maximum of the screen coordinates protected Point smax; /** * Draw a Feature scaled to fit the paper * * @param feature The Feature to draw */ protected void drawFeature(Feature feature) { double alpha; Enumeration points; Point p, q, rho, sigma, wmax, wmin, wminhat; // Determine the range in world coorinates wmax = hull.getMax(); wmin = hull.getMin(); rho = wmax.minus(wmin); // Determine the scale for each coordinate sigma = screenMax.cover(rho); // Maintain the aspect ratio by using the smallest element of scale alpha = sigma.smallestCoordinate(); // Scale the minimum in world coordinates (for the translation) wminhat = wmin.times(alpha); // Scale and translate each point // points = feature.points(); // The first Point in the feature p = (Point)e.nextElement(); q = (p.times(alpha)).minus(wminhat); moveTo(q); if (!e.hasMoreElements()) // The Feature is a Point { drawTo(q); } else // The Feature is a LineSegment, etc... { while (e.hasMoreElements()) { // The subsequent Point objects in the feature p = (Point)e.nextElement(); q = (q.times(alpha)).minus(wminhat); drawTo(q); } } }