Exemple #1
0
void test_on_border_edge_case() {

	// Create an array of temperatures...
	double u[50];
	fill_array(50, u, 0.0);

	// Create borders
	border_t a = {10.0, {0.0, 100.0}, {0.0}},
			 b = {20.0, {100.0, 0.0}, {0.0}};


	// Run an iteration
	phase_update(&a, &b, u, &material);


	ASSERT(
		"Correct temperatures for near-border points",
		double_equal(u[11], 100.0) &&
		double_equal(u[19], 100.0)
	);


	// Try again with a slighly different position
	fill_array(50, u, 0.0);
	a.position = 10.0 - SMALL_VALUE / 100.0;
	a.u[1] = 100.0;
	b.u[0] = 100.0;

	phase_update(&a, &b, u, &material);

	ASSERT(
		"Temperatures have been updated correctly",
		double_approx_equal(u[11], 100.0, 0.01) &&
		double_equal(u[19], 100.0)
	);


	// Try again, but now with the other border.
	fill_array(50, u, 0.0);
	a.position = 10.0;
	b.position = 20.0 + SMALL_VALUE / 100.0;
	a.u[1] = 100.0;
	b.u[0] = 100.0;

	phase_update(&a, &b, u, &material);

	ASSERT(
		"Temperatures have been updated correctly",
		double_equal(u[11], 100.0) &&
		double_approx_equal(u[19], 100.0, 0.01)
	);
}
Exemple #2
0
/* DIFF: was gto_fit_rxyscale */
static int
geo_fit_linear(
        geomap_fit_t* const fit,
        surface_t* const sx1,
        surface_t* const sy1,
        const size_t ncoord,
        const coord_t* const input,
        const coord_t* const ref,
        const double* const weights,
        double* const residual_x,
        double* const residual_y,
        stimage_error_t* error) {

    bbox_t  bbox;
    double  sw      = 0.0;
    coord_t sr      = {0.0, 0.0};
    coord_t si      = {0.0, 0.0};
    coord_t r0      = {0.0, 0.0};
    coord_t i0      = {0.0, 0.0};
    double  sxrxr   = 0.0;
    double  syryr   = 0.0;
    double  syrxi   = 0.0;
    double  sxryi   = 0.0;
    double  sxrxi   = 0.0;
    double  syryi   = 0.0;
    double  num     = 0.0;
    double  denom   = 0.0;
    double  theta   = 0.0;
    double  ctheta  = 0.0;
    double  stheta  = 0.0;
    coord_t cthetac = {0.0, 0.0};
    coord_t sthetac = {0.0, 0.0};
    double  xmag    = 0.0;
    double  ymag    = 0.0;
    size_t  i       = 0;
    int     status  = 1;

    assert(fit);
    assert(sx1);
    assert(sy1);
    assert(input);
    assert(ref);
    assert(weights);
    assert(residual_x);
    assert(residual_y);

    surface_free(sx1);
    surface_free(sy1);

    bbox_copy(&fit->bbox, &bbox);
    bbox_make_nonsingular(&bbox);

    /* Compute the sums required to determine the offsets */
    compute_sums(ncoord, input, ref, weights, &sw, &si, &sr);

    if (sw < 3.0) {
        if (fit->projection == geomap_proj_none) {
            stimage_error_set_message(
                    error, "Too few data points for X and Y fits.");
        } else {
            stimage_error_set_message(
                    error, "Too few data points for XI and ETA fits.");
        }
        goto exit;
    }

    r0.x = sr.x / sw;
    r0.y = sr.y / sw;
    i0.x = si.x / sw;
    i0.y = si.y / sw;
    for (i = 0; i < ncoord; ++i) {
        sxrxr += weights[i] * (ref[i].x - r0.x) * (ref[i].x - r0.x);
        syryr += weights[i] * (ref[i].y - r0.y) * (ref[i].y - r0.y);
        syrxi += weights[i] * (ref[i].y - r0.y) * (input[i].x - i0.x);
        sxryi += weights[i] * (ref[i].x - r0.x) * (input[i].y - i0.y);
        sxrxi += weights[i] * (ref[i].x - r0.x) * (input[i].x - i0.x);
        syryi += weights[i] * (ref[i].y - r0.y) * (input[i].y - i0.y);
    }

    /* Compute the rotation angle */
    num = 2.0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi);
    denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - \
        sxrxr * (syrxi + syryi) * (syrxi - syryi);
    if (double_approx_equal(num, 0.0) && double_approx_equal(denom, 0.0)) {
        theta = 0.0;
    } else {
        theta = atan2(num, denom) / 2.0;
        if (theta < 0.0) {
            theta += M_PI * 2.0;
        }
    }

    ctheta = cos(theta);
    stheta = sin(theta);

    /* Compute the X magnification factor */
    num = sxrxi * ctheta - sxryi * stheta;
    denom = sxrxr;
    if (denom <= 0.0) {
        xmag = 1.0;
    } else {
        xmag = num / denom;
    }

    /* Compute the Y magnification factor */
    num = syrxi * stheta + syryi * ctheta;
    denom = syryr;
    if (denom <= 0.0) {
        ymag = 1.0;
    } else {
        ymag = num / denom;
    }

    /* Compute the polynomial coefficients */
    cthetac.x = xmag * ctheta;
    sthetac.x = ymag * stheta;
    sthetac.y = xmag * stheta;
    cthetac.x = ymag * ctheta;

    /* Compute the X and Y fit coefficients */
    if (compute_surface_coefficients(
                fit->function, &bbox, &i0, &r0, &cthetac, &sthetac, sx1, sy1,
                error)) goto exit;

    /* Compute the residuals */
    if (compute_residuals(
                sx1, sy1, ncoord, input, ref, residual_x, residual_y,
                error)) goto exit;

    /* Compute the number of zero-weighted points */
    fit->n_zero_weighted = count_zero_weighted(ncoord, weights);

    /* Compute the rms of the x and y fits */
    compute_rms(
            ncoord, weights, residual_x, residual_y, &fit->xrms, &fit->yrms);

    fit->ncoord = ncoord;

    status = 0;

 exit:

    return status;
}
Exemple #3
0
static int
geo_get_coeff(
        const surface_t* const sx,
        const surface_t* const sy,
        /* Output */
        coord_t* const shift,
        coord_t* const scale,
        coord_t* const rot,
        stimage_error_t* const error) {

    size_t nxxcoeff, nxycoeff, nyxcoeff, nyycoeff;
    double xxrange  = 1.0;
    double xyrange  = 1.0;
    double xxmaxmin = 1.0;
    double xymaxmin = 1.0;
    double yxrange  = 1.0;
    double yyrange  = 1.0;
    double yxmaxmin = 1.0;
    double yymaxmin = 1.0;
    double a, b, c, d;

    assert(sx);
    assert(sy);
    assert(shift);
    assert(scale);
    assert(rot);
    assert(sx->coeff);
    assert(sy->coeff);
    assert(sx->ncoeff >= 3);
    assert(sy->ncoeff >= 3);

    nxxcoeff = nyxcoeff = sx->nxcoeff;
    nxycoeff = nyycoeff = sy->nycoeff;

    /* Get the data range */
    if (sx->type != surface_type_polynomial) {
        xxrange = (sx->bbox.max.x - sx->bbox.min.x) / 2.0;
        xxmaxmin = -(sx->bbox.max.x - sx->bbox.min.x) / 2.0;
        xyrange = (sx->bbox.max.y - sx->bbox.min.y) / 2.0;
        xymaxmin = (sx->bbox.max.y - sx->bbox.min.y) / 2.0;
    }

    if (sy->type != surface_type_polynomial) {
        yxrange = (sy->bbox.max.x - sy->bbox.min.x) / 2.0;
        yxmaxmin = (sy->bbox.max.x - sy->bbox.min.x) / 2.0;
        yyrange = (sy->bbox.max.y - sy->bbox.min.y) / 2.0;
        yymaxmin = (sy->bbox.max.y - sy->bbox.min.y) / 2.0;
    }

    /* Get the shifts */
    shift->x = sx->coeff[0] + \
        sx->coeff[1] * xxmaxmin / xxrange + \
        sx->coeff[2] * xymaxmin / xyrange;
    shift->y = sy->coeff[0] + \
        sy->coeff[1] * yxmaxmin / yxrange +
        sx->coeff[2] * yymaxmin / yyrange;

    /* Get the rotation and scaling parameters */
    if (nxxcoeff > 1) {
        a = sx->coeff[1] / xxrange;
    } else {
        a = 0.0;
    }

    if (nxycoeff > 1) {
        b = sx->coeff[nxxcoeff] / xyrange;
    } else {
        b = 0.0;
    }

    if (nyxcoeff > 1) {
        c = sx->coeff[1] / yxrange;
    } else {
        c = 0.0;
    }

    if (nyycoeff > 1) {
        d = sy->coeff[nyxcoeff] / yyrange;
    } else {
        d = 0.0;
    }

    scale->x = sqrt(a*a + c*c);
    scale->y = sqrt(b*b + d*d);

    if (double_approx_equal(a, 0.0) && double_approx_equal(c, 0.0)) {
        rot->x = 0.0;
    } else {
        rot->x = RADTODEG(atan2(-c, a));
    }
    if (rot->x < 0.0) {
        rot->x += 360.0;
    }

    if (double_approx_equal(b, 0.0) && double_approx_equal(d, 0.0)) {
        rot->y = 0.0;
    } else {
        rot->y = RADTODEG(atan2(b, d));
    }
    if (rot->y < 0.0) {
        rot->y += 360.0;
    }

    return 0;
}