I'm working on the API in my copious free time. In the first iteration, I wrote a bunch of classes with
static factory methods, like `Diamond.fromPointSideAngle()`

, but the factory names were getting
quite unwieldy. I thought about API techniques that could make this easier to handle, and I've decided that
for my second iteration, I'm going to use a *fluid API* - I'll implement a bunch of setter methods
(e.g., `setCenter`

), and each setter will return the object itself, which will make it easy for
the developer to chain setters together: `Circle c = new Circle().setCenter(x, y).setRadius(r);`

.

The downside of the fluent API is that the developer can create an object that is not well-formed. For example, one can create a circle with a center but no radius, and there is no compile-time way to catch that. On the other hand, the fluid API will allow developers to use combinations of points, edges, and angles that would be too difficult to plan for in factory methods (for example, creating a triangle with a collection of vertices, or various combinations of sides and angles, a center point with distances to the vertices, and so on).

One of my goals is to produce an API with which developers can create complicated shapes, tesselations, and pictures, with a minimal exposure to math and trigonometry. For example, suppose I wanted to draw a pentagon, with equilateral triangles off each side. In today's graphic APIs, this would require a fair amount of math. In my API, it would be as simple as:

List<Shape> allShapes = new List<Shape>(); Polygon pentagon = new Polygon().setSides(5).setCenter(x, y).setCenterToVertex(10); // Could also have setCenterToSide() allShapes.add(pentagon); Line[] lines = pentagon.getSides(); for (Line line : lines) { Triangle triangle = new Triangle().setEquilateral().setBase(line); allShapes.add(triangle); } Geometry.drawShapes(Graphics g, allShapes);Look at that - no math! And the code is conceptually simple - you can read this and understand it.

The examples below use the first iteration of the API, which I didn't complete before I had my ideas for the fluid API.

private void drawRadialDiamonds(Graphics2D g2, int cx, int cy, int n) { int radius = 5; int base = 50; int numDiamonds = n; double angle = 2*Math.PI / numDiamonds; RelativePoint[] points = RelativePoint.createNRadialPoints(cx, cy, radius, numDiamonds); for (RelativePoint point : points) { Shape diamond = Diamond.fromPointSideAngle(point.getX(), point.getY(), base, angle); Shape rotatedDiamond = Rotator.rotate(diamond, point.getX(), point.getY(), point.getAngle()); g2.setPaint(Color.BLACK); g2.fill(rotatedDiamond); } if (numDiamonds > 10) { points = RelativePoint.createNRadialPointsWithOffset(cx, cy, 50, numDiamonds, (2*Math.PI / numDiamonds) / 2); for (RelativePoint point : points) { Shape diamond = Diamond.fromPointSideAngle(point.getX(), point.getY(), base, angle); Shape rotatedDiamond = Rotator.rotate(diamond, point.getX(), point.getY(), point.getAngle()); g2.setPaint(Color.BLACK); g2.fill(rotatedDiamond); } } } |