/*
   *  ComputeMaxError :
   *      Find the maximum squared distance of digitized points
   *      to fitted curve.
   */
  public double ComputeMaxError(
      Vector2[] d, int first, int last, Vector2[] bezCurve, double[] u, int[] splitPoint)
        /* d;     Array of digitized points   */
        /* first, last;   Indices defining region     */
        /* BezierCurve bezCurve  Fitted Bezier curve         */
        /* u;     Parameterization of points  */
        /* splitPoint;  Point of maximum error      */
      {
    int i;
    double maxDist; /*  Maximum error               */
    double dist; /*  Current error               */
    Vector2 P; /*  Point on curve              */
    Vector2 v; /*  Vector from point to curve  */

    // System.out.println("ENTERING MAX ERROR"+splitPoint[0]);
    splitPoint[0] = (last - first + 1) / 2;
    /*  *splitPoint = (last - first + 1)/2; */
    maxDist = 0.0;
    for (i = first + 1; i < last; i++) {
      P = BezierII(3, bezCurve, u[i - first]);
      v = V2SubII(P, d[i]);
      dist = v.V2SquaredLength();
      /*  dist = V2SquaredLength(&v); */
      if (dist >= maxDist) {
        maxDist = dist;
        /* *splitPoint = i; */
        splitPoint[0] = i;
      }
    }
    // System.out.println("EXITING MAX ERROR"+splitPoint[0]);
    // System.out.println("splitPoint "+splitPoint[0]+" and maxDist "+maxDist);
    return (maxDist);
  }
  public Vector2 V2ScaleIII(Vector2 a, double s) {
    Vector2 result = new Vector2();

    result.xset(s * a.xval());
    result.yset(s * a.yval());

    return (result);
  }
 public Vector2 ComputeRightTangent(Vector2[] d, int end)
       /* d;                      Digitized points            */
       /* end;          Index to "right" end of region */
     {
   Vector2 tHat2;
   tHat2 = V2SubII(d[end - 1], d[end]);
   // tHat2 = V2Normalize(tHat2);
   tHat2.V2Normalize();
   // System.out.println("IN RIGHT TANGENT:"+tHat2.xval()+" "+tHat2.yval() );
   return tHat2;
 }
  public Vector2 V2Scale(Vector2 v, double newlen) {
    double len = v.V2Length();
    if (len != 0.0) {
      double temp;

      temp = v.xval();
      v.xset(temp * newlen / len);

      temp = v.yval();
      v.yset(temp * newlen / len);
    }
    return (v);
  }
 /*
  * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
  *Approximate unit tangents at endpoints and "center" of digitized curve
  */
 public Vector2 ComputeLeftTangent(Vector2[] d, int end)
       /* d;   Digitized points*/
       /* end; Index to "left" end of region */
     {
   Vector2 tHat1;
   tHat1 = V2SubII(d[end + 1], d[end]);
   // tHat1 = V2Normalize(tHat1);
   // System.out.println("end "+end+" d[end+1] "+d[end+1].xval()+" "+d[end+1].yval()+" d[end]
   // "+d[end].xval()+" "+d[end].yval()+" IN LEFT TANGENT:"+tHat1.xval()+" "+tHat1.yval() );
   tHat1.V2Normalize();
   // System.out.println("IN LEFT TANGENT:"+tHat1.xval()+" "+tHat1.yval() );
   return tHat1;
 }
  public Vector2 ComputeCenterTangent(Vector2[] d, int center)
        /* d;                     Digitized points */

        /*center;          Index to point inside region        */
      {
    Vector2 V1, V2, tHatCenter;

    V1 = V2SubII(d[center - 1], d[center]);
    V2 = V2SubII(d[center], d[center + 1]);

    tHatCenter = new Vector2();
    tHatCenter.xset((V1.xval() + V2.xval()) / 2.0);
    tHatCenter.yset((V1.yval() + V2.yval()) / 2.0);
    tHatCenter.V2Normalize();
    return tHatCenter;
  }
  public Vector2 V2AddII(Vector2 a, Vector2 b) {
    Vector2 c = new Vector2();

    c.xset(a.xval() + b.xval());
    c.yset(a.yval() + b.yval());
    return (c);
  }
 /* return vector sum c = a+b */
 public Vector2 V2Add(Vector2 a, Vector2 b, Vector2 c) {
   // c = new Vector2();
   c.xset(a.xval() + b.xval());
   c.yset(a.yval() + b.yval());
   // System.out.println("V2Add: "+a.xval()+" + "+b.xval()+" = "+c.xval() );
   // System.out.println("V2Add: "+a.yval()+" + "+b.yval()+" = "+c.yval()+"\n");
   return (c);
 }
 /* return the distance between two points */
 public double V2DistanceBetween2Points(Vector2 a, Vector2 b) {
   double dx = a.xval() - b.xval();
   double dy = a.yval() - b.yval();
   // System.out.println("Distance: "+Math.sqrt((dx*dx)+(dy*dy))+"\n\n");
   return (Math.sqrt((dx * dx) + (dy * dy)));
 }
