[GRASS-SVN] r74206 - grass/trunk/vector/v.patch
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Mar 9 10:51:06 PST 2019
Author: mmetz
Date: 2019-03-09 10:51:06 -0800 (Sat, 09 Mar 2019)
New Revision: 74206
Modified:
grass/trunk/vector/v.patch/main.c
Log:
v.patch: +automagic cleaning of boundaries if areas have been patched
Modified: grass/trunk/vector/v.patch/main.c
===================================================================
--- grass/trunk/vector/v.patch/main.c 2019-03-09 18:43:05 UTC (rev 74205)
+++ grass/trunk/vector/v.patch/main.c 2019-03-09 18:51:06 UTC (rev 74206)
@@ -32,6 +32,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <math.h>
#include <grass/gis.h>
#include <grass/vector.h>
#include <grass/dbmi.h>
@@ -64,6 +65,7 @@
int maxcat = 0;
int out_is_3d = WITHOUT_Z;
char colnames[4096];
+ double snap = -1;
G_gisinit(argv[0]);
@@ -457,6 +459,108 @@
if (!no_topo->answer) {
if (append->answer)
Vect_build_partial(&OutMap, GV_BUILD_NONE);
+
+ Vect_build_partial(&OutMap, GV_BUILD_BASE);
+
+ if (Vect_get_num_primitives(&OutMap, GV_BOUNDARY) > 0) {
+ int nmodif;
+ struct bound_box box;
+ double xmax, ymax, min_snap, max_snap;
+ int exp;
+ char *separator = "-----------------------------------------------------";
+
+ Vect_get_map_box(&OutMap, &box);
+
+ if (abs(box.E) > abs(box.W))
+ xmax = abs(box.E);
+ else
+ xmax = abs(box.W);
+ if (abs(box.N) > abs(box.S))
+ ymax = abs(box.N);
+ else
+ ymax = abs(box.S);
+
+ if (xmax < ymax)
+ xmax = ymax;
+
+ /* double precision ULP */
+ min_snap = frexp(xmax, &exp);
+ exp -= 52;
+ min_snap = ldexp(min_snap, exp);
+ /* human readable */
+ min_snap = log10(min_snap);
+ if (min_snap < 0)
+ min_snap = (int)min_snap;
+ else
+ min_snap = (int)min_snap + 1;
+
+ /* single precision ULP */
+ max_snap = frexp(xmax, &exp);
+ exp -= 23;
+ max_snap = ldexp(max_snap, exp);
+ /* human readable */
+ max_snap = log10(max_snap);
+ if (max_snap < 0)
+ max_snap = (int)max_snap;
+ else
+ max_snap = (int)max_snap + 1;
+
+ snap = (min_snap + max_snap) / 2 - 1.5;
+ snap = pow(10, snap);
+
+ if (snap >= 0) {
+ G_message("%s", separator);
+ G_message(_("Snapping boundaries (threshold = %.3e)..."), snap);
+ Vect_snap_lines(&OutMap, GV_BOUNDARY, snap, NULL);
+ }
+
+ G_message("%s", separator);
+ G_message(_("Breaking polygons..."));
+ Vect_break_polygons(&OutMap, GV_BOUNDARY, NULL);
+
+ G_message("%s", separator);
+ G_message(_("Removing duplicates..."));
+ Vect_remove_duplicates(&OutMap, GV_BOUNDARY, NULL);
+
+ /* in non-pathological cases, the bulk of the cleaning is now done */
+
+ /* Vect_clean_small_angles_at_nodes() can change the geometry so that new intersections
+ * are created. We must call Vect_break_lines(), Vect_remove_duplicates()
+ * and Vect_clean_small_angles_at_nodes() until no more small angles are found */
+ do {
+ G_message("%s", separator);
+ G_message(_("Breaking boundaries..."));
+ Vect_break_lines(&OutMap, GV_BOUNDARY, NULL);
+
+ G_message("%s", separator);
+ G_message(_("Removing duplicates..."));
+ Vect_remove_duplicates(&OutMap, GV_BOUNDARY, NULL);
+
+ G_message("%s", separator);
+ G_message(_("Cleaning boundaries at nodes..."));
+ nmodif =
+ Vect_clean_small_angles_at_nodes(&OutMap, GV_BOUNDARY, NULL);
+ } while (nmodif > 0);
+
+ /* merge boundaries */
+ G_message("%s", separator);
+ G_message(_("Merging boundaries..."));
+ Vect_merge_lines(&OutMap, GV_BOUNDARY, NULL, NULL);
+
+ G_message("%s", separator);
+ G_message(_("Removing dangles..."));
+ Vect_remove_dangles(&OutMap, GV_BOUNDARY, -1.0, NULL);
+
+ G_message("%s", separator);
+ Vect_build_partial(&OutMap, GV_BUILD_ALL);
+
+ G_message(_("Removing bridges..."));
+ Vect_remove_bridges(&OutMap, NULL, &nmodif, NULL);
+
+ /* Boundaries are hopefully clean, build areas */
+ G_message("%s", separator);
+ Vect_build_partial(&OutMap, GV_BUILD_NONE);
+ }
Vect_build(&OutMap);
}
Vect_close(&OutMap);
More information about the grass-commit
mailing list