/** Turns a List<CubicCurve2D.Float> into a SVG Element representing a sketch of that spline. */
    Element splineToSketch(SVGDocument document, List<CubicCurve2D.Float> spline) {
      String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;

      // <g> is an SVG group
      // TODO: add a random(ish) rotation to the group
      Element group = document.createElementNS(svgNS, "g");

      // For each curve in the path, draw along it using a "brush".  In
      // our case the brush is a simple circle, but this could be changed
      // to something more advanced.
      for (CubicCurve2D.Float curve : spline) {
        // TODO: magic number & step in loop guard
        for (double i = 0.0; i <= 1.0; i += 0.01) {
          Point2D result = evalParametric(curve, i);

          // Add random jitter at some random positive or negative
          // distance along the unit normal to the tangent of the
          // curve
          Point2D n = vectorUnitNormal(evalParametricTangent(curve, i));
          float dx = (float) ((Math.random() - 0.5) * n.getX());
          float dy = (float) ((Math.random() - 0.5) * n.getY());

          Element brush = document.createElementNS(svgNS, "circle");
          brush.setAttribute("cx", Double.toString(result.getX() + dx));
          brush.setAttribute("cy", Double.toString(result.getY() + dy));
          // TODO: magic number for circle radius
          brush.setAttribute("r", Double.toString(1.0));
          brush.setAttribute("fill", "green");
          brush.setAttributeNS(null, "z-index", Integer.toString(zOrder.CONTOUR.ordinal()));
          group.appendChild(brush);
        }
      }

      return group;
    }
    /**
     * Draws a concreteDiagram as an SVG.
     *
     * <p>This approach is wholly declarative. It currently knows nothing about the on screen
     * rendering of the diagram. To make decisions based on the on screen rendering (such as better
     * label placement) we will, in future, have to build a GVT (from the Batik library) of the
     * SVGDocument.
     *
     * @returns An SVGDocument DOM structure representing the SVG.
     */
    @Override
    public SVGDocument toSVG(ConcreteDiagram cd) {
      // Get a DOMImplementation.
      DOMImplementation domImpl = SVGDOMImplementation.getDOMImplementation();

      // Create an instance of org.w3c.dom.Document.
      String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;
      SVGDocument document = (SVGDocument) domImpl.createDocument(svgNS, "svg", null);

      // Get the root element (the 'svg' element).
      Element svgRoot = document.getDocumentElement();

      // Set the width and height attributes on the root 'svg' element.
      svgRoot.setAttributeNS(null, "width", Integer.toString(cd.getSize()));
      svgRoot.setAttributeNS(null, "height", Integer.toString(cd.getSize()));

      // Draw the shaded zones
      for (ConcreteZone z : cd.getShadedZones()) {
        Element path = document.createElementNS(svgNS, "path");
        path.setAttributeNS(null, "d", toSVGPath(z.getShape(cd.getBox())));
        path.setAttributeNS(null, "fill", "#cccccc"); // grey
        path.setAttributeNS(null, "z-index", Integer.toString(zOrder.SHADING.ordinal()));

        svgRoot.appendChild(path);
      }

      // TODO: Concrete* should return themselves as DocumentFragments
      for (CircleContour c : cd.getCircles()) {
        // Draw the circle
        Element circle = document.createElementNS(svgNS, "circle");
        circle.setAttributeNS(null, "cx", Double.toString(c.get_cx()));
        circle.setAttributeNS(null, "cy", Double.toString(c.get_cy()));
        circle.setAttributeNS(null, "r", Double.toString(c.get_radius()));
        circle.setAttributeNS(null, "z-index", Integer.toString(zOrder.CONTOUR.ordinal()));
        // Not pretty, but it works.
        Color strokeColor = c.color();
        circle.setAttributeNS(
            null, "stroke", (null == strokeColor) ? "black" : "#" + toHexString(c.color()));
        circle.setAttributeNS(null, "stroke-width", "2");
        circle.setAttributeNS(null, "fill", "none");
        svgRoot.appendChild(circle);

        // TODO: Put this text in a path around the circle
        // alternatively come up with some better label placement
        // algorithm
        Element text = document.createElementNS(svgNS, "text");
        text.setAttributeNS(null, "x", Double.toString(c.get_cx()));
        text.setAttributeNS(null, "y", Double.toString(c.get_cy() + c.get_radius()));
        text.setAttributeNS(null, "text-anchor", "middle");
        text.setAttributeNS(
            null, "fill", (null == strokeColor) ? "black" : "#" + toHexString(c.color()));
        text.setAttributeNS(null, "z-index", Integer.toString(zOrder.LABEL.ordinal()));

        Text textNode = document.createTextNode(c.ac.getLabel().getLabel());
        text.appendChild(textNode);
        svgRoot.appendChild(text);
      }

      for (ConcreteSpider cs : cd.getSpiders()) {
        for (ConcreteSpiderFoot f : cs.feet) {
          // Draw the foot
          Element circle = document.createElementNS(svgNS, "circle");
          circle.setAttributeNS(null, "cx", Double.toString(f.getX()));
          circle.setAttributeNS(null, "cy", Double.toString(f.getY()));
          circle.setAttributeNS(null, "r", Double.toString(ConcreteSpiderFoot.FOOT_RADIUS));
          circle.setAttributeNS(null, "z-index", Integer.toString(zOrder.SPIDER.ordinal()));

          circle.setAttributeNS(null, "stroke", "black");
          circle.setAttributeNS(null, "stroke-width", "2");
          circle.setAttributeNS(null, "fill", "black");
          svgRoot.appendChild(circle);
        }

        for (ConcreteSpiderLeg l : cs.legs) {
          Element line = document.createElementNS(svgNS, "line");
          line.setAttributeNS(null, "x1", Double.toString(l.from.getX()));
          line.setAttributeNS(null, "y1", Double.toString(l.from.getY()));
          line.setAttributeNS(null, "x2", Double.toString(l.to.getX()));
          line.setAttributeNS(null, "y2", Double.toString(l.to.getY()));
          line.setAttributeNS(null, "z-index", Integer.toString(zOrder.SPIDER.ordinal()));

          line.setAttributeNS(null, "stroke", "black");
          line.setAttributeNS(null, "stroke-width", "2");
          line.setAttributeNS(null, "fill", "black");
          svgRoot.appendChild(line);
        }
      }
      return document;
    }