Esempio n. 10
0
 /* return the dot product of vectors a and b */
 public double V2Dot(Vector2 a, Vector2 b) {
   return (a.xval() * b.xval() + a.yval() * b.yval());
 }
Esempio n. 11
0
  /*
   *  GenerateBezier :
   *  Use least-squares method to find Bezier control points for region.
   *
   */
  public Vector2[] GenerateBezier(
      Vector2[] d, int first, int last, double uPrime[], Vector2 tHat1, Vector2 tHat2)
        /* d:  Array of digitized points   */
        /* first last:  Indices defining region     */
        /* uPrime: Parameter values for region */
        /* tHat1, tHat2:  Unit tangents at endpoints  */
      {
    int i;
    double C[][] = new double[2][2]; /* Matrix C             */
    double[] X = new double[2]; /* Matrix X                     */
    Vector2 A[][]; /* Precomputed rhs for eqn      */
    int nPts; /* Number of pts in sub-curve */
    double det_C0_C1, /* Determinants of matrices     */ det_C0_X, det_X_C1;
    double alpha_l, /* Alpha values, left and right */ alpha_r;
    Vector2 tmp; /* Utility variable             */
    Vector2[] bezCurve = new Vector2[4]; /* RETURN bezier curve ctl pts  */

    // System.out.println("ENTERING GENERATE BEZIER "+tHat1.xval()+" "+tHat1.yval()+"
    // "+tHat2.xval()+" "+tHat2.yval());

    for (i = 0; i < 4; i++) bezCurve[i] = new Vector2();

    /*    bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2)); */
    nPts = last - first + 1;

    A = new Vector2[nPts][2];

    /* Compute the A's  */
    for (i = 0; i < nPts; i++) {
      Vector2 v1 = new Vector2();
      Vector2 v2 = new Vector2();

      v1.xset(tHat1.xval());
      v1.yset(tHat1.yval());
      v2.xset(tHat2.xval());
      v2.yset(tHat2.yval());
      // System.out.println("PT: "+i);
      // System.out.print("that1 length "+tHat1.V2Length()+" "+tHat1.xval()+" "+tHat1.yval() );
      // System.out.print("that2 length "+tHat2.V2Length()+" "+tHat2.xval()+" "+tHat2.yval() );
      // System.out.print("Before: "+v1.xval() +" "+v1.yval() );
      V2Scale(v1, B1(uPrime[i]));
      // System.out.println("after : "+v1.xval() +" "+v1.yval() );
      // System.out.print("Before: "+v2.xval() +" "+v2.yval() );
      V2Scale(v2, B2(uPrime[i]));
      // System.out.println("after : "+v2.xval() +" "+v2.yval() );

      A[i][0] = new Vector2();
      A[i][0].xset(v1.xval());
      A[i][0].yset(v1.yval());
      A[i][1] = new Vector2();
      A[i][1].xset(v2.xval());
      A[i][1].yset(v2.yval());
      //	System.out.println("A[i][0] "+A[i][0].xval()+" "+A[i][0].yval());
      //	System.out.println("A[i][1] "+A[i][1].xval()+" "+A[i][1].yval());
      //	System.out.println("B1 "+B1(uPrime[i])+" B2 "+B2(uPrime[i]));
    }

    /* Create the C and X matrices      */
    C[0][0] = 0.0;
    C[0][1] = 0.0;
    C[1][0] = 0.0;
    C[1][1] = 0.0;
    X[0] = 0.0;
    X[1] = 0.0;

    for (i = 0; i < nPts; i++) {
      C[0][0] += V2Dot(A[i][0], A[i][0]);
      C[0][1] += V2Dot(A[i][0], A[i][1]);
      /*                                      C[1][0] += V2Dot(A[i][0], A[i][1]);*/
      C[1][0] = C[0][1];
      C[1][1] += V2Dot(A[i][1], A[i][1]);

      tmp =
          V2SubII(
              d[first + i],
              V2AddII(
                  V2ScaleIII(d[first], B0(uPrime[i])),
                  V2AddII(
                      V2ScaleIII(d[first], B1(uPrime[i])),
                      V2AddII(
                          V2ScaleIII(d[last], B2(uPrime[i])),
                          V2ScaleIII(d[last], B3(uPrime[i]))))));

      X[0] += V2Dot(A[i][0], tmp);
      X[1] += V2Dot(A[i][1], tmp);
    }

    System.out.println("C " + C[0][0] + " " + C[0][1] + " " + C[1][0] + " " + C[1][1]);
    System.out.println("X " + X[0] + " " + X[1]);

    /* Compute the determinants of C and X      */
    det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
    det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
    det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];

    /* Finally, derive alpha values     */
    if (det_C0_C1 == 0.0) {
      det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
    }
    alpha_l = det_X_C1 / det_C0_C1;
    alpha_r = det_C0_X / det_C0_C1;

    // System.out.println("\n\n\nalpha_l "+alpha_l+" alpha_r "+alpha_r);

    /*  If alpha negative, use the Wu/Barsky heuristic (see text) */

    if (alpha_l < 0.0 || alpha_r < 0.0) {
      int ddd;
      double dist = V2DistanceBetween2Points(d[last], d[first]) / 3.0;

      for (ddd = 0; ddd < 4; ddd++) bezCurve[ddd] = new Vector2();

      bezCurve[0] = d[first];
      bezCurve[3] = d[last];
      // System.out.println("HERE!!!!");

      V2Add(bezCurve[0], V2Scale(tHat1, dist), bezCurve[1]);
      V2Add(bezCurve[3], V2Scale(tHat2, dist), bezCurve[2]);
      return (bezCurve);
    }

    /*  First and last control points of the Bezier curve are */
    /*  positioned exactly at the first and last data points */
    /*  Control points 1 and 2 are positioned an alpha distance out */
    /*  on the tangent vectors, left and right, respectively */
    bezCurve[0] = new Vector2();
    bezCurve[1] = new Vector2();
    bezCurve[2] = new Vector2();
    bezCurve[3] = new Vector2();
    bezCurve[0].xset(d[first].xval());
    bezCurve[0].yset(d[first].yval());
    bezCurve[3].xset(d[last].xval());
    bezCurve[3].yset(d[last].yval());
    // System.out.println("EDW??? 1");
    V2Add(bezCurve[0], V2Scale(tHat1, alpha_l), bezCurve[1]);

    // System.out.println("EDW??? 2");
    V2Add(bezCurve[3], V2Scale(tHat2, alpha_r), bezCurve[2]);

    // System.out.println("BEZ_CURVE is "+bezCurve[0].xval()+" "+bezCurve[0].yval()+" and
    // "+bezCurve[3].xval()+" "+bezCurve[3].yval());
    // System.out.println("BEZ_CURVE is "+bezCurve[1].xval()+" "+bezCurve[1].yval()+" and
    // "+bezCurve[2].xval()+" "+bezCurve[2].yval());

    // System.out.println("EXITING GENERATE BEZIER");
    return (bezCurve);
  }
