Example #1
0
inline double   EulerSpiral::compute_error(double k0, double L)
{
    //assumes normalized parameters

    //compute the endpoint of the Euler spiral with the given intrinsic parameters
    double gamma = 2*(params.turningAngle - k0*L)/(L*L);
    Point2D<double> cur_end_pt = compute_end_pt(k0, gamma, L, true);

    //the error is the distance between the current end point and the desired end point
    return euc_distance(Point2D<double>(1,0), cur_end_pt);
}
Example #2
0
static int fair_distances(struct point *pt, struct point pts[], int npts, double epsilon)
{
	int i;

	pt->dists = calloc(npts, sizeof(double));

	for (i = 0; i < npts; i++) {
		if ((fabs(pt->x - pts[i].x) < POS_THRESHOLD * epsilon) ||
		    (fabs(pt->y - pts[i].y) < POS_THRESHOLD * epsilon)) {
			//printf("points too close, discarding: (%.2lf, %.2lf)   (%.2lf, %.2lf)\n", pt->x, pt->y, pts[i].x, pts[i].y);
			return 0;
		}

		pt->dists[i] = euc_distance(pt->x, pts[i].x, pt->y, pts[i].y);
	}
	return 1;
}
Example #3
0
// Computes the Euler spiral for the given params
//if the global lookup table is available, it looks up the ES params first and then optimizes them
//this should dramatically cut down in the time to optimize
void EulerSpiral::compute_es_params ()
{
    //compute scaling distance
    double d = euc_distance(params.start_pt, params.end_pt);
    params.psi = angle0To2Pi(atan2(params.end_pt.y()-params.start_pt.y(),params.end_pt.x()-params.start_pt.x()));

    //degeneracy check
    if (d<eError)
        return;

    //first compute a biarc estimate
    _bi_arc_estimate.set_start_params(params.start_pt, params.start_angle);
    _bi_arc_estimate.set_end_params(params.end_pt, params.end_angle);
    _bi_arc_estimate.compute_biarc_params();

    //get the total turning angle::This is an important parameter because
    //it defines the one solution out of many possible solutions
    params.turningAngle = _bi_arc_estimate.params.K1*_bi_arc_estimate.params.L1 +
                          _bi_arc_estimate.params.K2*_bi_arc_estimate.params.L2;

    //From here on, normlize the parameters and use these to perform the optimization

    double k0_init_est = _bi_arc_estimate.params.K1*d;
    double L_init_est = _bi_arc_estimate.params.L()/d;
    double dstep = 0.1;

    //Alternately, we can get the initial values from the lookup table and perform
    //the optimization from there
    //double k0_init_est = globalEulerSpiralLookupTable->get_globalEulerSpiralLookupTable()->k0(CCW(params.psi, params.start_angle), CCW(params.psi, params.end_angle));
    //double L_init_est = globalEulerSpiralLookupTable->get_globalEulerSpiralLookupTable()->L(CCW(params.psi, params.start_angle), CCW(params.psi, params.end_angle));
    //double dstep = globalEulerSpiralLookupTable->get_globalEulerSpiralLookupTable()->dt()/4;

    //then perform a simple gradient descent to find the real solution
    double error = compute_error(k0_init_est, L_init_est);
    double prev_error = error;

    double k0 = k0_init_est;
    double L = L_init_est;

    double e1, e2, e3, e4 = 0;

    for (int i=0; i<MAX_NUM_ITERATIONS; i++)
    {
        if (error<eError)
            break;

        e1 = compute_error(k0 + dstep, L);
        e2 = compute_error(k0 - dstep, L);
        e3 = compute_error(k0, L + dstep);
        if (L>dstep)  e4 = compute_error(k0, L - dstep);

        error = MIN2(MIN2(e1,e2),MIN2(e3,e4));

        if (error>prev_error)
        {
            dstep = dstep/2;
            continue;
        }

        if    (error==e1)  k0 = k0 + dstep;
        else if (error==e2) k0 = k0 - dstep;
        else if (error==e3) L = L + dstep;
        else if (error==e4) L = L - dstep;

        prev_error = error;
    }

    //store the parameters
    params.K0 = k0/d;
    params.L = L*d;
    params.gamma = 2*(params.turningAngle - k0*L)/(L*L)/(d*d);
    params.K2 = (k0 + params.gamma*L)/d;
    params.error = error;
}