static void poly_level_do_with_mask(GwyDataField *dfield, GwyDataField *mask, GwyDataField *result, GwyDataField *bg, const PolyLevelArgs *args) { gint *term_powers; gdouble *coeffs; gint nterms, i, j, k; k = 0; if (args->independent) { nterms = (args->col_degree + 1)*(args->row_degree + 1); term_powers = g_new(gint, 2*nterms); for (i = 0; i <= args->col_degree; i++) { for (j = 0; j <= args->row_degree; j++) { term_powers[k++] = i; term_powers[k++] = j; } } } else { nterms = (args->max_degree + 1)*(args->max_degree + 2)/2; term_powers = g_new(gint, 2*nterms); for (i = 0; i <= args->max_degree; i++) { for (j = 0; j <= args->max_degree - i; j++) { term_powers[k++] = i; term_powers[k++] = j; } } } coeffs = gwy_data_field_fit_poly(dfield, mask, nterms, term_powers, args->masking == GWY_MASK_EXCLUDE, NULL); gwy_data_field_subtract_poly(result, nterms, term_powers, coeffs); gwy_data_field_data_changed(result); if (bg) { for (i = 0; i < nterms; i++) { coeffs[i] = -coeffs[i]; } gwy_data_field_subtract_poly(bg, nterms, term_powers, coeffs); gwy_data_field_data_changed(bg); } g_free(coeffs); g_free(term_powers); }
/* Does not include x and y offsets of the data field */ static gboolean curvature_calculate(GwyDataField *dfield, GwyDataField *mask, const CurvatureArgs *args, gdouble *params, Intersection *i1, Intersection *i2) { enum { DEGREE = 2 }; enum { A, BX, CXX, BY, CXY, CYY, NTERMS }; gint term_powers[2*NTERMS]; gdouble coeffs[NTERMS], ccoeffs[NTERMS]; gdouble xreal, yreal, qx, qy, q, mx, my; gint xres, yres, i, j, k; gboolean ok; k = 0; g_assert(NTERMS == (DEGREE + 1)*(DEGREE + 2)/2); for (i = 0; i <= DEGREE; i++) { for (j = 0; j <= DEGREE - i; j++) { term_powers[k++] = j; term_powers[k++] = i; } } gwy_data_field_fit_poly(dfield, mask, NTERMS, term_powers, args->masking != GWY_MASK_INCLUDE, coeffs); gwy_debug("NORM a=%g, bx=%g, by=%g, cxx=%g, cxy=%g, cyy=%g", coeffs[A], coeffs[BX], coeffs[BY], coeffs[CXX], coeffs[CXY], coeffs[CYY]); /* Transform coeffs from normalized coordinates to coordinates that are * still numerically around 1 but have the right aspect ratio. */ xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); xreal = gwy_data_field_get_xreal(dfield); yreal = gwy_data_field_get_yreal(dfield); qx = 2.0/xreal*xres/(xres - 1.0); qy = 2.0/yreal*yres/(yres - 1.0); q = sqrt(qx*qy); mx = sqrt(qx/qy); my = sqrt(qy/qx); ccoeffs[0] = coeffs[A]; ccoeffs[1] = mx*coeffs[BX]; ccoeffs[2] = my*coeffs[BY]; ccoeffs[3] = mx*mx*coeffs[CXX]; ccoeffs[4] = coeffs[CXY]; ccoeffs[5] = my*my*coeffs[CYY]; gwy_math_curvature(ccoeffs, params + PARAM_R1, params + PARAM_R2, params + PARAM_PHI1, params + PARAM_PHI2, params + PARAM_X0, params + PARAM_Y0, params + PARAM_A); /* Transform to physical values. */ /* FIXME: Why we have q*q here? */ params[PARAM_R1] = 1.0/(q*q*params[PARAM_R1]); params[PARAM_R2] = 1.0/(q*q*params[PARAM_R2]); params[PARAM_X0] = params[PARAM_X0]/q + 0.5*xreal; params[PARAM_Y0] = params[PARAM_Y0]/q + 0.5*yreal; ok = TRUE; for (i = 0; i < 2; i++) { ok &= intersect_with_boundary(params[PARAM_X0], params[PARAM_Y0], -params[PARAM_PHI1 + i], xreal, yreal, i1 + i, i2 + i); } return ok; }