Esempio n. 12
0
  /*
   *  FitCubic :
   *      Fit a Bezier curve to a (sub)set of digitized points
   */
  public void FitCubic(
      Vector2[] d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error, PrintStream ps)
        // Vector2 tHat1, Vector2 tHat2, double error, PrintStream ps, int i1, int j1)
        /*   d;      Array of digitized points */
        /*   first, last;   Indices of first and last pts in region */
        /*   tHat1, tHat2; Unit tangent vectors at endpoints */
        /*    error;   User-defined error squared     */
        /*    FILE        *fp; */
      {
    Vector2[] bezCurve; /*Control points of fitted Bezier curve*/
    double[] u; /*  Parameter values for point  */
    double[] uPrime; /*  Improved parameter values */
    double maxError; /*  Maximum fitting error        */
    int splitPoint; /*  Point to split point set at  */
    int nPts; /*  Number of points in subset  */
    double iterationError; /*Error below which you try iterating  */
    int maxIterations = 4; /*  Max times to try iterating  */
    Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
    int i;

    iterationError = error * error;
    nPts = last - first + 1;

    splitPoint = nPts; /* MAKE SURE THIS IS CORRECT!! */

    // printf("Error is %f (nPts = %d -- last %d first %d)\n", error, nPts, last, f irst);
    // System.out.println("Error is "+error+" (nPts = "+ nPts+" -- last "+last+" first "+first+")");

    /*  Use heuristic if region only has two points in it */
    if (nPts == 2) {
      double dist = V2DistanceBetween2Points(d[last], d[first]) / 3.0;

      bezCurve = new Vector2[4];
      for (i = 0; i < 4; i++) bezCurve[i] = new Vector2();

      /*                bezCurve = (Point2 *)malloc(4 * sizeof(Point2)); */
      bezCurve[0] = d[first];
      bezCurve[3] = d[last];
      // System.out.println("BEZ CURVE is "+bezCurve[0].xval()+" "+bezCurve[0].yval()+" and
      // "+bezCurve[3].xval()+" "+bezCurve[3].yval());
      // System.out.println("BEZ CURVE is "+bezCurve[1].xval()+" "+bezCurve[1].yval()+" and
      // "+bezCurve[2].xval()+" "+bezCurve[2].yval());
      V2Add(bezCurve[0], V2Scale(tHat1, dist), bezCurve[1]);
      V2Add(bezCurve[3], V2Scale(tHat2, dist), bezCurve[2]);
      //                DrawBezierCurve(3, bezCurve, fp);
      // DrawBezierCurve(3, bezCurve, ps, i1, j1);
      DrawBezierCurve(3, bezCurve, ps);
      /*    printf("Returning from nPts=2\n"); */
      return;
    }

    /*  Parameterize points, and attempt to fit curve */
    u = ChordLengthParameterize(d, first, last);
    // for (i=1;i<5;i++) System.out.print(" "+u[i]);
    // System.out.print("\n");

    bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);

    //    printf("Value %4.3f\n", sizeof(bezCurve)/sizeof(Point2));

    /*  Find max deviation of points to fitted curve */

    int[] split = new int[1];
    // System.out.println("BEFORE: SPLITPOINT "+splitPoint);
    split[0] = splitPoint;
    // maxError=1;
    maxError = ComputeMaxError(d, first, last, bezCurve, u, split);
    splitPoint = split[0];
    // System.out.println("AFTER: SPLITPOINT "+splitPoint);
    if (maxError < error) {
      // DrawBezierCurve(3, bezCurve, fp);
      // DrawBezierCurve(3, bezCurve, ps, i1, j1);
      DrawBezierCurve(3, bezCurve, ps);
      // free((void *)u);
      //   free(u);
      // free((void *)bezCurve);
      //   free(bezCurve);
      //    printf("Returning from maxerror %f\n", maxError);
      return;
    }
    /*  If error not too large, try some reparameterization  */
    /*  and iteration */
    if (maxError < iterationError) {
      // printf("Returning from maxerror %f and iteration error  %f\n", maxError, it erationError);
      for (i = 0; i < maxIterations; i++) {

        /* int [] split = new int[1]; */

        split[0] = splitPoint;

        uPrime = Reparameterize(d, first, last, u, bezCurve);
        bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
        maxError = ComputeMaxError(d, first, last, bezCurve, uPrime, split);
        splitPoint = split[0];

        if (maxError < error) {
          // DrawBezierCurve(3, bezCurve, fp);
          // DrawBezierCurve(3, bezCurve, ps, i1, j1);
          DrawBezierCurve(3, bezCurve, ps);
          // free((void *)u);
          //  free(u);
          // free((void *)bezCurve);
          //  free(bezCurve);
          return;
        }
        // free((void *)u);
        //  free(u);
        u = uPrime;
      }
    }

    /* Fitting failed -- split at max error point and fit recursively */
    // free((void *)u);
    //  free(u);
    // free((void *)bezCurve);
    //   free(bezCurve);
    tHatCenter = ComputeCenterTangent(d, splitPoint);
    // FitCubic(d, first, splitPoint, tHat1, tHatCenter, error, fp);
    // FitCubic(d, first, splitPoint, tHat1, tHatCenter, error, ps,i1,j1);
    //   FitCubic(d, first, splitPoint, tHat1, tHatCenter, error, ps);
    // V2Negate(&tHatCenter);
    tHatCenter.V2Negate();
    // FitCubic(d, splitPoint, last, tHatCenter, tHat2, error, fp);
    // FitCubic(d, splitPoint, last, tHatCenter, tHat2, error, ps,i1,j1);
    //    FitCubic(d, splitPoint, last, tHatCenter, tHat2, error, ps);

    // System.out.println("EXITING FITCUBIC");
  }
