int fit_cubic(Point<ndims> *pts, int first, int last, Vector<ndims> t_hat1, Vector<ndims> t_hat2, double error_bound, Point<ndims> *curve, double &sum_error) { int npts = last - first + 1; if (npts == 2) { double dist = distance(pts[last], pts[first]) / 3.; curve[0] = pts[first]; curve[3] = pts[last]; curve[1] = curve[0] + t_hat1 * dist; curve[2] = curve[3] + t_hat2 * dist; sum_error = 0; return 4; } double *u = (double *)malloc(npts * sizeof(double)); chord_length_parameterize(pts, first, last, u); int nctrlpts = gen_bezier(pts, first, last, u, t_hat1, t_hat2, curve); int split; double max_error = calc_max_error(pts, first, last, curve, u, split, sum_error); if (max_error < error_bound) { free(u); return nctrlpts; } int max_n_iters = 4; if (max_error < error_bound * error_bound) { for (int i = 0; i < max_n_iters; ++i) { double *u_prime = (double *)malloc(npts * sizeof(double)); reparameterize(pts, first, last, u, curve, u_prime); nctrlpts = gen_bezier(pts, first, last, u_prime, t_hat1, t_hat2, curve); max_error = calc_max_error(pts, first, last, curve, u_prime, split, sum_error); free(u); u = u_prime; } if (max_error < error_bound) { free(u); return nctrlpts; } } free(u); Vector<ndims> t_hat_center = calc_center_tangent(pts, split); double serror1, serror2; int nctrlpts0 = fit_cubic(pts, first, split, t_hat1, t_hat_center, error_bound, curve, serror1); int nctrlpts1 = fit_cubic(pts, split, last, -t_hat_center, t_hat2, error_bound, curve + nctrlpts0, serror2); sum_error = serror1 + serror2; return nctrlpts0 + nctrlpts1; }
int main( int argc, char *argv[] ) { STRING input_filename, output_filename; STRING model_filename; File_formats src_format, model_format; int n_src_objects, n_model_objects; object_struct **src_objects, **model_objects; polygons_struct *original, *model; Real movement_threshold, ratio; int n_iters, method, grid_size; initialize_argument_processing( argc, argv ); if( !get_string_argument( NULL, &input_filename ) || !get_string_argument( NULL, &model_filename ) || !get_string_argument( NULL, &output_filename ) ) { print_error( "Usage: %s input.obj model.obj output.obj\n", argv[0] ); return( 1 ); } (void) get_int_argument( 1, &n_iters ); (void) get_real_argument( 1.0, &ratio ); (void) get_int_argument( 0, &method ); (void) get_int_argument( 30, &grid_size ); (void) get_real_argument( 0.0, &movement_threshold ); if( input_graphics_file( input_filename, &src_format, &n_src_objects, &src_objects ) != OK || n_src_objects != 1 || get_object_type(src_objects[0]) != POLYGONS ) { print_error( "Error in %s\n", input_filename ); return( 1 ); } if( input_graphics_file( model_filename, &model_format, &n_model_objects, &model_objects ) != OK || n_model_objects != 1 || get_object_type(model_objects[0]) != POLYGONS ) { print_error( "Error in %s\n", model_filename ); return( 1 ); } original = get_polygons_ptr( src_objects[0] ); model = get_polygons_ptr( model_objects[0] ); if( !objects_are_same_topology( original->n_points, original->n_items, original->end_indices, original->indices, model->n_points, model->n_items, model->end_indices, model->indices ) ) { print_error( "Mismatched topology.\n" ); return( 1 ); } reparameterize( original, model, method, grid_size, ratio, movement_threshold, n_iters ); if( output_graphics_file( output_filename, src_format, n_src_objects, src_objects ) != OK ) return( 1 ); delete_object_list( n_src_objects, src_objects ); output_alloc_to_file( NULL ); return( 0 ); }
QPointF *fitCubic(QPolygonF &points,int first,int last,FitVector tHat1,FitVector tHat2,float error,int &width) { double *u; double *uPrime; double maxError; int splitPoint; int nPts; double iterationError; int maxIterations=4; FitVector tHatCenter; QPointF *curve; int i; width=0; iterationError=error*error; nPts = last-first+1; if (nPts == 2) { double dist = distance(points[last], points[first]) / 3.0; curve = new QPointF[4]; curve[0] = points[first]; curve[3] = points[last]; tHat1.scale(dist); tHat2.scale(dist); curve[1] = tHat1 + curve[0]; curve[2] = tHat2 + curve[3]; width=4; return curve; } /* Parameterize points, and attempt to fit curve */ u = chordLengthParameterize(points, first, last); curve = generateBezier(points, first, last, u, tHat1, tHat2); /* Find max deviation of points to fitted curve */ maxError = computeMaxError(points, first, last, curve, u, &splitPoint); if (maxError < error) { delete[] u; width=4; return curve; } /* If error not too large, try some reparameterization */ /* and iteration */ if (maxError < iterationError) { for (i = 0; i < maxIterations; i++) { uPrime = reparameterize(points, first, last, u, curve); curve = generateBezier(points, first, last, uPrime, tHat1, tHat2); maxError = computeMaxError(points, first, last, curve, uPrime, &splitPoint); if (maxError < error) { delete[] u; width=4; return curve; } delete[] u; u = uPrime; } } /* Fitting failed -- split at max error point and fit recursively */ delete[] u; delete[] curve; tHatCenter = computeCenterTangent(points, splitPoint); int w1,w2; QPointF *cu1=NULL, *cu2=NULL; cu1 = fitCubic(points, first, splitPoint, tHat1, tHatCenter, error,w1); tHatCenter.negate(); cu2 = fitCubic(points, splitPoint, last, tHatCenter, tHat2, error,w2); QPointF *newcurve = new QPointF[w1+w2]; for (int i=0;i<w1;i++) newcurve[i]=cu1[i]; for (int i=0;i<w2;i++) newcurve[i+w1]=cu2[i]; delete[] cu1; delete[] cu2; width=w1+w2; return newcurve; }