예제 #1
0
    /** 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;
    }
예제 #2
0
    private static Point2D evalParametric(CubicCurve2D curve, double t) {
      if (null == curve) {
        return null;
      }

      // B(t) = (1-t)^3 P_0 + 3(1-t)^2t C_1 + 3(1 - t)t^2 C_2 + t^3 P_1
      // do nothing fancy, just calculate it.
      double rx =
          ((Math.pow((1 - t), 3) * curve.getX1()))
              + (3 * Math.pow((1 - t), 2) * t * curve.getCtrlX1())
              + (3 * (1 - t) * t * t * curve.getCtrlX2())
              + (t * t * t * curve.getX2());
      double ry =
          ((Math.pow((1 - t), 3) * curve.getY1()))
              + (3 * Math.pow((1 - t), 2) * t * curve.getCtrlY1())
              + (3 * (1 - t) * t * t * curve.getCtrlY2())
              + (t * t * t * curve.getY2());

      return new Point2D.Float((float) rx, (float) ry);
    }
예제 #3
0
    /**
     * Calculates the unit normal of a particular vector, where the vector is represented by the
     * direction and magnitude of the line segment from (0,0) to (p.x, p.y).
     *
     * @param p
     * @return
     */
    private static Point2D vectorUnitNormal(Point2D p) {
      // if null object passed or if the passed vector has zero length
      if (null == p || ((0 == p.getX()) && (0 == p.getY()))) {
        return null;
      }

      // normalise the input "vector"
      // 1. get length of vector (Pythagoras)
      // 2. divide both x and y by this length
      // note: c cannot be 0 as we've already considered zero length input
      // vectors above.
      double c = Math.sqrt((p.getX() * p.getX()) + (p.getY() * p.getY()));
      double nvx = p.getX() / c;
      double nvy = p.getY() / c;

      // Now rotate (nvx, nvy) by 90 degrees to get the normal for the
      // input vector.
      // rx = nvx * cos (pi/2) - nvy * sin (pi/2)
      // ty = nvx * sin (pi/2) + nvy * cos (pi/2)
      // but cos (pi/2) = 0 and sin (pi/2) = 1, so this simplifies
      return new Point2D.Float((float) (-1 * nvy), (float) nvx);
    }