/** Normalize an individual stroke to time increments given by timestep. */
  public static TimedStroke interpolate(TimedStroke s, int timestep) {
    long t0 = s.getTimestamp(0);
    long tN = s.getTimestamp(s.getVertexCount() - 1);
    int nsteps = (int) ((tN - t0) / timestep);
    TimedStroke out = new TimedStroke();
    long tcur = t0;
    int j = 0;
    for (int i = 0; i < nsteps; i++) {
      while (j < s.getVertexCount() && s.getTimestamp(j) <= tcur) {
        j++;
      }
      if (j >= s.getVertexCount()) {
        throw new RuntimeException("not enough points!");
      } else {
        long tplus = s.getTimestamp(j);
        long tminus = s.getTimestamp(j - 1);

        double xcur = (tplus - tcur) * s.getX(j - 1) + (tcur - tminus) * s.getX(j);
        xcur = xcur / (tplus - tminus);

        double ycur = (tplus - tcur) * s.getY(j - 1) + (tcur - tminus) * s.getY(j);
        ycur = ycur / (tplus - tminus);

        out.addVertex((float) xcur, (float) ycur, tcur);
        tcur += timestep;
      }
    }
    return out;
  }
 /** Treat the current stroke as a lasso selection if it is mostly closed. */
 public void actionPerformed(ActionEvent evt) {
   _interp.removeCurrentSymbol();
   TimedStroke stroke = _interp.getCurrentStroke();
   int num = stroke.getVertexCount();
   /*
   double length = PathLengthFE.pathLength(stroke);
   double dist = FEUtilities.distance(stroke.getX(0), stroke.getY(0),
           stroke.getX(num-1), stroke.getY(num-1));
   double ratio = dist/length;
   if(ratio <= CLOSE_PROPORTION){
   */
   Polygon2D poly = new Polygon2D.Float();
   poly.moveTo(stroke.getX(0), stroke.getY(0));
   for (int i = 1; i < num; i++) {
     poly.lineTo(stroke.getX(i), stroke.getY(i));
   }
   poly.closePath();
   Iterator iter = _interp.getController().containedSketchFigures(poly);
   ArrayList hitFigures = new ArrayList();
   while (iter.hasNext()) {
     Figure f = (Figure) iter.next();
     if (f instanceof FigureDecorator) {
       f = ((FigureDecorator) f).getDecoratedFigure();
     }
     hitFigures.add(f);
   }
   //        }
   toggleSelection(hitFigures);
 }
示例#3
0
  /**
   * Return the indices where the corners occur in the given stroke. Return null if no corners exist
   * in the stroke. Iterate over the points in the stroke, for every three points (p1, p2, p3) we
   * form two vectors, (p1,p2) and (p2, p3). If the dot product of these two vectors is less than
   * threshDot, then there is definitely an angle at p2. If the dot product is greater than
   * threshDot but less than threshRelaxedDot, it is likely that there is an angle at p2, but we're
   * not sure. In this case, the magnitudes of both vectors are calculated, m1 and m2. Let 'plen' be
   * the stroke path length, we calculate r1 = m1/plen and r2 = m2/plen. If either r1 or r2 is
   * greater than threshMagRatio, then we say that there is a corner. If both vectors are really
   * short (r1<threshMagRatio && r2<threshMagRatio), then they are not significant enough to be used
   * to determine a corner. They are more likely to be noise due to the pen/tablet hardware.
   */
  public static final int[] cornerIndices(
      TimedStroke s, double threshMagRatio, double threshDot, double threshRelaxedDot) {
    if (s == null) {
      return null;
    } else if (s.getVertexCount() < 3) {
      return null;
    } else {
      int numPoints = s.getVertexCount();
      ArrayList cornerIndices = new ArrayList();
      double pathLength = PathLengthFE.pathLength(s);
      double x1, y1, x2, y2, x3, y3;
      for (int i = 0; i < numPoints - 2; i++) {
        x1 = s.getX(i);
        y1 = s.getY(i);
        x2 = s.getX(i + 1);
        y2 = s.getY(i + 1);
        x3 = s.getX(i + 2);
        y3 = s.getY(i + 2);
        double dot = FEUtilities.dotProduct(x1, y1, x2, y2, x3, y3);

        if (dot < threshDot) { // definitely an angle
          double angle = Math.acos(dot);
          angle = Math.toDegrees(angle);
          int j = i + 1;
          cornerIndices.add(new Integer(j));
          //                        numCorners++;
        } else if (dot < threshRelaxedDot) {
          // likely to be an angle
          double l1 = FEUtilities.distance(x1, y1, x2, y2);
          double l2 = FEUtilities.distance(x2, y2, x3, y3);
          l1 = l1 / pathLength;
          l2 = l2 / pathLength;
          if ((l1 > threshMagRatio) || (l2 > threshMagRatio)) {
            double angle = Math.acos(dot);
            angle = Math.toDegrees(angle);
            //                            numCorners++;
            int j = i + 1;
            cornerIndices.add(new Integer(j));
          }
        }
      }
      if (cornerIndices.size() == 0) {
        return null;
      } else {
        int arr[] = new int[cornerIndices.size()];
        // System.out.println("Corner indices:-----");
        int k = 0;
        for (Iterator i = cornerIndices.iterator(); i.hasNext(); ) {
          Integer index = (Integer) i.next();
          int val = index.intValue();
          arr[k++] = val;
          // System.out.println(val+":("+s.getX(val)+", "+s.getY(val)+")");
        }
        // System.out.println("--------------------");
        return arr;
      }
    }
  }