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 );
}
Exemple #3
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;
}