Browse Source

v.buffer: implement -c -s flags also for GEOS
explain corners (caps) with screenshots
(merge https://trac.osgeo.org/grass/changeset/65710, https://trac.osgeo.org/grass/changeset/65712, https://trac.osgeo.org/grass/changeset/65715, https://trac.osgeo.org/grass/changeset/65759)


git-svn-id: https://svn.osgeo.org/grass/grass/branches/releasebranch_7_0@65957 15284696-431f-4ddb-bdfa-cd5b030d7da7

Martin Landa 9 years ago
parent
commit
ea3d418818

+ 20 - 5
vector/v.buffer/geos.c

@@ -142,12 +142,12 @@ int geos_buffer(struct Map_info *In, struct Map_info *Out,
 		struct spatial_index *si,
 		struct spatial_index *si,
 		struct line_cats *Cats,
 		struct line_cats *Cats,
 		struct buf_contours **arr_bc,
 		struct buf_contours **arr_bc,
-		int *buffers_count, int *arr_bc_alloc)
+		int *buffers_count, int *arr_bc_alloc, int flat, int no_caps)
 {
 {
     GEOSGeometry *IGeom = NULL;
     GEOSGeometry *IGeom = NULL;
     GEOSGeometry *OGeom = NULL;
     GEOSGeometry *OGeom = NULL;
     
     
-    G_debug(3, "geos_buffer()");
+    G_debug(3, "geos_buffer(): id=%d", id);
 
 
     if (type == GV_AREA)
     if (type == GV_AREA)
 	IGeom = Vect_read_area_geos(In, id);
 	IGeom = Vect_read_area_geos(In, id);
@@ -158,10 +158,25 @@ int geos_buffer(struct Map_info *In, struct Map_info *Out,
      * A value of 8 gives less than 2% max error in the buffer distance.
      * A value of 8 gives less than 2% max error in the buffer distance.
      * For a max error of < 1%, use QS = 12.
      * For a max error of < 1%, use QS = 12.
      * For a max error of < 0.1%, use QS = 18. */
      * For a max error of < 0.1%, use QS = 18. */
+#ifdef GEOS_3_3
+    if (flat || no_caps) {
+        GEOSBufferParams* geos_params = GEOSBufferParams_create();
+        GEOSBufferParams_setEndCapStyle(geos_params,
+                                        no_caps ? GEOSBUF_CAP_FLAT : GEOSBUF_CAP_SQUARE);
+
+        OGeom = GEOSBufferWithParams(IGeom, geos_params, da);
+        GEOSBufferParams_destroy(geos_params);
+    }
+    else {
+        OGeom = GEOSBuffer(IGeom, da, 12);
+    }
+#else
     OGeom = GEOSBuffer(IGeom, da, 12);
     OGeom = GEOSBuffer(IGeom, da, 12);
-
-    if (!OGeom)
-	G_warning(_("Buffering failed"));
+#endif
+    
+    if (!OGeom) {
+        G_fatal_error(_("Buffering failed (feature %d)"), id);
+    }
     
     
     geom2ring(OGeom, Out, Buf, si, Cats, arr_bc, buffers_count, arr_bc_alloc);
     geom2ring(OGeom, Out, Buf, si, Cats, arr_bc, buffers_count, arr_bc_alloc);
 
 

+ 4 - 1
vector/v.buffer/local_proto.h

@@ -1,3 +1,6 @@
+#if (GEOS_VERSION_MAJOR >= 3 && GEOS_VERSION_MINOR >= 3)
+#define GEOS_3_3
+#endif
 
 
 struct buf_contours
 struct buf_contours
 {
 {
@@ -19,6 +22,6 @@ int geos_buffer(struct Map_info *, struct Map_info *,
 		struct spatial_index *,
 		struct spatial_index *,
 		struct line_cats *,
 		struct line_cats *,
 		struct buf_contours **,
 		struct buf_contours **,
-		int *, int *);
+		int *, int *, int, int);
 #endif
 #endif
 
 

+ 10 - 2
vector/v.buffer/main.c

@@ -475,6 +475,12 @@ int main(int argc, char *argv[])
 
 
 #ifdef HAVE_GEOS
 #ifdef HAVE_GEOS
     initGEOS(G_message, G_fatal_error);
     initGEOS(G_message, G_fatal_error);
+
+    /* check required version for -s/-c flag */
+#ifndef GEOS_3_3
+        G_warning(_("Flags -%c/%c ignored by this version, GEOS >= 3.3 is required"),
+                  's', 'c');
+#endif
 #endif
 #endif
     if(!use_geos && (da < 0. || db < 0.)) {
     if(!use_geos && (da < 0. || db < 0.)) {
 	G_warning(_("Negative distances for internal buffers are not supported "
 	G_warning(_("Negative distances for internal buffers are not supported "
@@ -544,7 +550,8 @@ int main(int argc, char *argv[])
 #ifdef HAVE_GEOS
 #ifdef HAVE_GEOS
 	    if (use_geos)
 	    if (use_geos)
 		geos_buffer(&In, &Out, &Buf, area, GV_AREA, da,
 		geos_buffer(&In, &Out, &Buf, area, GV_AREA, da,
-			    &si, CCats, &arr_bc, &buffers_count, &arr_bc_alloc);
+			    &si, CCats, &arr_bc, &buffers_count, &arr_bc_alloc,
+                            straight_flag->answer, nocaps_flag->answer);
 #endif
 #endif
 	    if (!use_geos) {
 	    if (!use_geos) {
 		Vect_area_buffer2(&In, area, da, db, dalpha,
 		Vect_area_buffer2(&In, area, da, db, dalpha,
@@ -668,7 +675,8 @@ int main(int argc, char *argv[])
 #ifdef HAVE_GEOS
 #ifdef HAVE_GEOS
 		if (use_geos)
 		if (use_geos)
 		    geos_buffer(&In, &Out, &Buf, line, type, da,
 		    geos_buffer(&In, &Out, &Buf, line, type, da,
-				&si, CCats, &arr_bc, &buffers_count, &arr_bc_alloc);
+				&si, CCats, &arr_bc, &buffers_count, &arr_bc_alloc,
+                                straight_flag->answer, nocaps_flag->answer);
 #endif
 #endif
 		if (!use_geos) {
 		if (!use_geos) {
 		    Vect_line_buffer2(Points, da, db, dalpha,
 		    Vect_line_buffer2(Points, da, db, dalpha,

+ 41 - 5
vector/v.buffer/v.buffer.html

@@ -21,11 +21,47 @@ areas with category X (see example below).
 Buffers for lines and areas are generated using the algorithms from
 Buffers for lines and areas are generated using the algorithms from
 the GEOS library.
 the GEOS library.
 
 
-<!-- built-in buffer algorithm no longer desired, we use GEOS:
-If GRASS is not compiled with GEOS support or environmental
-variable <tt>GRASS_VECTOR_BUFFER</tt> is defined, then GRASS generates
-buffers using built-in buffering algorithm (which is still buggy for
-some input data).
+<p>
+<i>For advanced users:</i> built-in buffer algorithm no longer
+desired, we use GEOS: If GRASS is not compiled with GEOS support
+or <a href="variables.html">environmental
+variable</a> <tt>GRASS_VECTOR_BUFFER</tt> is defined, then GRASS
+generates buffers using built-in buffering algorithm (which is still
+buggy for some input data).
+
+<h3>Corner settings</h3>
+
+The following corners (also called "cap") exist:
+<ul>
+<li>no cap: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="v_buffer_no_cap.png" valign="middle" alt="line buffer: no cap"></li>
+<li>rounded cap: <img src="v_buffer_rounded_cap.png" valign="middle" alt="line buffer: rounded cap"></li>
+<li>square cap: <img src="v_buffer_square_cap.png" valign="middle" alt="line buffer: square cap"></li>
+</ul>
+
+By default <em>v.buffer</em> creates rounded buffers (blue color on
+figure below): 
+
+<center>
+  <img src="v_buffer_line.png">
+</center>
+
+Straight corners with caps are created by <b>-s</b> flag (red color on
+the figure below), while <b>-c</b> flag doesn't make caps at the ends of
+polylines (green color on the figure below):
+
+<center>
+  <img src="v_buffer_line_s.png">
+  <img src="v_buffer_line_c.png">
+</center>
+
+<!-- Only support by GRASS buffer 
+Flag <b>-s</b> also influences corners around polygons (see red color
+on the figure below):
+
+<center>
+  <img src="v_buffer_area.png">
+  <img src="v_buffer_area_s.png">
+</center>
 -->
 -->
 
 
 <h2>EXAMPLES</h2>
 <h2>EXAMPLES</h2>

BIN
vector/v.buffer/v_buffer_area.png


BIN
vector/v.buffer/v_buffer_area_s.png


BIN
vector/v.buffer/v_buffer_line.png


BIN
vector/v.buffer/v_buffer_line_c.png


BIN
vector/v.buffer/v_buffer_line_s.png


BIN
vector/v.buffer/v_buffer_no_cap.png


BIN
vector/v.buffer/v_buffer_rounded_cap.png


BIN
vector/v.buffer/v_buffer_square_cap.png