LOCAL int advance_front2d( double dt, double *dt_frac, Front *front, Front **newfront, POINTER wave) { CURVE *oldc,*tempc,*newc; CURVE **c; INTERFACE *tempintfc; NODE *oldn,*tempn,*newn; NODE_FLAG flag; RPROBLEM *rp; RPROBLEM *rp1; boolean scatter_normally_propagated_front = YES; boolean scatter_tangentially_propagated_front = YES; boolean stat; boolean do_redist; int status; long intfc_modified; long redo_advance_front; static const char *fname = "advance_front2d()"; int debug_flag = NO; debug_print("front","Entered %s(step %d time %g dt %g)\n",fname, front->step,front->time,dt); debug_front("old_front","into advance front",front); *newfront = copy_front(front); Interface_redistributed(*newfront) = NO; do_redist = (front->num_mts == 0) ? YES : NO; begin_advance_front2d: redo_advance_front = 0; tempintfc = NULL; rp = NULL; set_to_next_node_only(flag); set_node_doubly_linked_list(front->interf); /* Initialize Newfront */ start_clock("init_new_front"); capture_waves(front); print_storage("before init_new_front","ADV_storage"); /* TODO: Remove this option!!!!! */ if (front->init_topology_of_new_interface) status = (*front->init_topology_of_new_interface)(front,*newfront); else { set_size_of_intfc_state(size_of_state(front->interf)); set_copy_intfc_states(NO); set_add_to_correspond_list(YES); (*newfront)->interf = pp_copy_interface(front->interf); reset_hs_flags_on_intfc((*newfront)->interf); status = ((*newfront)->interf != NULL) ? GOOD_STEP : ERROR_IN_STEP; set_copy_intfc_states(YES); } if (front->pp_grid) status = syncronize_time_step_status(status,front->pp_grid); if (status != GOOD_STEP) { (void) printf("WARNING in advance_front2d(), " "unable to copy interface\n"); status = ERROR_IN_STEP; stop_clock("init_new_front"); return return_advance_front(front,newfront,status,fname); } print_storage("after init_new_front","ADV_storage"); stop_clock("init_new_front"); /* Set Default Propagation Limits */ set_propagation_limits(front,*newfront); /* Propagate the Curves */ if (front->intfc_propagate != NULL) { start_clock("intfc_propagate"); intfc_propagate(front,wave,front->interf,(*newfront)->interf,dt); debug_front("cp_front","after intfc prop",*newfront); stop_clock("curve_propagate"); } else if (front->curve_propagate != NULL) { start_clock("curve_propagate"); if (debugging("front")) (void) printf("Loop over Curves\n"); for (c = front->interf->curves; c && *c; ++c) { oldc = *c; if (((newc = correspond_curve(oldc)) != NULL) && (correspond_curve(newc) != NULL)) { if (debugging("propagate")) (void) printf("\t\tpropagating curve %llu\n", (long long unsigned int)curve_number(oldc)); curve_propagate(front,wave,oldc,newc,dt); /*f_curve_propagate2d */ } } debug_front("cp_front","after curve prop",*newfront); stop_clock("curve_propagate"); } /* Propagate the Nodes */ if (debugging("front")) { print_correspond_hyper_surf_list(front->interf); print_correspond_hyper_surf_list((*newfront)->interf); } if (front->node_propagate != NULL) { start_clock("node_propagate"); set_corresponds_for_node_prop(front->interf,(*newfront)->interf); oldn = first_node(front->interf); while (oldn != NULL) { newn = correspond_node(oldn); if (debugging("crx_status")) print_linked_node_list((*newfront)->interf); status = (newn != NULL) ? (*front->node_propagate)(front,wave,oldn,newn,&rp, dt,dt_frac,flag,NULL) : GOOD_NODE; if (debugging("crx_status")) if (is_bad_status(status) && (point_in_buffer(Coords(oldn->posn),front->rect_grid) == YES)) { print_node_status("WARNING in advance_front2d(), " "node_propagation returns ",status,"\n"); (void) printf("Problem occurs in buffer zone - ignoring\n"); if (set_node_states_and_continue(oldn,newn,front)) status = GOOD_NODE; } switch (status) { case GOOD_NODE: oldn = adv_node_loop_after_good_prop(oldn,newn,&rp); break; case PSEUDOCROSS_NODE_NODE: debug_print("PSEUDOCROSS","PSEUDOCROSS case\n"); oldn = reorder_node_loop(oldn,newn); break; case CROSS_NODE_NODE: case BIFURCATION_NODE: debug_print("CROSS","CROSS case\n"); oldn = next_node(oldn); break; case CROSS_PAST_CURVE_NODE: print_node_status("WARNING in advance_front2d(), " "node_propagate failed with status ", status,"\n"); print_node(oldn); if (debugging("CROSS_PAST")) { (void) printf("Cross past curve case\n" "dt_frac = %g\n",*dt_frac); (void) printf("Reducing time step\n"); } status = node_modify_time_step(oldn,front,dt_frac, MODIFY_TIME_STEP); free_rp_list(&rp); goto sync_prop_stat1; case MODIFY_TIME_STEP_NODE: (void) printf("WARNING in advance_front2d(), " "node_propagate returns " "MODIFY_TIME_STEP_NODE\n"); free_rp_list(&rp); status = node_modify_time_step(oldn,front,NULL, MODIFY_TIME_STEP); goto sync_prop_stat1; case REPEAT_TIME_STEP_NODE: (void) printf("WARNING in advance_front2d(), " "node_propagate returns " "REPEAT_TIME_STEP_NODE\n"); free_rp_list(&rp); status = node_modify_time_step(oldn,front,NULL, REPEAT_TIME_STEP); goto sync_prop_stat1; case NO_CROSS_NODE: print_node_status("WARNING in advance_front2d(), " "node_propagate failed with status ", status,"\n"); print_node(oldn); if (debugging("NO_CROSS")) { (void) printf("No cross case\n"); (void) printf("dt_frac = %g\n",*dt_frac); (void) printf("Reducing time step\n"); } free_rp_list(&rp); status = node_modify_time_step(oldn,front,dt_frac, MODIFY_TIME_STEP); goto sync_prop_stat1; case ERROR_NODE: default: print_node_status("WARNING in advance_front2d(), " "node_propagate failed with status ", status,"\n"); print_node(oldn); if (debugging("ERROR_NODE")) { (void) printf("Old interface:\n"); print_interface(front->interf); print_correspond_hyper_surf_list(front->interf); (void) printf("New interface:\n"); print_interface((*newfront)->interf); print_correspond_hyper_surf_list((*newfront)->interf); } status = node_modify_time_step(oldn,front,dt_frac, ERROR_IN_STEP); free_rp_list(&rp); goto sync_prop_stat1; } } /* end of while (oldn != NULL) */ set_correspond_hyper_surf_bdrys_to_NULL(front->interf); set_correspond_hyper_surf_bdrys_to_NULL((*newfront)->interf); if (rp && (front->twodrproblem != NULL)) { for (rp1 = rp; rp1; rp1 = rp1->prev) { debug_front("2drp_front", "new between node loop and rp loop",*newfront); status = (*front->twodrproblem)(front,*newfront,wave,&rp1); /* At this point, rp is nothing more than a valid element * of the list which provides a starting point * for deleting the list. If we delete an element of * the list in front->twodrproblem (presumably due to * merging two RPROBLEM's), then rp may point to freed * storage and will need to be updated. rp1 should still * be a valid element of the list. */ rp = rp1; if (status != GOOD_STEP) { print_time_step_status("WARNING in advance_front2d(), " "rp failed with status = ", status,"\n"); switch (status) { case GOOD_STEP: break; case REPEAT_TIME_STEP: break; case MODIFY_TIME_STEP: status = rp_modify_time_step(rp1,front,status); if (status == MODIFY_TIME_STEP) { *dt_frac = rp1->dt_frac; if (debugging("2drp")) { print_rproblem(rp1); (void) printf("dt_frac %g\n",*dt_frac); (void) printf("Reducing time step\n"); } *dt_frac = limit_dt_frac(*dt_frac,front); } break; case ERROR_IN_STEP: default: print_rproblem(rp1); /* Try reducing the time step */ status = rp_modify_time_step(rp1,front,status); if (status == MODIFY_TIME_STEP) *dt_frac *= TIME_STEP_REDUCTION_FACTOR(front->interf); break; } } if (status != GOOD_STEP) break; } free_rp_list(&rp); debug_front("2drp_front","after 2drp loop",*newfront); } else if (rp) { for (rp1 = rp; rp1; rp1 = rp1->prev) print_rproblem(rp1); free_rp_list(&rp); (void) printf("WARNING in advance_front2d(), " "CROSS code needed\n"); status = ERROR_IN_STEP; } sync_prop_stat1: stop_clock("node_propagate"); if (front->pp_grid) status = syncronize_time_step_status(status,front->pp_grid); if (status != GOOD_STEP) return return_advance_front(front,newfront,status,fname); } if (*front->max_scaled_propagation > 0.5) { (void) printf("WARNING in advance_front2d(), " "front->max_scaled_propagation = %f\n", *(front->max_scaled_propagation)); *dt_frac = 0.4/(*front->max_scaled_propagation); status = MODIFY_TIME_STEP; goto sync_prop_stat2; } stat = consistent_propagated_loop_orientations(dt,dt_frac,front,wave); if (stat == NO) { (void) printf("WARNING in advance_front2d(), " "Inconsistent orientation of propagated loop " "detected after point and node propagations"); if (pp_numnodes() > 1) (void) printf(" on processor %d\n",pp_mynode()); else (void) printf("\n"); } if (pp_min_status(stat) == NO) { if (stat == YES) { (void) printf("WARNING in advance_front2d(), " "Inconsistent orientation of propagated loop " "detected on a remote processor " "after point and node propagations "); } status = MODIFY_TIME_STEP; goto sync_prop_stat2; } /* Make Temp Interface for Tangential Propagation */ set_node_doubly_linked_list((*newfront)->interf); if (front->snd_node_propagate) { start_clock("snd_copy_interface"); print_storage("before snd_copy_interface","ADV_storage"); tempintfc = (*newfront)->interf; set_size_of_intfc_state(size_of_state(tempintfc)); set_add_to_correspond_list(YES); if (((*newfront)->interf = pp_copy_interface(tempintfc)) == NULL) { (void) printf("WARNING in advance_front2d(), " "unable to copy interface\n"); status = ERROR_IN_STEP; goto sync_prop_stat2; } copy_hypersurface_flags((*newfront)->interf); print_storage("after snd_copy_interface","ADV_storage"); stop_clock("snd_copy_interface"); } interpolate_intfc_states((*newfront)->interf) = YES; /* Second Propagation for the States Around the Nodes */ if (front->snd_node_propagate) { start_clock("snd_node_propagate"); if (debugging("front")) (void) printf("Second Loop over Nodes\n"); tempn = first_node(tempintfc); newn = first_node((*newfront)->interf); while (newn != NULL) { (*front->snd_node_propagate)(front,*newfront,wave, tempintfc,tempn,newn,dt); tempn = next_node(tempn); newn = next_node(newn); } debug_front("snd_front","after snd_node prop",*newfront); stop_clock("snd_node_propagate"); } if (tempintfc) (void) delete_interface(tempintfc); print_storage("after delete tempintfc","ADV_storage"); /* Redistribute the New Front */ switch (redistribute(*newfront,do_redist,NO)) { case GOOD_REDISTRIBUTION: status = GOOD_STEP; break; case UNABLE_TO_UNTANGLE: (void) printf("WARNING in advance_front2d(), " "redistribution of front failed\n" "Restarting advance_front2d()\n"); *dt_frac = Min_time_step_modification_factor(front); status = MODIFY_TIME_STEP; break; case MODIFY_TIME_STEP_REDISTRIBUTE: (void) printf("WARNING in advance_front2d(), " "redistribute returns\n" "\t\tMODIFY_TIME_STEP_REDISTRIBUTE, dt_frac = %g\n", *dt_frac); *dt_frac = Min_time_step_modification_factor(front); status = MODIFY_TIME_STEP; break; case BAD_REDISTRIBUTION: default: (void) printf("WARNING in advance_front2d(), " "redistribution of front failed\n"); debug_front("ERROR_front","after error",*newfront); *dt_frac = Min_time_step_modification_factor(front); status = MODIFY_TIME_STEP; break; } if (front->pp_grid) status = syncronize_time_step_status(status,front->pp_grid); if (status != GOOD_STEP) return return_advance_front(front,newfront,status,fname); Redistribution_count(front) = Redistribution_count(*newfront); (*newfront)->step = front->step + 1; (*newfront)->time = front->time + dt; debug_front("redist_front","after redistribution",*newfront); /* Communicate topologically propagated front */ if (scatter_normally_propagated_front == YES) { start_clock("scatter_front"); if (!scatter_front(*newfront)) { (void) printf("WARNING in advance_front2d(), " "scatter_front() failed for " "normally propagated front\n"); scatter_normally_propagated_front = NO; scatter_tangentially_propagated_front = NO; (void) delete_interface((*newfront)->interf); (*newfront)->interf = NULL; goto begin_advance_front2d; } stop_clock("scatter_front"); } debug_front("node_front","after node loop",*newfront); if (debugging("front")) { print_correspond_hyper_surf_list(front->interf); print_correspond_hyper_surf_list((*newfront)->interf); } if (front->mass_consv_diagn_driver) (*front->mass_consv_diagn_driver)(front,wave,dt); if (debugging("bond_lengths")) check_bond_lengths((*newfront)->interf); /* Check for the geometric orientation of loops */ /* ONLY check loops that will not be deleted !!!! */ delete_small_loops(*newfront); /* Delete non-boundary curves that lie */ /* fully on or exterior to the boundary */ delete_exterior_curves(*newfront,front->interf); intfc_delete_fold_back_bonds(*newfront); debug_front("dec_front","after delete_exterior_curves:",*newfront); interpolate_intfc_states((*newfront)->interf) = YES; /* Make Temp Interface for Tangential Propagation */ if (front->tan_curve_propagate) { start_clock("snd_copy_interface"); print_storage("before snd_copy_interface","ADV_storage"); tempintfc = (*newfront)->interf; set_size_of_intfc_state(size_of_state(tempintfc)); set_add_to_correspond_list(YES); if (((*newfront)->interf = pp_copy_interface(tempintfc)) == NULL) { (void) printf("WARNING in advance_front2d(), " "unable to copy interface\n"); status = ERROR_IN_STEP; goto sync_prop_stat2; } copy_hypersurface_flags((*newfront)->interf); interpolate_intfc_states((*newfront)->interf) = YES; print_storage("after snd_copy_interface","ADV_storage"); stop_clock("snd_copy_interface"); } /* Tangential Sweep for States on the Curves */ if (front->tan_curve_propagate) { start_clock("tan_curve_propagate"); if (debugging("front")) (void) printf("Second Loop over Curves\n"); for (c = tempintfc->curves; c && *c; ++c) { tempc = *c; newc = correspond_curve(tempc); (*front->tan_curve_propagate)(front,*newfront, tempintfc,tempc,newc,dt); } debug_front("tcp_front","after tan_curve_propagate:",*newfront); stop_clock("tan_curve_propagate"); } if (tempintfc) (void) delete_interface(tempintfc); print_storage("after delete tempintfc","ADV_storage"); /* Provide robustness for untangle algorithms */ /* delete remnants of scalar physical */ /* curves sticking to NEUMANN boundaries */ /* Add to delete_exterior_curves()? */ if (pp_min_status(delete_phys_remn_on_bdry(*newfront)) == NO) { (void) printf("WARNING in advance_front2d(), " "delete_phys_remn_on_bdry() detected error\n"); debug_front("ERROR_front","after error",*newfront); *dt_frac = Min_time_step_modification_factor(front); status = MODIFY_TIME_STEP; goto sync_prop_stat2; } debug_front("dspr_front", "after 1st delete_phys_remn_on_bdry():",*newfront); sync_prop_stat2: if (front->pp_grid) status = syncronize_time_step_status(status,front->pp_grid); if (status != GOOD_STEP) return return_advance_front(front,newfront,status,fname); /* Communicate tangentially propagated front */ if (scatter_tangentially_propagated_front == YES) { start_clock("scatter_front"); if (!scatter_front(*newfront)) { (void) printf("WARNING in advance_front2d(), " "scatter_front() failed for " "tangentially propagated front\n"); scatter_normally_propagated_front = NO; scatter_tangentially_propagated_front = NO; (void) delete_interface((*newfront)->interf); (*newfront)->interf = NULL; goto begin_advance_front2d; } stop_clock("scatter_front"); } if (status != GOOD_STEP) return return_advance_front(front,newfront,status,fname); /* Post-process newfront->interf */ /* Provide robustness after redistribution */ /* for node propagate on next time step */ /* Delete non-boundary curves that lie */ /* fully on or exterior to the boundary */ delete_exterior_curves(*newfront,front->interf); debug_front("dec_front","after delete_exterior_curves:",*newfront); /* delete remnants of scalar physical */ /* curves sticking to NEUMANN boundaries */ /* Add to delete_exterior_curves()? */ if (pp_min_status(delete_phys_remn_on_bdry(*newfront)) == NO) { (void) printf("WARNING in advance_front2d(), " "delete_phys_remn_on_bdry() detected error\n"); debug_front("ERROR_front","after error",*newfront); *dt_frac = Min_time_step_modification_factor(front); status = MODIFY_TIME_STEP; return return_advance_front(front,newfront,status,fname); } debug_front("dspr_front", "after 2nd delete_phys_remn_on_bdry():",*newfront); /* These guys keep sneaking through !! */ /* This should be the most effective place for this call */ /* Brent - I believe it is better to have the function at * the end of advance_front2d() applied to the newfront * instead of at the beginning applied to front. * In general our policy should be never to modify the * old interface data. */ delete_small_loops(*newfront); debug_front("dsloop_front","after delete_small_loops():",*newfront); test_for_mono_comp_curves((*newfront)->interf); /* Check if post processing has changed topology */ intfc_modified = (*newfront)->interf->modified; pp_global_lmax(&intfc_modified,1L); if (intfc_modified) { if (!scatter_front(*newfront)) { (void) printf("WARNING in advance_front2d(), " "final scatter_front() failed\n"); *dt_frac = Max_time_step_modification_factor(front); return return_advance_front(front,newfront, MODIFY_TIME_STEP,fname); } stat = make_bond_comp_lists((*newfront)->interf); if (pp_min_status(stat) == FUNCTION_FAILED) { screen("ERROR in advance_front2d(), " "make_bond_comp_lists() failed\n"); clean_up(ERROR); } } return return_advance_front(front,newfront,GOOD_STEP,fname); } /*end advance_front2d*/
int main(int argc, char *argv[]) { struct Map_info In, Out, Buf; struct line_pnts *Points; struct line_cats *Cats, *BCats; char bufname[GNAME_MAX]; struct GModule *module; struct Option *in_opt, *out_opt, *type_opt, *dista_opt, *distb_opt, *angle_opt; struct Flag *straight_flag, *nocaps_flag; struct Option *tol_opt, *bufcol_opt, *scale_opt, *field_opt; int verbose; double da, db, dalpha, tolerance, unit_tolerance; int type; int i, ret, nareas, area, nlines, line; char *Areas, *Lines; int field; struct buf_contours *arr_bc; struct buf_contours_pts arr_bc_pts; int buffers_count = 0, line_id; struct spatial_index si; struct bound_box bbox; /* Attributes if sizecol is used */ int nrec, ctype; struct field_info *Fi; dbDriver *Driver; dbCatValArray cvarr; double size_val, scale; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword(_("buffer")); module->description = _("Creates a buffer around vector features of given type."); in_opt = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL); field_opt->guisection = _("Selection"); type_opt = G_define_standard_option(G_OPT_V_TYPE); type_opt->options = "point,line,boundary,centroid,area"; type_opt->answer = "point,line,area"; type_opt->guisection = _("Selection"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); dista_opt = G_define_option(); dista_opt->key = "distance"; dista_opt->type = TYPE_DOUBLE; dista_opt->required = NO; dista_opt->description = _("Buffer distance along major axis in map units"); dista_opt->guisection = _("Distance"); distb_opt = G_define_option(); distb_opt->key = "minordistance"; distb_opt->type = TYPE_DOUBLE; distb_opt->required = NO; distb_opt->description = _("Buffer distance along minor axis in map units"); distb_opt->guisection = _("Distance"); angle_opt = G_define_option(); angle_opt->key = "angle"; angle_opt->type = TYPE_DOUBLE; angle_opt->required = NO; angle_opt->answer = "0"; angle_opt->description = _("Angle of major axis in degrees"); angle_opt->guisection = _("Distance"); bufcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); bufcol_opt->key = "bufcolumn"; bufcol_opt->description = _("Name of column to use for buffer distances"); bufcol_opt->guisection = _("Distance"); scale_opt = G_define_option(); scale_opt->key = "scale"; scale_opt->type = TYPE_DOUBLE; scale_opt->required = NO; scale_opt->answer = "1.0"; scale_opt->description = _("Scaling factor for attribute column values"); scale_opt->guisection = _("Distance"); tol_opt = G_define_option(); tol_opt->key = "tolerance"; tol_opt->type = TYPE_DOUBLE; tol_opt->required = NO; tol_opt->answer = "0.01"; tol_opt->description = _("Maximum distance between theoretical arc and polygon segments as multiple of buffer"); tol_opt->guisection = _("Distance"); straight_flag = G_define_flag(); straight_flag->key = 's'; straight_flag->description = _("Make outside corners straight"); nocaps_flag = G_define_flag(); nocaps_flag->key = 'c'; nocaps_flag->description = _("Don't make caps at the ends of polylines"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); type = Vect_option_to_types(type_opt); if ((dista_opt->answer && bufcol_opt->answer) || (!(dista_opt->answer || bufcol_opt->answer))) G_fatal_error(_("Select a buffer distance/minordistance/angle " "or column, but not both.")); if (bufcol_opt->answer) G_warning(_("The bufcol option may contain bugs during the cleaning " "step. If you encounter problems, use the debug " "option or clean manually with v.clean tool=break; " "v.category step=0; v.extract -d type=area")); if (field_opt->answer) field = Vect_get_field_number(&In, field_opt->answer); else field = -1; if (bufcol_opt->answer && field == -1) G_fatal_error(_("The bufcol option requires a valid layer.")); tolerance = atof(tol_opt->answer); if (tolerance <= 0) G_fatal_error(_("The tolerance must be > 0.")); if (adjust_tolerance(&tolerance)) G_warning(_("The tolerance was reset to %g"), tolerance); scale = atof(scale_opt->answer); if (scale <= 0.0) G_fatal_error("Illegal scale value"); da = db = dalpha = 0; if (dista_opt->answer) { da = atof(dista_opt->answer); if (distb_opt->answer) db = atof(distb_opt->answer); else db = da; if (angle_opt->answer) dalpha = atof(angle_opt->answer); else dalpha = 0; unit_tolerance = tolerance * MIN(da, db); G_verbose_message(_("The tolerance in map units = %g"), unit_tolerance); } Vect_check_input_output_name(in_opt->answer, out_opt->answer, GV_FATAL_EXIT); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); BCats = Vect_new_cats_struct(); Vect_set_open_level(2); /* topology required */ if (1 > Vect_open_old2(&In, in_opt->answer, "", field_opt->answer)) G_fatal_error(_("Unable to open vector map <%s>"), in_opt->answer); if (0 > Vect_open_new(&Out, out_opt->answer, WITHOUT_Z)) { Vect_close(&In); G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); } /* open tmp vector for buffers, needed for cleaning */ sprintf(bufname, "%s_tmp_%d", out_opt->answer, getpid()); if (0 > Vect_open_new(&Buf, bufname, 0)) { Vect_close(&In); Vect_close(&Out); Vect_delete(out_opt->answer); exit(EXIT_FAILURE); } Vect_build_partial(&Buf, GV_BUILD_BASE); /* check and load attribute column data */ if (bufcol_opt->answer) { db_CatValArray_init(&cvarr); Fi = Vect_get_field(&In, field); if (Fi == NULL) G_fatal_error(_("Database connection not defined for layer %d"), field); Driver = db_start_driver_open_database(Fi->driver, Fi->database); if (Driver == NULL) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); /* Note do not check if the column exists in the table because it may be expression */ /* TODO: only select values we need instead of all in column */ nrec = db_select_CatValArray(Driver, Fi->table, Fi->key, bufcol_opt->answer, NULL, &cvarr); if (nrec < 0) G_fatal_error(_("Unable to select data from table <%s>"), Fi->table); G_debug(2, "%d records selected from table", nrec); ctype = cvarr.ctype; if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("Column type not supported")); db_close_database_shutdown_driver(Driver); /* Output cats/values list */ for (i = 0; i < cvarr.n_values; i++) { if (ctype == DB_C_TYPE_INT) { G_debug(4, "cat = %d val = %d", cvarr.value[i].cat, cvarr.value[i].val.i); } else if (ctype == DB_C_TYPE_DOUBLE) { G_debug(4, "cat = %d val = %f", cvarr.value[i].cat, cvarr.value[i].val.d); } } } Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* Create buffers' boundaries */ nlines = nareas = 0; if ((type & GV_POINTS) || (type & GV_LINES)) nlines += Vect_get_num_primitives(&In, type); if (type & GV_AREA) nareas = Vect_get_num_areas(&In); if (nlines + nareas == 0) { G_warning(_("No features available for buffering. " "Check type option and features available in the input vector.")); exit(EXIT_SUCCESS); } buffers_count = 1; arr_bc = G_malloc((nlines + nareas + 1) * sizeof(struct buf_contours)); Vect_spatial_index_init(&si, 0); /* Lines (and Points) */ if ((type & GV_POINTS) || (type & GV_LINES)) { int ltype; if (nlines > 0) G_message(_("Buffering lines...")); for (line = 1; line <= nlines; line++) { int cat; G_debug(2, "line = %d", line); G_percent(line, nlines, 2); if (!Vect_line_alive(&In, line)) continue; ltype = Vect_read_line(&In, Points, Cats, line); if (!(ltype & type)) continue; if (field > 0 && !Vect_cat_get(Cats, field, &cat)) continue; if (bufcol_opt->answer) { ret = db_CatValArray_get_value_di(&cvarr, cat, &size_val); if (ret != DB_OK) { G_warning(_("No record for category %d in table <%s>"), cat, Fi->table); continue; } if (size_val < 0.0) { G_warning(_("Attribute is of invalid size (%.3f) for category %d"), size_val, cat); continue; } if (size_val == 0.0) continue; da = size_val * scale; db = da; dalpha = 0; unit_tolerance = tolerance * MIN(da, db); G_debug(2, " dynamic buffer size = %.2f", da); G_debug(2, _("The tolerance in map units: %g"), unit_tolerance); } Vect_line_prune(Points); if (ltype & GV_POINTS || Points->n_points == 1) { Vect_point_buffer2(Points->x[0], Points->y[0], da, db, dalpha, !(straight_flag->answer), unit_tolerance, &(arr_bc_pts.oPoints)); Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats); Vect_destroy_line_struct(arr_bc_pts.oPoints); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].outer = line_id; arr_bc[buffers_count].inner_count = 0; arr_bc[buffers_count].inner = NULL; buffers_count++; } else { Vect_line_buffer2(Points, da, db, dalpha, !(straight_flag->answer), !(nocaps_flag->answer), unit_tolerance, &(arr_bc_pts.oPoints), &(arr_bc_pts.iPoints), &(arr_bc_pts.inner_count)); Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats); Vect_destroy_line_struct(arr_bc_pts.oPoints); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].outer = line_id; arr_bc[buffers_count].inner_count = arr_bc_pts.inner_count; if (arr_bc_pts.inner_count > 0) { arr_bc[buffers_count].inner = G_malloc(arr_bc_pts.inner_count * sizeof(int)); for (i = 0; i < arr_bc_pts.inner_count; i++) { Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], Cats); Vect_destroy_line_struct(arr_bc_pts.iPoints[i]); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].inner[i] = line_id; } G_free(arr_bc_pts.iPoints); } buffers_count++; } } } /* Areas */ if (type & GV_AREA) { int centroid; if (nareas > 0) G_message(_("Buffering areas...")); for (area = 1; area <= nareas; area++) { int cat; G_percent(area, nareas, 2); if (!Vect_area_alive(&In, area)) continue; centroid = Vect_get_area_centroid(&In, area); if (centroid == 0) continue; Vect_read_line(&In, NULL, Cats, centroid); if (field > 0 && !Vect_cat_get(Cats, field, &cat)) continue; if (bufcol_opt->answer) { ret = db_CatValArray_get_value_di(&cvarr, cat, &size_val); if (ret != DB_OK) { G_warning(_("No record for category %d in table <%s>"), cat, Fi->table); continue; } if (size_val < 0.0) { G_warning(_("Attribute is of invalid size (%.3f) for category %d"), size_val, cat); continue; } if (size_val == 0.0) continue; da = size_val * scale; db = da; dalpha = 0; unit_tolerance = tolerance * MIN(da, db); G_debug(2, " dynamic buffer size = %.2f", da); G_debug(2, _("The tolerance in map units: %g"), unit_tolerance); } Vect_area_buffer2(&In, area, da, db, dalpha, !(straight_flag->answer), !(nocaps_flag->answer), unit_tolerance, &(arr_bc_pts.oPoints), &(arr_bc_pts.iPoints), &(arr_bc_pts.inner_count)); Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats); Vect_destroy_line_struct(arr_bc_pts.oPoints); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].outer = line_id; arr_bc[buffers_count].inner_count = arr_bc_pts.inner_count; if (arr_bc_pts.inner_count > 0) { arr_bc[buffers_count].inner = G_malloc(arr_bc_pts.inner_count * sizeof(int)); for (i = 0; i < arr_bc_pts.inner_count; i++) { Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats); line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], Cats); Vect_destroy_line_struct(arr_bc_pts.iPoints[i]); /* add buffer to spatial index */ Vect_get_line_box(&Buf, line_id, &bbox); Vect_spatial_index_add_item(&si, buffers_count, &bbox); arr_bc[buffers_count].inner[i] = line_id; } G_free(arr_bc_pts.iPoints); } buffers_count++; } } verbose = G_verbose(); G_message(_("Cleaning buffers...")); /* Break lines */ G_message(_("Building parts of topology...")); Vect_build_partial(&Out, GV_BUILD_BASE); G_message(_("Snapping boundaries...")); Vect_snap_lines(&Out, GV_BOUNDARY, 1e-7, NULL); G_message(_("Breaking polygons...")); Vect_break_polygons(&Out, GV_BOUNDARY, NULL); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL); do { G_message(_("Breaking boundaries...")); Vect_break_lines(&Out, GV_BOUNDARY, NULL); G_message(_("Removing duplicates...")); Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL); G_message(_("Cleaning boundaries at nodes")); } while (Vect_clean_small_angles_at_nodes(&Out, GV_BOUNDARY, NULL) > 0); /* Dangles and bridges don't seem to be necessary if snapping is small enough. */ /* Still needed for larger buffer distances ? */ /* G_message(_("Removing dangles...")); Vect_remove_dangles(&Out, GV_BOUNDARY, -1, NULL); G_message (_("Removing bridges...")); Vect_remove_bridges(&Out, NULL); */ G_message(_("Attaching islands...")); Vect_build_partial(&Out, GV_BUILD_ATTACH_ISLES); /* Calculate new centroids for all areas */ nareas = Vect_get_num_areas(&Out); Areas = (char *)G_calloc(nareas + 1, sizeof(char)); G_message(_("Calculating centroids for areas...")); G_percent(0, nareas, 2); for (area = 1; area <= nareas; area++) { double x, y; G_percent(area, nareas, 2); G_debug(3, "area = %d", area); if (!Vect_area_alive(&Out, area)) continue; ret = Vect_get_point_in_area(&Out, area, &x, &y); if (ret < 0) { G_warning(_("Cannot calculate area centroid")); continue; } ret = point_in_buffer(arr_bc, &si, &Buf, x, y); if (ret) { G_debug(3, " -> in buffer"); Areas[area] = 1; } } /* Make a list of boundaries to be deleted (both sides inside) */ nlines = Vect_get_num_lines(&Out); G_debug(3, "nlines = %d", nlines); Lines = (char *)G_calloc(nlines + 1, sizeof(char)); G_message(_("Generating list of boundaries to be deleted...")); for (line = 1; line <= nlines; line++) { int j, side[2], areas[2]; G_percent(line, nlines, 2); G_debug(3, "line = %d", line); if (!Vect_line_alive(&Out, line)) continue; Vect_get_line_areas(&Out, line, &side[0], &side[1]); for (j = 0; j < 2; j++) { if (side[j] == 0) { /* area/isle not build */ areas[j] = 0; } else if (side[j] > 0) { /* area */ areas[j] = side[j]; } else { /* < 0 -> island */ areas[j] = Vect_get_isle_area(&Out, abs(side[j])); } } G_debug(3, " areas = %d , %d -> Areas = %d, %d", areas[0], areas[1], Areas[areas[0]], Areas[areas[1]]); if (Areas[areas[0]] && Areas[areas[1]]) Lines[line] = 1; } G_free(Areas); /* Delete boundaries */ G_message(_("Deleting boundaries...")); for (line = 1; line <= nlines; line++) { G_percent(line, nlines, 2); if (!Vect_line_alive(&Out, line)) continue; if (Lines[line]) { G_debug(3, " delete line %d", line); Vect_delete_line(&Out, line); } else { /* delete incorrect boundaries */ int side[2]; Vect_get_line_areas(&Out, line, &side[0], &side[1]); if (!side[0] && !side[1]) Vect_delete_line(&Out, line); } } G_free(Lines); /* Create new centroids */ Vect_reset_cats(Cats); Vect_cat_set(Cats, 1, 1); nareas = Vect_get_num_areas(&Out); G_message(_("Calculating centroids for areas...")); for (area = 1; area <= nareas; area++) { double x, y; G_percent(area, nareas, 2); G_debug(3, "area = %d", area); if (!Vect_area_alive(&Out, area)) continue; ret = Vect_get_point_in_area(&Out, area, &x, &y); if (ret < 0) { G_warning(_("Cannot calculate area centroid")); continue; } ret = point_in_buffer(arr_bc, &si, &Buf, x, y); if (ret) { Vect_reset_line(Points); Vect_append_point(Points, x, y, 0.); Vect_write_line(&Out, GV_CENTROID, Points, Cats); } } /* free arr_bc[] */ /* will only slow down the module for (i = 0; i < buffers_count; i++) { Vect_destroy_line_struct(arr_bc[i].oPoints); for (j = 0; j < arr_bc[i].inner_count; j++) Vect_destroy_line_struct(arr_bc[i].iPoints[j]); G_free(arr_bc[i].iPoints); } */ Vect_spatial_index_destroy(&si); Vect_close(&Buf); Vect_delete(bufname); G_set_verbose(verbose); Vect_close(&In); Vect_build_partial(&Out, GV_BUILD_NONE); Vect_build(&Out); Vect_close(&Out); exit(EXIT_SUCCESS); }
EXPORT int normal_advance_front2d( float dt, float *dt_frac, Front *front, Front **newfront, POINTER wave) { CURVE *oldc,*newc; CURVE **c; NODE *oldn,*newn; RPROBLEM *rp,*rp1; int status, node_stat; NODE_FLAG flag; const char *fname = "normal_advance_front2d()"; debug_print("front","Entered %s(step %d time %g dt %g)\n",fname, front->step,front->time,dt); debug_front("old_front","into advance front",front); *newfront = copy_front(front); Interface_redistributed(*newfront) = NO; if(front->interf->nodes == NULL) { bool sav_copy; INTERFACE *sav_intfc; sav_intfc = current_interface(); sav_copy = copy_intfc_states(); set_size_of_intfc_state(size_of_state(front->interf)); set_copy_intfc_states(YES); (*newfront)->interf = copy_interface(front->interf); set_current_interface(sav_intfc); set_copy_intfc_states(sav_copy); return return_advance_front(front,newfront,GOOD_STEP,fname); } rp = NULL; set_to_next_node_only(flag); set_node_doubly_linked_list(front->interf); /* Initialize Newfront */ start_clock("init_new_front"); capture_waves(front); print_storage("before init_new_front","ADV_storage"); /* TODO: Remove this option!!!!! */ if (front->init_topology_of_new_interface) status = (*front->init_topology_of_new_interface)(front,*newfront); else { set_size_of_intfc_state(size_of_state(front->interf)); set_copy_intfc_states(NO); set_add_to_correspond_list(YES); /* If USE_OVERTURE, can not syncronize_time_step at here (*newfront)->interf = pp_copy_interface(front->interf); */ (*newfront)->interf = copy_interface(front->interf); reset_hs_flags_on_intfc((*newfront)->interf); status = ((*newfront)->interf != NULL) ? GOOD_STEP : ERROR_IN_STEP; set_copy_intfc_states(YES); } if (status != GOOD_STEP) { (void) printf("ERROR in normal_advance_front2d(), " "unable to copy interface\n"); print_storage("after init_new_front","ADV_storage"); clean_up(ERROR); } print_storage("after init_new_front","ADV_storage"); stop_clock("init_new_front"); /* Set Default Propagation Limits */ set_propagation_limits(front,*newfront); /* Propagate the Curves */ if (front->curve_propagate != NULL) { start_clock("curve_propagate"); if (debugging("front")) (void) printf("Loop over Curves\n"); for (c = front->interf->curves; c && *c; c++) { oldc = *c; if (((newc = correspond_curve(oldc)) != NULL) && (correspond_curve(newc) != NULL)) { if (debugging("propagate")) (void) printf("\t\tpropagating curve %lu\n", curve_number(oldc)); curve_propagate(front,wave,oldc,newc,dt); } } debug_front("cp_front","after curve prop",*newfront); stop_clock("curve_propagate"); } /* Propagate the Nodes */ if (debugging("front")) { print_correspond_hyper_surf_list(front->interf); print_correspond_hyper_surf_list((*newfront)->interf); } if (front->node_propagate != NULL) { start_clock("node_propagate"); set_corresponds_for_node_prop(front->interf,(*newfront)->interf); oldn = first_node(front->interf); while (oldn != NULL) { newn = correspond_node(oldn); if (debugging("crx_status")) print_linked_node_list((*newfront)->interf); if(DEBUG) { /* printf("IN normal_advance_front2d\n"); printf("node propagate\n"); print_node(oldn); print_node(newn); printf("oldnode is virtual fixed = %s\n", is_virtual_fixed_node(oldn) == YES ? "YES" : "NO"); printf("newnode is virtual fixed = %s\n", is_virtual_fixed_node(newn) == YES ? "YES" : "NO"); printf("End of print new and old nodes\n"); */ } status = (newn != NULL) ? (*front->node_propagate)(front,wave,oldn,newn,&rp, dt,dt_frac,flag,NULL) : GOOD_NODE; if (is_bad_status(status) && (point_in_buffer(Coords(oldn->posn),front->rect_grid) == YES)) { (void) printf("WARNING in normal_advance_front2d(), " "node_propagation returns "); print_node_status("WARNING in normal_advance_front2d(), " "node_propagation returns ",status,"\n"); /* print_node_status(status); */ (void) printf("Problem occurs in buffer zone - ignoring\n"); if (set_node_states_and_continue(oldn,newn,front)) status = GOOD_NODE; } switch (status) { case GOOD_NODE: oldn = adv_node_loop_after_good_prop(oldn,newn,&rp); break; case PSEUDOCROSS_NODE_NODE: debug_print("PSEUDOCROSS","PSEUDOCROSS case\n"); oldn = reorder_node_loop(oldn,newn); break; case CROSS_NODE_NODE: case BIFURCATION_NODE: debug_print("CROSS","CROSS case\n"); oldn = next_node(oldn); break; case CROSS_PAST_CURVE_NODE: (void) printf("WARNING in normal_advance_front2d(), "); (void) printf("node_propagate failed, "); print_node_status("WARNING in normal_advance_front2d(), " "node_propagate failed with status ", status,"\n"); print_node(oldn); if (debugging("CROSS_PAST")) { (void) printf("Cross past curve case\n" "dt_frac = %g\n",*dt_frac); (void) printf("Reducing time step\n"); } *dt_frac *= TIME_STEP_REDUCTION_FACTOR(front->interf); free_rp_list(&rp); status = MODIFY_TIME_STEP; goto sync_prop_stat1; case MODIFY_TIME_STEP_NODE: (void) printf("WARNING in normal_advance_front2d(), " "node_propagate returns " "MODIFY_TIME_STEP_NODE\n"); free_rp_list(&rp); status = MODIFY_TIME_STEP; goto sync_prop_stat1; case REPEAT_TIME_STEP_NODE: (void) printf("WARNING in normal_advance_front2d(), " "node_propagate returns " "REPEAT_TIME_STEP_NODE\n"); free_rp_list(&rp); status = REPEAT_TIME_STEP; goto sync_prop_stat1; case NO_CROSS_NODE: (void) printf("WARNING in normal_advance_front2d(), "); (void) printf("node_propagate failed, "); print_node_status("WARNING in normal_advance_front2d(), " "node_propagate failed with status ", status,"\n"); print_node(oldn); if (debugging("NO_CROSS")) { (void) printf("No cross case\n"); (void) printf("dt_frac = %g\n",*dt_frac); (void) printf("Reducing time step\n"); } *dt_frac *= TIME_STEP_REDUCTION_FACTOR(front->interf); free_rp_list(&rp); status = MODIFY_TIME_STEP; goto sync_prop_stat1; case ERROR_NODE: default: (void) printf("WARNING in normal_advance_front2d(), "); (void) printf("node_propagate failed, "); print_node_status("WARNING in normal_advance_front2d(), " "node_propagate failed with status ", status,"\n"); print_node(oldn); if (debugging("ERROR_NODE")) { (void) printf("Old interface:\n"); print_interface(front->interf); print_correspond_hyper_surf_list(front->interf); (void) printf("New interface:\n"); print_interface((*newfront)->interf); print_correspond_hyper_surf_list((*newfront)->interf); } *dt_frac = Min_time_step_modification_factor(front); free_rp_list(&rp); status = MODIFY_TIME_STEP; goto sync_prop_stat1; } } /* end of while (oldn != NULL) */ set_correspond_hyper_surf_bdrys_to_NULL(front->interf); set_correspond_hyper_surf_bdrys_to_NULL((*newfront)->interf); if (rp && (front->twodrproblem != NULL)) { for (rp1 = rp; rp1; rp1 = rp1->prev) { debug_front("2drp_front", "new between node loop and rp loop",*newfront); status = (*front->twodrproblem)(front,*newfront,wave,&rp1); /* At this point, rp is nothing more than a valid element * of the list which provides a starting point * for deleting the list. If we delete an element of * the list in front->twodrproblem (presumably due to * merging two RPROBLEM's), then rp may point to freed * storage and will need to be updated. rp1 should still * be a valid element of the list. */ rp = rp1; if (status != GOOD_STEP) { print_time_step_status("WARNING in advance_front2d(), " "rp failed with status = ", status,"\n"); switch (status) { case GOOD_STEP: break; case REPEAT_TIME_STEP: break; case MODIFY_TIME_STEP: status = rp_modify_time_step(rp1,front,status); if (status == MODIFY_TIME_STEP) { *dt_frac = rp1->dt_frac; if (debugging("2drp")) { print_rproblem(rp1); (void) printf("dt_frac %g\n",*dt_frac); (void) printf("Reducing time step\n"); } *dt_frac = limit_dt_frac(*dt_frac,front); } break; case ERROR_IN_STEP: default: print_rproblem(rp1); /* Try reducing the time step */ status = rp_modify_time_step(rp1,front,status); if (status == MODIFY_TIME_STEP) *dt_frac *= TIME_STEP_REDUCTION_FACTOR(front->interf); break; } } if (status != GOOD_STEP) break; } free_rp_list(&rp); debug_front("2drp_front","after 2drp loop",*newfront); } else if (rp) { for (rp1 = rp; rp1; rp1 = rp1->prev) { print_rproblem(rp1); } free_rp_list(&rp); (void) printf("WARNING in normal_advance_front2d(), "); (void) printf("CROSS code needed\n"); status = ERROR_IN_STEP; } } /* 061003 closed, since the correspondence is reset. * The second node prop. is done in tangential step now. node_stat = second_node_propagate2d(dt,dt_frac,front,newfront,wave); if(GOOD_STEP != node_stat) { (void) printf("WARNING in normal_advance_front2d(), " "second node_propagation returns stat= %d", node_stat); clean_up(ERROR); } */ sync_prop_stat1: return return_advance_front(front,newfront,GOOD_STEP,fname); } /*end normal_advance_front2d*/