/** * gwy_surface_copy: * @src: Source surface. * @dest: Destination surface. * * Copies the data of a surface to another surface of the same dimensions. * * Only the data points are copied. To make a surface completely identical to * another, including units and change of dimensions, you can use * gwy_surface_clone(). * * Since: 2.45 **/ void gwy_surface_copy(GwySurface *src, GwySurface *dest) { g_return_if_fail(GWY_IS_SURFACE(src)); g_return_if_fail(GWY_IS_SURFACE(dest)); g_return_if_fail(dest->n == src->n); gwy_assign(dest->data, src->data, src->n); gwy_surface_invalidate(dest); }
/** * gwy_surface_new_part: * @surface: A surface. * @xfrom: Minimum x-coordinate value. * @xto: Maximum x-coordinate value. * @yfrom: Minimum y-coordinate value. * @yto: Maximum y-coordinate value. * * Creates a new surface as a part of another surface. * * The new surface consits of data with lateral coordinates within the * specified ranges (inclusively). It may be empty. * * Data are physically copied, i.e. changing the new surface data does not * change @surface's data and vice versa. * * Returns: A new surface. * * Since: 2.45 **/ GwySurface* gwy_surface_new_part(GwySurface *surface, gdouble xfrom, gdouble xto, gdouble yfrom, gdouble yto) { GwySurface *part; guint n, i; g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL); part = gwy_surface_new_alike(surface); if (!surface->n || xfrom > xto || yfrom > yto) return part; n = 0; for (i = 0; i < surface->n; i++) { gdouble x = surface->data[i].x, y = surface->data[i].y; if (x >= xfrom && x <= xto && y >= yfrom && y <= yto) n++; } part->n = n; alloc_data(part); n = 0; for (i = 0; i < surface->n; i++) { gdouble x = surface->data[i].x, y = surface->data[i].y; if (x >= xfrom && x <= xto && y >= yfrom && y <= yto) part->data[n++] = surface->data[i]; } return part; }
/** * gwy_surface_invalidate: * @surface: A surface. * * Invalidates cached surface statistics. * * Cached statistics include ranges returned by gwy_surface_get_xrange(), * gwy_surface_get_yrange() and gwy_surface_get_min_max(), the fingerprint * for gwy_surface_xy_is_compatible() and and possibly other characteristics * in the future. * * See gwy_data_field_invalidate() for discussion of invalidation and examples. * * Since: 2.45 **/ void gwy_surface_invalidate(GwySurface *surface) { g_return_if_fail(GWY_IS_SURFACE(surface)); surface->priv->cached_ranges = FALSE; surface->priv->cached_checksum = FALSE; }
/** * gwy_surface_copy_units_to_data_field: * @surface: A surface. * @data_field: A two-dimensional data field. * * Sets lateral and value units of a data field to match a surface. * * Since: 2.46 **/ void gwy_surface_copy_units_to_data_field(GwySurface *surface, GwyDataField *data_field) { Surface *priv; g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(GWY_IS_DATA_FIELD(data_field)); priv = surface->priv; if (priv->si_unit_xy && data_field->si_unit_xy) gwy_serializable_clone(G_OBJECT(priv->si_unit_xy), G_OBJECT(data_field->si_unit_xy)); else if (priv->si_unit_xy && !data_field->si_unit_xy) data_field->si_unit_xy = gwy_si_unit_duplicate(priv->si_unit_xy); else if (!priv->si_unit_xy && data_field->si_unit_xy) GWY_OBJECT_UNREF(data_field->si_unit_xy); if (priv->si_unit_z && data_field->si_unit_z) gwy_serializable_clone(G_OBJECT(priv->si_unit_z), G_OBJECT(data_field->si_unit_z)); else if (priv->si_unit_z && !data_field->si_unit_z) data_field->si_unit_z = gwy_si_unit_duplicate(priv->si_unit_z); else if (!priv->si_unit_z && data_field->si_unit_z) GWY_OBJECT_UNREF(data_field->si_unit_z); }
/** * gwy_surface_get_data: * @surface: A surface. * * Gets the raw XYZ data array of a surface. * * The returned buffer is not guaranteed to be valid through whole data * surface life time. * * This function invalidates any cached information, use * gwy_surface_get_data_const() if you are not going to change the data. * * See gwy_surface_invalidate() for some discussion. * * Returns: The surface XYZ data as a pointer to an array of * gwy_surface_get_npoints() items. * * Since: 2.45 **/ GwyXYZ* gwy_surface_get_data(GwySurface *surface) { g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL); gwy_surface_invalidate(surface); return surface->data; }
/** * gwy_surface_get_data_full: * @surface: A surface. * @n: Location to store the count of extracted data points. * * Provides the values of an entire surface as a flat array. * * This function, paired with gwy_surface_set_data_full() can be namely useful * in language bindings. * * Note that this function returns a pointer directly to @surface's data. * * Returns: The array containing the surface points. * * Since: 2.45 **/ const GwyXYZ* gwy_surface_get_data_full(GwySurface *surface, guint *n) { g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL); *n = surface->n; return surface->data; }
/** * gwy_surface_set_from_data_field: * @surface: A surface. * @data_field: A two-dimensional data field. * * Fills the data of a surface from a data field. * * The number of points in the new surface will be equal to the number of * points in the field. Lateral coordinates will be equal to the corresponding * @data_field coordinates; values will be created in regular grid according to * @data_field's physical size and offset. * * Lateral and value units will correspond to @data_field's units. This means * the field needs to have identical @x and @y units. * * Since: 2.45 **/ void gwy_surface_set_from_data_field(GwySurface *surface, GwyDataField *dfield) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(GWY_IS_DATA_FIELD(dfield)); copy_field_to_surface(dfield, surface, NULL, GWY_MASK_IGNORE); }
static void surface_assert_equal(const GwySurface *result, const GwySurface *reference) { g_assert(GWY_IS_SURFACE(result)); g_assert(GWY_IS_SURFACE(reference)); g_assert_cmpuint(result->n, ==, reference->n); compare_properties(G_OBJECT(result), G_OBJECT(reference)); for (guint i = 0; i < result->n; i++) { GwyXYZ resxy = result->data[i]; GwyXYZ refxy = reference->data[i]; g_assert_cmpfloat(resxy.x, ==, refxy.x); g_assert_cmpfloat(resxy.y, ==, refxy.y); g_assert_cmpfloat(resxy.z, ==, refxy.z); } }
static void gwy_surface_clone_real(GObject *source, GObject *copy) { GwySurface *surface, *clone; g_return_if_fail(GWY_IS_SURFACE(source)); g_return_if_fail(GWY_IS_SURFACE(copy)); surface = GWY_SURFACE(source); clone = GWY_SURFACE(copy); if (clone->n != surface->n) { clone->n = surface->n; alloc_data(clone); } gwy_assign(clone->data, surface->data, surface->n); copy_info(clone, surface); }
/** * gwy_surface_xy_is_compatible: * @surface: A surface. * @othersurface: Another surface. * * Checks whether the XY positions of two surfaces are compatible. * * Compatible XY positions mean the XY units are the same and the points are * the same. Two surfaces that have the same set of XY points but in different * orders are <emphasis>not</emphasis> considered compatible. This is because * the points at the same index in @data are different and thus calculations * involving data from the two surfaces are impossible. It is necessary to * match the points order in the two surfaces to make this possible. * * This information is cached. * * Returns: %TRUE if the surfaces are XY-position compatible, %FALSE if they * are not. * * Since: 2.45 **/ gboolean gwy_surface_xy_is_compatible(GwySurface *surface, GwySurface *othersurface) { g_return_val_if_fail(GWY_IS_SURFACE(surface), FALSE); g_return_val_if_fail(GWY_IS_SURFACE(othersurface), FALSE); ensure_units(surface); ensure_units(othersurface); if (!gwy_si_unit_equal(surface->priv->si_unit_xy, othersurface->priv->si_unit_xy)) return FALSE; ensure_checksum(surface); ensure_checksum(othersurface); return !memcmp(surface->priv->checksum, othersurface->priv->checksum, sizeof(surface->priv->checksum)); }
/** * gwy_surface_set: * @surface: A surface. * @pos: Position in @surface. * @point: Point to store at given position. * * Sets a single surface value. * * This function exists <emphasis>only for language bindings</emphasis> as it * is very slow compared to simply accessing @data in #GwySurface directly in * C. * * Since: 2.45 **/ void gwy_surface_set(GwySurface *surface, guint pos, GwyXYZ point) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(pos < surface->n); surface->data[pos] = point; }
/** * gwy_surface_get_si_unit_z: * @surface: A surface. * * Returns value SI unit of a surface. * * Returns: SI unit corresponding to the "height" (Z) dimension of the surface. * Its reference count is not incremented. * * Since: 2.45 **/ GwySIUnit* gwy_surface_get_si_unit_z(GwySurface *surface) { g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL); if (!surface->priv->si_unit_z) surface->priv->si_unit_z = gwy_si_unit_new(NULL); return surface->priv->si_unit_z; }
/** * gwy_surface_get: * @surface: A surface. * @pos: Position in @surface. * * Obtains a single surface point. * * This function exists <emphasis>only for language bindings</emphasis> as it * is very slow compared to simply accessing @data in #GwySurface directly in * C. * * Returns: The point at @pos. * * Since: 2.45 **/ GwyXYZ gwy_surface_get(GwySurface *surface, guint pos) { GwyXYZ nullpoint = { 0.0, 0.0, 0.0 }; g_return_val_if_fail(GWY_IS_SURFACE(surface), nullpoint); g_return_val_if_fail(pos < surface->n, nullpoint); return surface->data[pos]; }
/** * gwy_surface_set_from_data_field_mask: * @surface: A surface. * @data_field: A two-dimensional data field. * @mask: Mask of pixels to include from/exclude, or %NULL * @masking: Masking mode to use. * * Fills the data of a surface from a data field, possibly using masking. * * Since: 2.46 **/ void gwy_surface_set_from_data_field_mask(GwySurface *surface, GwyDataField *dfield, GwyDataField *mask, GwyMaskingType masking) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(GWY_IS_DATA_FIELD(dfield)); g_return_if_fail(!mask || GWY_IS_DATA_FIELD(mask)); copy_field_to_surface(dfield, surface, mask, masking); }
/** * gwy_surface_get_min_max: * @surface: A surface. * @min: Location where to store the minimum value. * @max: Location where to store the maximum value. * * Gets the range of Z values of a surface. * * This information is cached. * * Since: 2.45 **/ void gwy_surface_get_min_max(GwySurface *surface, gdouble *min, gdouble *max) { g_return_if_fail(GWY_IS_SURFACE(surface)); ensure_ranges(surface); if (min) *min = surface->priv->min.z; if (max) *max = surface->priv->max.z; }
static GObject* gwy_surface_duplicate_real(GObject *object) { GwySurface *surface, *duplicate; g_return_val_if_fail(GWY_IS_SURFACE(object), NULL); surface = GWY_SURFACE(object); duplicate = gwy_surface_new_from_data(surface->data, surface->n); copy_info(duplicate, surface); return (GObject*)duplicate; }
/** * gwy_surface_new_alike: * @model: A surface to use as the template. * * Creates a new empty surface similar to another surface. * * The units of the new surface will be identical to those of @model but the * new surface will not contain any points. Use gwy_surface_duplicate() to * completely duplicate a surface including data. * * Returns: A new empty surface. * * Since: 2.45 **/ GwySurface* gwy_surface_new_alike(GwySurface *model) { GwySurface *surface; g_return_val_if_fail(GWY_IS_SURFACE(model), NULL); surface = g_object_newv(GWY_TYPE_SURFACE, 0, NULL); copy_info(surface, model); gwy_surface_invalidate(surface); return surface; }
/** * gwy_surface_set_si_unit_z: * @surface: A surface. * @si_unit: SI unit to be set. * * Sets the SI unit corresponding to the "height" (Z) dimension of a surface. * * It does not assume a reference on @si_unit, instead it adds its own * reference. * * Since: 2.45 **/ void gwy_surface_set_si_unit_z(GwySurface *surface, GwySIUnit *si_unit) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(GWY_IS_SI_UNIT(si_unit)); if (surface->priv->si_unit_z == si_unit) return; GWY_OBJECT_UNREF(surface->priv->si_unit_z); g_object_ref(si_unit); surface->priv->si_unit_z = si_unit; }
/** * gwy_surface_set_data_full: * @surface: A surface. * @points: Data points to copy to the surface. They replace whatever points * are in @surface now. * @n: The number of points in @data. * * Puts back values from a flat array to an entire data surface. * * See gwy_surface_get_data_full() for a discussion. * * Since: 2.45 **/ void gwy_surface_set_data_full(GwySurface *surface, const GwyXYZ *points, guint n) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(points || !n); if (surface->n != n) { surface->n = n; alloc_data(surface); } if (n) gwy_assign(surface->data, points, n); }
/** * gwy_surface_get_value_format_z: * @surface: A surface. * @style: Unit format style. * @format: A SI value format to modify, or %NULL to allocate a new one. * * Finds value format good for displaying values of a surface. * * Returns: The value format. If @format is %NULL, a newly allocated format * is returned, otherwise (modified) @format itself is returned. * * Since: 2.45 **/ GwySIValueFormat* gwy_surface_get_value_format_z(GwySurface *surface, GwySIUnitFormatStyle style, GwySIValueFormat *format) { GwySIUnit *siunit; gdouble max, min; g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL); siunit = gwy_surface_get_si_unit_z(surface); gwy_surface_get_min_max(surface, &min, &max); if (max == min) { max = ABS(max); min = 0.0; } return gwy_si_unit_get_format_with_digits(siunit, style, max - min, 3, format); }
static gsize gwy_surface_get_size(GObject *obj) { GwySurface *surface; guint32 datasize; g_return_val_if_fail(GWY_IS_SURFACE(obj), 0); surface = GWY_SURFACE(obj); ensure_units(surface); datasize = 3*surface->n; { GwySerializeSpec spec[] = { { 'o', "si_unit_xy", &surface->priv->si_unit_xy, NULL, }, { 'o', "si_unit_z", &surface->priv->si_unit_z, NULL, }, { 'D', "data", &surface->data, &datasize, }, }; return gwy_serialize_get_struct_size(GWY_SURFACE_TYPE_NAME, G_N_ELEMENTS(spec), spec); } }
/** * gwy_surface_get_value_format_xy: * @surface: A surface. * @style: Unit format style. * @format: A SI value format to modify, or %NULL to allocate a new one. * * Finds value format good for displaying coordinates of a surface. * * Returns: The value format. If @format is %NULL, a newly allocated format * is returned, otherwise (modified) @format itself is returned. * * Since: 2.45 **/ GwySIValueFormat* gwy_surface_get_value_format_xy(GwySurface *surface, GwySIUnitFormatStyle style, GwySIValueFormat *format) { gdouble xmin, xmax, ymin, ymax; gdouble max, unit; GwySIUnit *siunit; g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL); siunit = gwy_surface_get_si_unit_xy(surface); if (!surface->n) { return gwy_si_unit_get_format_with_resolution(siunit, style, 1.0, 0.1, format); } if (surface->n == 1) { max = MAX(fabs(surface->data[0].x), fabs(surface->data[0].y)); if (!max) max = 1.0; return gwy_si_unit_get_format_with_resolution(siunit, style, max, max/10.0, format); } gwy_surface_get_xrange(surface, &xmin, &xmax); gwy_surface_get_yrange(surface, &ymin, &ymax); max = MAX(MAX(fabs(xmax), fabs(xmin)), MAX(fabs(ymax), fabs(ymin))); if (!max) max = 1.0; unit = hypot(ymax - ymin, xmax - xmin)/sqrt(surface->n); if (!unit) unit = max/10.0; return gwy_si_unit_get_format_with_resolution(siunit, style, max, 0.2*unit, format); }
/** * gwy_surface_get_npoints: * @surface: A surface. * * Gets the number of points in an XYZ surface. * * Returns: The number of points. * * Since: 2.45 **/ guint gwy_surface_get_npoints(GwySurface *surface) { g_return_val_if_fail(GWY_IS_SURFACE(surface), 0); return surface->n; }
/** * gwy_surface_data_changed: * @surface: A surface. * * Emits signal GwySurface::data-changed on a surface. * * Since: 2.45 **/ void gwy_surface_data_changed(GwySurface *surface) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_signal_emit(surface, signals[DATA_CHANGED], 0); }
/** * gwy_surface_get_data_const: * @surface: A surface. * * Gets the raw XYZ data array of a surface, read-only. * * The returned buffer is not guaranteed to be valid through whole data * field life time. * * Use gwy_surface_get_data() if you want to change the data. * * See gwy_surface_invalidate() for some discussion. * * Returns: The surface XYZ data as a pointer to an array of * gwy_surface_get_npoints() items. * * Since: 2.45 **/ const GwyXYZ* gwy_surface_get_data_const(GwySurface *surface) { g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL); return surface->data; }