#include <sadie.h>
#include <math.h>
#include "junkmath.h"
#include "Sadie_Index.h"
#include "logerr.h"
#include "chain_provisional.h"
Classes | |
struct | Provisionalrings |
Measurements for rings affected by an added or removed boundary (2 at most). More... | |
struct | Boundbracket |
Used for interpolating new points between old points and boundaries. More... | |
struct | Roiframe |
Holds a summary of the region of interest coordinate frame. More... | |
Defines | |
#define | MAXIMUM_DISTANCE HUGE_VAL |
A constant larger than any measurable distance. | |
Typedefs | |
typedef Provisionalrings * | provisionalringsp_t |
Pointer to a container of messy easurement and boundary data. | |
typedef Boundbracket * | boundbracketp_t |
Pointer to the pairing of a point and a boundary. | |
typedef Roiframe * | roiframep_t |
Pointer to the summary of the ROI coordinate frame. | |
Functions | |
void | provisionalrings_destruct (void *data) |
Destroy a provisional measurement collection and all its sub-structures. | |
void | scale_boundary (BOUNDER *bound, double scale) |
Scale the coordinate representation of a boundary by a scalar multiplier. | |
LIST_NODE * | make_chain (BOUNDER *bound) |
Generate a chain-coded boundary from a coordinate boundary representation. | |
void | chain_extrapolate (IMAGE_BYTE *mimage, MOSAIC_INDEX *mindex, double scale, double x, double y, double orig_x, double orig_y, double orig_phi, LIST_NODE *guide, BOUNDBOX_LIST box, double *width, PROFILE_LIST *prof, LIST_NODE **extrapolated, LIST_NODE **small_extrapolated) |
Copy an existing chain-coded boundary, and measure the ring thus defined. | |
void | chain_collapse (IMAGE_BYTE *mimage, MOSAIC_INDEX *mindex, LIST_NODE *inner, LIST_NODE *outer, double *width, PROFILE_LIST *prof) |
Measure the new ring formed by deleting the common boundary of two rings. | |
int | provisional_point_in_roi (MOSAIC_INDEX *mindex, double x, double y) |
Test if coordinates fall within the region of interest in the image mosaic. | |
double | provisional_point_distance (double x, double y, LIST_NODE *boundary) |
Find the minimum distance between a point and a chain-coded boundary. | |
void | chain_interpolate (IMAGE_BYTE *mimage, MOSAIC_INDEX *mindex, double scale, double x, double y, LIST_NODE *inner, LIST_NODE *outer, BOUNDBOX_LIST box, double *w_before, PROFILE_LIST *prof_before, double *w_after, PROFILE_LIST *prof_after, LIST_NODE **interpolated, LIST_NODE **small_interpolated) |
Interpolate a new chain-coded ring boundary between two existing ones. | |
int | provisional_insert (char *doc, int provbnum, IMAGE_BYTE *mimage, MOSAIC_INDEX *mindex, double scale, double x, double y, LIST_NODE *inner, LIST_NODE *outer) |
Insert a new boundary in the chain map between two existing boundaries. | |
int | provisional_delete (char *doc, int provbnum, IMAGE_BYTE *mimage, MOSAIC_INDEX *mindex, LIST_NODE *inner, LIST_NODE *deleted, LIST_NODE *outer, LIST_NODE *small) |
Delete an existing chain-coded boundary. | |
int | provisional_missing (char *doc, int provbnum, IMAGE_BYTE *mimage, MOSAIC_INDEX *mindex, BOUNDBOX_LIST bbox, LIST_NODE *guide, LIST_NODE *small) |
Insert a missing ring after an existing chain-coded boundary. | |
int | provisional_extend (char *doc, int provbnum, IMAGE_BYTE *mimage, MOSAIC_INDEX *mindex, double scale, double x, double y, LIST_NODE *initial, LIST_NODE *final) |
Extend the list of chain-coded boundaries by a new boundary at the end. | |
int | provisional_check (double x, double y, LIST_NODE *inner, LIST_NODE *outer) |
Check if a point lies between two chain-coded boundaries. | |
int | have_provisional_changes (char *doc, char *pname) |
Test if there are valid modified data in the provisional measurements. | |
LIST_NODE * | get_provisional_full_chain (char *doc, char *pname) |
Recover the full-resolution chain-coded boundary from the hash table. | |
LIST_NODE * | get_provisional_small_chain (char *doc, char *pname) |
Recover the downsampled chain-coded boundary from the hash table. | |
int | get_provisional_insert_point (char *doc, char *pname) |
Recover the insertion point in the list of chain-coded boundaries. | |
int | find_provisional_widths (char *doc, char *pname, double **widthhandle) |
Find the array of provisional total ring widths in the hash table. | |
int | find_provisional_profiles (char *doc, char *pname, PROFILE_LIST **profhandle) |
Find the array of provisional brightness profiles in the hash table. | |
int | find_provisional_diff_profiles (char *doc, char *pname, PROFILE_LIST **diffprofhandle) |
Find the array of provisional differenced brightness profiles. | |
int | find_provisional_earlywidths (char *doc, char *pname, double **earlywidthhandle) |
Find the array of provisional earlywood widths in the hash table. | |
int | find_provisional_latewidths (char *doc, char *pname, double **latewidthhandle) |
Find the array of provisional latewood widths in the hash table. | |
int | find_provisional_boundbox (char *doc, char *pname, BOUNDBOX_LIST *boundboxhandle) |
Find the bounding box for the provisional ring. | |
Variables | |
sad_doclistp_t | global_doclist |
Hash table storing arbitrary data (including Provisionalrings structures). |
This provides several operations to support the operations that add or remove ring boundaries. They generate new boundaries by either interpolating between a pair of previously detected boundaries close to a specified position (e.g., a mouse click on an image), or by taking the long axis of the region of interest within which the other boundaries lie and placing a copy of one of these previously detected boundaries at a position along this axis close to the secified position. We use the Sadie_Index hash table implementation to store the measurements generated or modified by the boundary insertions and deletions, and provide a complete range of functions to retrieve these data while hiding the messy details of the implementation.
|
Measure the new ring formed by deleting the common boundary of two rings. Although we will generally use this to derive a new set of measurements for the single ring formed from two rings by the deletion of their common boundary, in principle it is just a general single-ring measurement function, analogous to a single iteration of the main loop in the CHAIN_RINGWIDTHS function.
|
|
Copy an existing chain-coded boundary, and measure the ring thus defined. Taking the region of interest within the image mosaic, the coordinates of the new boundary position, and an existing chain-coded boundary, we generate a new boundary as copy of the existing one, translated along the region of interest so that it falls near the specified coordinates. We transcribe the old chain-coded boundary to a representation that records the absolute coordinates of each point in continuous space (rather than the discrete relative steps of the chain code): a BOUNDER structure. The new boundary is initially also a BOUNDER structure, and all the ring measurements are derived from this pair of BOUNDER representations. We convert the new boundary to a chain-code representation (at two different resolutions), and simply discard the BOUNDER structures, which isn't very elegant.
|
|
Interpolate a new chain-coded ring boundary between two existing ones. Given two existing chain-coded boundaries and the coordinates of a point, we construct a new boundary by interpolation between the boundaries, taking the point coordinates as an approximate guide to its position. As normally used, the new boundary will split a previously measured ring in two, so there will be not just one set of modified ring measurements, but two. We transcribe the existing chain-coded boundaries to a representation that use the absolute coordinates of each point (BOUNDER structures); when first constructed, the new boundary uses the same representation, however the new boundary gets converted to a chain-coded representation (at two different resolutions), which along with the new measurements are the only data output from this function. The original BOUNDER representation of the interpolated boundary lacks the accurate information about local perpendicular directions needed for the width measurement, so we wastefully discard it after creating the chain-coded boundary, re-generate a new BOUNDER from the chain code, and use this for the measurements, before discarding it as well.
|
|
Find the bounding box for the provisional ring. Although this could be the head of a list of bounding boxes in a completely general case, here we're assuming it's the single box for one ring boundary.
|
|
Find the array of provisional differenced brightness profiles.
|
|
Find the array of provisional earlywood widths in the hash table.
|
|
Find the array of provisional latewood widths in the hash table.
|
|
Find the array of provisional brightness profiles in the hash table.
|
|
Find the array of provisional total ring widths in the hash table.
|
|
Recover the full-resolution chain-coded boundary from the hash table.
|
|
Recover the insertion point in the list of chain-coded boundaries. The id number for the list item immediately before the insertion point should have been saved in the hash table, and may be the invalid id code if the insertion point is at the head of the list.
|
|
Recover the downsampled chain-coded boundary from the hash table.
|
|
Test if there are valid modified data in the provisional measurements. Even if there are no valid profiles, there will always be a (possibly empty) profile structure if there are valid widths, so use its presence as the test.
|
|
Generate a chain-coded boundary from a coordinate boundary representation. A BOUNDER structure represents boundaries by lists of points with explicit coordinates in continuous space, whereas chain-coded boundaries use lists of discrete relative steps instead. Conversion may reduce the total number of points, as the coordinates of several points may fall within the same discrete interval.
|
|
Check if a point lies between two chain-coded boundaries. We treat the boundaries as edges of a polygon, which is closed by defining an extra edge between the first points of the boundary pair, and another edge between the last points of the pair. For full background see Haines, Eric, "Point in Polygon Strategies", Graphics Gems IV, ed. Paul Heckbert : Academic Press : 1994. p. 24--46. and equivalently: http://www.acm.org/tog/editors/erich/ptinpoly/
|
|
Delete an existing chain-coded boundary. Given a chain-coded boundary that is already in the chain map lists, and two enclosing boundaries (which are also already in the chain map, or are NULL), remove the boundary and re-compute the measurements to be associated with the enclosing boundaries (if they exist).
|
|
Extend the list of chain-coded boundaries by a new boundary at the end. Given the first and last chain-coded boundaries (which are already in the full-resolution chain map) and the coordinates of a point outside them, we construct a new boundary close to this point, derive revised measurements from the re-defined rings, and store them with the new boundaries in the hash table.
|
|
Insert a new boundary in the chain map between two existing boundaries. Given a pair of chain-coded boundaries (which are already in the full-resolution chain map) and the coordinates of a point between them, we construct a new boundary close to this point, derive revised measurements from the re-defined rings, and store them with the new boundaries in the hash table.
|
|
Insert a missing ring after an existing chain-coded boundary. Given a chain-coded boundary that is already in the chain map lists, and two enclosing boundaries (which are also already in the chain map, or are NULL), copy the boundary and create a set of measurements to be associated with it and the original boundary as a special zero-width ring (the marker following a convention in other dendrochronology software for a ring whose position is inferred, but not visible in the part of the tree-ring sample used to produce a particular series of measurements).
|
|
Find the minimum distance between a point and a chain-coded boundary. Although the individual line segments making up the chain-coded boundary can only have two lengths, and are joined at nodes that lie on a regular grid, the coordinates of the point are not necessarily constrained in any way, so we treat it as the more general case of finding the distance between a point and an arbitrary polyline in continuous coordinates.
|
|
Test if coordinates fall within the region of interest in the image mosaic. Transform the coordinates to a frame with its origin an upper corner of the ROI and its x axis along the longest edge, then compare them to the lengths of the edges of the ROI.
|
|
Destroy a provisional measurement collection and all its sub-structures.
|
|
Scale the coordinate representation of a boundary by a scalar multiplier. Multiply all the x and y coordinates in the boundary representation, and remove the (now inavalid) index to the points.
|