Drawable interface

The Drawable interface specifies some basic properties of all drawable objects.

It specifies that each Drawable object shall implement a method getPoints() that returns an Iterator<? extends Point> that will yield a series of Point objects (or some subclass thereof) that describe the Drawable. As that description is self-referencing and therefore confusing, let us give a few examples:

    Point2d p = new Point2d(12.34, 23.45);
    System.out.println("The iterator of a point yields one point (the point itself):");
    for (Iterator<? extends Point2d> iterator = p.getPoints(); iterator.hasNext();)
    {
        System.out.println(iterator.next());
    }
    LineSegment2d ls = new LineSegment2d(12.34, 23.45, 34.56, 45.67);
    System.out.println("The iterator of a line segment yields two points (the start point and the end point):");
    for (Iterator<? extends Point2d> iterator = ls.getPoints(); iterator.hasNext();)
    {
        System.out.println(iterator.next());
    }
    Bounds3d b = new Bounds3d(12.34, 23.45, 34.56, 45.67, 56.78, 67.89);
    System.out.println("The iterator of a bounds3d yields eight points (the vertices of the bounds):");
    for (Iterator<? extends Point3d> iterator = b.getPoints(); iterator.hasNext();)
    {
        System.out.println(iterator.next());
    }

Outputs:

The iterator of a point yields one point (the point itself):
Point2d [x=12.340000, y=23.450000]
The iterator of a line segment yields two points (the start point and the end point):
Point2d [x=12.340000, y=23.450000]
Point2d [x=34.560000, y=45.670000]
The iterator of a bounds3d yields eight points (the vertices of the bounds):
Point3d [x=12.340000, y=34.560000, z=56.780000]
Point3d [x=12.340000, y=34.560000, z=67.890000]
Point3d [x=12.340000, y=45.670000, z=56.780000]
Point3d [x=12.340000, y=45.670000, z=67.890000]
Point3d [x=23.450000, y=34.560000, z=56.780000]
Point3d [x=23.450000, y=34.560000, z=67.890000]
Point3d [x=23.450000, y=45.670000, z=56.780000]
Point3d [x=23.450000, y=45.670000, z=67.890000]

Please do not write code that depends on the order in which the iterator of a Bounds yields those points. The iterator of a PolyLine is guaranteed to yields the points in the order that these appear in the PolyLine. The iterator of a LineSegment is guaranteed to yield two points; first the start point and then the end point.

A Drawable must also implement a size() method that returns the number of points that the iterator will produce.

Any Drawable object can report the number of dimensions that it stores:

    Point2d point2d = new Point2d(12.34, 23.45);
    System.out.println("2D object has two dimensions: " + point2d.getDimensions());
    Point3d point3d = new Point3d(12.34, 23.45, 34.56);
    System.out.println("3D object has three dimensions: " + point3d.getDimensions());

Outputs:

2D object has two dimensions: 2
3D object has three dimensions: 3

Finally, the Drawable interface demands implementation of a couple of toString methods:

toString(String doubleFormat, boolean doNotIncludeClassName)

toString(String doubleFormat)

toString(boolean doNotIncludeClassName)

The second and third variant have default implementations that call the first one. The first one is the most versatile. The doubleFormat argument should be something like %6.3f. This overrides the default (%f) format used to format the coordinate values and angles. When the doNotIncludeClassName argument is true; the name of the class is not included in the output. When false, the name of the class is included in the output.

Regrettably, it is not possible to add a default implementation for de zero-argument toString() method. This should be implemented explicitly in all classes that implement Drawable. The implementation usually looks like:

public String toString()
{
    return toString("%f", false);
}

This implementation lets the two-parameter version do the real work.

None of the Drawable implementing classes implements it directly. In stead, these classes implement an extension of Drawable. The Drawable2d interface extends the Drawable interface by specifying implementation of a getBounds() method that must return a Bounds2d object. The Drawable3d interface extends the Drawable interface by specifying implementation of a getBounds() method that must return a Bounds3d object.

Therefore, all Drawable objects implement a getBounds() method that returns a suitable Bounds object. As a Bounds2d object implements Drawable2d it implements getBounds() (which simply returns this).