|
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);
}
}
}