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); }
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 V2ScaleIII(Vector2 a, double s) { Vector2 result = new Vector2(); result.xset(s * a.xval()); result.yset(s * a.yval()); return (result); }
/* * 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); }
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); }
/* 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))); }
/* 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()); }
/* * 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); }