-
-
Notifications
You must be signed in to change notification settings - Fork 302
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v.fill.holes: Remove isles, keep outer boundary
- Loading branch information
1 parent
1961472
commit 6d97fed
Showing
4 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ SUBDIRS = \ | |
v.edit \ | ||
v.extract \ | ||
v.extrude \ | ||
v.fill.holes \ | ||
v.generalize \ | ||
v.hull \ | ||
v.info \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
MODULE_TOPDIR = ../.. | ||
|
||
PGM = v.fill.holes | ||
|
||
LIBES = $(VECTORLIB) $(DBMILIB) $(GISLIB) | ||
DEPENDENCIES = $(VECTORDEP) $(DBMIDEP) $(GISDEP) | ||
EXTRA_INC = $(VECT_INC) | ||
EXTRA_CFLAGS = $(VECT_CFLAGS) | ||
|
||
include $(MODULE_TOPDIR)/include/Make/Module.make | ||
|
||
default: cmd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
|
||
/**************************************************************** | ||
* | ||
* MODULE: v.fill.holes | ||
* | ||
* AUTHOR: Vaclav Petras | ||
* | ||
* PURPOSE: Fill holes in an area, i.e., preserve only its outer boundary | ||
* | ||
* COPYRIGHT: (C) 2022 by Vaclav Petras and the GRASS Development Team | ||
* | ||
* This program is free software under the GNU General | ||
* Public License (>=v2). Read the file COPYING that | ||
* comes with GRASS for details. | ||
* | ||
****************************************************************/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <grass/gis.h> | ||
#include <grass/vector.h> | ||
#include <grass/dbmi.h> | ||
#include <grass/glocale.h> | ||
|
||
struct VFillHolesParameters | ||
{ | ||
struct GModule *module; | ||
struct Option *input; | ||
struct Option *output; | ||
struct Option *field; | ||
struct Option *cats; | ||
struct Option *where; | ||
}; | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
struct Map_info input; | ||
struct Map_info output; | ||
int open3d; | ||
|
||
G_gisinit(argv[0]); | ||
|
||
struct VFillHolesParameters options; | ||
|
||
options.module = G_define_module(); | ||
G_add_keyword(_("vector")); | ||
G_add_keyword(_("geometry")); | ||
G_add_keyword(_("fill")); | ||
G_add_keyword(_("exterior")); | ||
G_add_keyword(_("ring")); | ||
G_add_keyword(_("perimeter")); | ||
options.module->description = | ||
_("Fill holes in areas by keeping only outer boundaries"); | ||
|
||
options.input = G_define_standard_option(G_OPT_V_INPUT); | ||
|
||
options.field = G_define_standard_option(G_OPT_V_FIELD); | ||
|
||
options.cats = G_define_standard_option(G_OPT_V_CATS); | ||
|
||
options.where = G_define_standard_option(G_OPT_DB_WHERE); | ||
|
||
options.output = G_define_standard_option(G_OPT_V_OUTPUT); | ||
|
||
if (G_parser(argc, argv)) | ||
exit(EXIT_FAILURE); | ||
|
||
Vect_check_input_output_name(options.input->answer, | ||
options.output->answer, G_FATAL_EXIT); | ||
Vect_set_open_level(2); | ||
|
||
if (1 > | ||
Vect_open_old2(&input, options.input->answer, "", | ||
options.field->answer)) | ||
G_fatal_error(_("Unable to open vector map <%s>"), | ||
options.input->answer); | ||
|
||
/* Check if old vector is 3D. We should preserve 3D data. */ | ||
if (Vect_is_3d(&input)) | ||
open3d = WITH_Z; | ||
else | ||
open3d = WITHOUT_Z; | ||
|
||
/* Set error handler for input vector map */ | ||
Vect_set_error_handler_io(&input, NULL); | ||
|
||
/* Open new vector for reading/writing */ | ||
if (0 > Vect_open_new(&output, options.output->answer, open3d)) { | ||
G_fatal_error(_("Unable to create vector map <%s>"), | ||
options.output->answer); | ||
} | ||
|
||
/* Set error handler for output vector map */ | ||
Vect_set_error_handler_io(NULL, &output); | ||
|
||
int field = Vect_get_field_number(&input, options.field->answer); | ||
|
||
if (field <= 0 && options.cats->answer) | ||
G_fatal_error(_("Option %s cannot be combined with %s=%s"), | ||
options.cats->key, options.field->key, | ||
options.field->answer); | ||
if (field <= 0 && options.where->answer) | ||
G_fatal_error(_("Option %s cannot be combined with %s=%s"), | ||
options.where->key, options.field->key, | ||
options.field->answer); | ||
|
||
/* Copy header and history data from old to new map */ | ||
Vect_copy_head_data(&input, &output); | ||
Vect_hist_copy(&input, &output); | ||
Vect_hist_command(&output); | ||
|
||
// Set category constraint. | ||
struct cat_list *constraint_cat_list = NULL; | ||
|
||
if (field > 0) | ||
constraint_cat_list = | ||
Vect_cats_set_constraint(&input, field, options.where->answer, | ||
options.cats->answer); | ||
|
||
/* Create and initialize struct's where to store points/lines and categories */ | ||
struct line_pnts *points = Vect_new_line_struct(); | ||
struct line_cats *area_cats = Vect_new_cats_struct(); | ||
struct line_cats *empty_cats = Vect_new_cats_struct(); | ||
|
||
struct ilist *all_cats = Vect_new_list(); | ||
struct ilist *field_cats = Vect_new_list(); | ||
|
||
plus_t num_areas = Vect_get_num_areas(&input); | ||
|
||
G_percent(0, num_areas, 1); | ||
for (plus_t area = 1; area <= num_areas; area++) { | ||
G_percent(area, num_areas, 1); | ||
|
||
int centroid = Vect_get_area_centroid(&input, area); | ||
|
||
if (!centroid) | ||
continue; | ||
|
||
Vect_read_line(&input, points, area_cats, centroid); | ||
|
||
if (constraint_cat_list && | ||
!Vect_cats_in_constraint(area_cats, field, constraint_cat_list)) { | ||
continue; | ||
} | ||
Vect_write_line(&output, GV_CENTROID, points, area_cats); | ||
|
||
Vect_get_area_points(&input, area, points); | ||
Vect_write_line(&output, GV_BOUNDARY, points, empty_cats); | ||
|
||
if (field > 0) { | ||
Vect_field_cat_get(area_cats, field, field_cats); | ||
Vect_list_append_list(all_cats, field_cats); | ||
} | ||
} | ||
|
||
Vect_destroy_cats_struct(empty_cats); | ||
Vect_destroy_cats_struct(area_cats); | ||
Vect_destroy_line_struct(points); | ||
|
||
/* Let's get vector layers db connections information */ | ||
struct field_info *input_info = NULL; | ||
|
||
if (field > 0 && all_cats->n_values) | ||
input_info = Vect_get_field2(&input, options.field->answer); | ||
|
||
if (input_info) { | ||
G_verbose_message(_("Copying attributes for layer <%s>"), | ||
options.field->answer); | ||
|
||
|
||
/* outputput information useful for debuging | ||
include/vect/dig_structs.h | ||
*/ | ||
G_debug(1, | ||
"Field number:%d; Name:<%s>; Driver:<%s>; Database:<%s>; Table:<%s>; Key:<%s>;\n", | ||
input_info->number, input_info->name, input_info->driver, | ||
input_info->database, input_info->table, input_info->key); | ||
|
||
struct field_info *output_info = | ||
Vect_default_field_info(&output, field, NULL, GV_1TABLE); | ||
/* Create database for new vector map */ | ||
dbDriver *driver = db_start_driver_open_database(output_info->driver, | ||
output_info-> | ||
database); | ||
|
||
G_debug(1, | ||
"Field number:%d; Name:<%s>; Driver:<%s>; Database:<%s>; Table:<%s>; Key:<%s>;\n", | ||
output_info->number, output_info->name, output_info->driver, | ||
output_info->database, output_info->table, output_info->key); | ||
|
||
/* | ||
Vect_map_add_dblink(&output, output_info->number, output_info->name, | ||
output_info->table, input_info->key, | ||
output_info->database, output_info->driver); | ||
*/ | ||
|
||
/* Copy attribute table data */ | ||
if (db_copy_table_by_ints | ||
(input_info->driver, input_info->database, input_info->table, | ||
output_info->driver, Vect_subst_var(output_info->database, | ||
&output), output_info->table, | ||
input_info->key, all_cats->value, | ||
all_cats->n_values) == DB_FAILED) | ||
G_fatal_error(_("Unable to copy attribute table to vector map <%s>"), | ||
options.output->answer); | ||
db_close_database_shutdown_driver(driver); | ||
} | ||
|
||
Vect_destroy_list(field_cats); | ||
Vect_destroy_list(all_cats); | ||
|
||
Vect_build(&output); | ||
|
||
Vect_set_release_support(&input); | ||
Vect_set_release_support(&output); | ||
|
||
Vect_close(&input); | ||
|
||
/* Build topology for vector map and close them */ | ||
|
||
Vect_close(&output); | ||
|
||
exit(EXIT_SUCCESS); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<h2>DESCRIPTION</h2> | ||
|
||
<em>v.fill.holes</em> | ||
|
||
<h2>EXAMPLE</h2> | ||
|
||
(North Carolina sample dataset): | ||
|
||
<div class="code"><pre> | ||
v.fill.holes input= output= | ||
</pre></div> | ||
|
||
<h2>SEE ALSO</h2> | ||
|
||
<em> | ||
<a href="v.clean.html">v.clean</a>, | ||
</em> | ||
|
||
<h2>AUTHOR</h2> | ||
|
||
Vaclav Petras |