/* * Calls the (hopefully) desired interpolation/approximation routine. */ static void put_contour( cntr_struct *p_cntr, /* contour structure input */ double xx_min, double xx_max, double yy_min, double yy_max, /* minimum/maximum values input */ TBOOLEAN contr_isclosed) /* contour line closed? (input) */ { if (!p_cntr) return; /* Nothing to do if it is empty contour. */ switch (interp_kind) { case CONTOUR_KIND_LINEAR: /* No interpolation/approximation. */ put_contour_nothing(p_cntr); break; case CONTOUR_KIND_CUBIC_SPL: /* Cubic spline interpolation. */ put_contour_cubic(p_cntr, xx_min, xx_max, yy_min, yy_max, chk_contour_kind(p_cntr, contr_isclosed)); break; case CONTOUR_KIND_BSPLINE: /* Bspline approximation. */ put_contour_bspline(p_cntr, chk_contour_kind(p_cntr, contr_isclosed)); break; } free_contour(p_cntr); }
/************************************************************************* ************************************************************************** #cat: validate_ridge_crossing - Takes a pair of points, a ridge start #cat: transition and a ridge end transition, and walks the #cat: ridge contour from thre ridge end points a specified #cat: number of steps, looking for the ridge start point. #cat: If found, then transitions determined not to be a valid #cat: ridge crossing. Input: ridge_start - index into line trajectory of ridge start transition ridge_end - index into line trajectory of ridge end transition xlist - x-pixel coords of line trajectory ylist - y-pixel coords of line trajectory num - number of coords in line trajectory bdata - binary image data (0==while & 1==black) iw - width (in pixels) of image ih - height (in pixels) of image max_ridge_steps - number of steps taken in search in both scan directions Return Code: TRUE - ridge crossing VALID FALSE - ridge corssing INVALID Negative - system error **************************************************************************/ int validate_ridge_crossing(const int ridge_start, const int ridge_end, const int *xlist, const int *ylist, const int num, unsigned char *bdata, const int iw, const int ih, const int max_ridge_steps) { int ret; int feat_x, feat_y, edge_x, edge_y; int *contour_x, *contour_y, *contour_ex, *contour_ey, ncontour; /* Assign edge pixel pair for contour trace. */ feat_x = xlist[ridge_end]; feat_y = ylist[ridge_end]; edge_x = xlist[ridge_end-1]; edge_y = ylist[ridge_end-1]; /* Adjust pixel pair if they neighbor each other diagonally. */ fix_edge_pixel_pair(&feat_x, &feat_y, &edge_x, &edge_y, bdata, iw, ih); /* Trace ridge contour, starting at the ridge end transition, and */ /* taking a specified number of step scanning for edge neighbors */ /* clockwise. As we trace the ridge, we want to detect if we */ /* encounter the ridge start transition. NOTE: The ridge end */ /* position is on the white (of a black to white transition) and */ /* the ridge start is on the black (of a black to white trans), */ /* so the edge trace needs to look for the what pixel (not the */ /* black one) of the ridge start transition. */ ret = trace_contour(&contour_x, &contour_y, &contour_ex, &contour_ey, &ncontour, max_ridge_steps, xlist[ridge_start-1], ylist[ridge_start-1], feat_x, feat_y, edge_x, edge_y, SCAN_CLOCKWISE, bdata, iw, ih); /* If a system error occurred ... */ if(ret < 0) /* Return error code. */ return(ret); /* Otherwise, if the trace was not IGNORED, then a contour was */ /* was generated and returned. We aren't interested in the */ /* actual contour, so deallocate it. */ if(ret != IGNORE) free_contour(contour_x, contour_y, contour_ex, contour_ey); /* If the trace was IGNORED, then we had some sort of initialization */ /* problem, so treat this the same as if was actually located the */ /* ridge start point (in which case LOOP_FOUND is returned). */ /* So, If not IGNORED and ridge start not encounted in trace ... */ if((ret != IGNORE) && (ret != LOOP_FOUND)){ /* Now conduct contour trace scanning for edge neighbors counter- */ /* clockwise. */ ret = trace_contour(&contour_x, &contour_y, &contour_ex, &contour_ey, &ncontour, max_ridge_steps, xlist[ridge_start-1], ylist[ridge_start-1], feat_x, feat_y, edge_x, edge_y, SCAN_COUNTER_CLOCKWISE, bdata, iw, ih); /* If a system error occurred ... */ if(ret < 0) /* Return error code. */ return(ret); /* Otherwise, if the trace was not IGNORED, then a contour was */ /* was generated and returned. We aren't interested in the */ /* actual contour, so deallocate it. */ if(ret != IGNORE) free_contour(contour_x, contour_y, contour_ex, contour_ey); /* If trace not IGNORED and ridge start not encounted in 2nd trace ... */ if((ret != IGNORE) && (ret != LOOP_FOUND)){ /* If we get here, assume we have a ridge crossing. */ return(TRUE); } /* Otherwise, second trace returned IGNORE or ridge start found. */ } /* Otherwise, first trace returned IGNORE or ridge start found. */ /* If we get here, then we failed to validate a ridge crossing. */ return(FALSE); }
/* * Search the data base along a contour starts at the edge pe_start until * a boundary edge is detected or until we close the loop back to pe_start. * Returns a linked list of all the points on the contour * Also decreases num_active by the number of points on contour. */ static cntr_struct * trace_contour( edge_struct *pe_start, /* edge to start contour input */ double z_level, /* Z level of contour input */ int *num_active, /* number of active edges in/out */ TBOOLEAN contr_isclosed) /* open or closed contour line (input) */ { cntr_struct *p_cntr, *pc_tail; edge_struct *p_edge, *p_next_edge; poly_struct *p_poly, *PLastpoly = NULL; int i; p_edge = pe_start; /* first edge to start contour */ /* Generate the header of the contour - the point on pe_start. */ if (! contr_isclosed) { pe_start->is_active = FALSE; (*num_active)--; } if (p_edge->poly[0] || p_edge->poly[1]) { /* more than one point */ p_cntr = pc_tail = update_cntr_pt(pe_start, z_level); /* first point */ do { /* Find polygon to continue (Not where we came from - PLastpoly): */ if (p_edge->poly[0] == PLastpoly) p_poly = p_edge->poly[1]; else p_poly = p_edge->poly[0]; p_next_edge = NULL; /* In case of error, remains NULL. */ for (i = 0; i < 3; i++) /* Test the 3 edges of the polygon: */ if (p_poly->edge[i] != p_edge) if (p_poly->edge[i]->is_active) p_next_edge = p_poly->edge[i]; if (!p_next_edge) { /* Error exit */ pc_tail->next = NULL; free_contour(p_cntr); fprintf(stderr, "trace_contour: unexpected end of contour\n"); return NULL; } p_edge = p_next_edge; PLastpoly = p_poly; p_edge->is_active = FALSE; (*num_active)--; /* Do not allocate contour points on diagonal edges */ if (p_edge->position != DIAGONAL) { pc_tail->next = update_cntr_pt(p_edge, z_level); /* Remove nearby points */ if (fuzzy_equal(pc_tail, pc_tail->next)) { free(pc_tail->next); } else pc_tail = pc_tail->next; } } while ((p_edge != pe_start) && (p_edge->position != BOUNDARY)); pc_tail->next = NULL; /* For closed contour the first and last point should be equal */ if (pe_start == p_edge) { (p_cntr->X) = (pc_tail->X); (p_cntr->Y) = (pc_tail->Y); } } else { /* only one point, forget it */ p_cntr = NULL; } return p_cntr; }