Esempio n. 13
0
  /*
   *  NewtonRaphsonRootFind :
   *      Use Newton-Raphson iteration to find better root.
   */
  public double NewtonRaphsonRootFind(Vector2[] Q, Vector2 P, double u)
        /* Q;      Current fitted curve        */
        /* P;      Digitized point             */
        /* u;      Parameter value for "P"     */
      {
    double numerator, denominator;
    Vector2[] Q1 = new Vector2[3];
    Vector2[] Q2 = new Vector2[2]; /*  Q' and Q''                  */
    Vector2 Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q''  */
    double uPrime; /*  Improved u                  */
    int i;

    /* Compute Q(u)     */
    Q_u = BezierII(3, Q, u);

    /* Generate control vertices for Q' */
    for (i = 0; i <= 2; i++) {
      double x1 = Q[i + 1].xval() - Q[i].xval();
      double y1 = Q[i + 1].yval() - Q[i].yval();

      Q1[i] = new Vector2();
      Q1[i].xset(x1 * 3.0);
      Q1[i].yset(y1 * 3.0);
    }

    /* Generate control vertices for Q'' */
    for (i = 0; i <= 1; i++) {
      double x1 = Q[i + 1].xval() - Q[i].xval();
      double y1 = Q[i + 1].yval() - Q[i].yval();

      Q2[i] = new Vector2();
      Q2[i].xset(x1 * 2.0);
      Q2[i].yset(y1 * 2.0);
    }

    /* Compute Q'(u) and Q''(u) */
    Q1_u = BezierII(2, Q1, u);
    Q2_u = BezierII(1, Q2, u);

    /* Compute f(u)/f'(u) */
    numerator = (Q_u.xval() - P.xval()) * (Q1_u.xval()) + (Q_u.yval() - P.yval()) * (Q1_u.yval());
    denominator =
        (Q1_u.xval()) * (Q1_u.xval())
            + (Q1_u.yval()) * (Q1_u.yval())
            + (Q_u.xval() - P.xval()) * (Q2_u.xval())
            + (Q_u.yval() - P.yval()) * (Q2_u.yval());

    /* u = u - f(u)/f'(u) */
    uPrime = u - (numerator / denominator);
    return (uPrime);
  }