[GRASS-user] v.generalize and external boundaries

Hi List,

I'm using v.generalize in a script (excerpt included below) to smooth
the boundaries of a polygon vector dataset. In the attached example
(input_vector.png), I would like to *only* generalize the internal lines
(blue), and leave the external boundary (green line) unchanged. I
thought that the flag, '-l' might provide this functionality, but
unfortunately the resulting external boundary is changed significantly
(attached vgeneralize_output.png).

Is this functionality available in v.generalize or is there another way
that this could be achieved in GRASS?

Thanks in advance.

Best regards,
Daniel.

##run generalisation (step: 1 - douglas)
gscript.run_command('v.generalize', flags='l', overwrite=True,
input='segments', output='segments_douglas', method='douglas', threshold=1)

##run generalisation (step: 2 - sliding average)
gscript.run_command('v.generalize', flags='l', overwrite=True,
input='segments_douglas', output='segments_douglas_slide',
method='sliding_averaging', threshold='2', look_ahead='9', slide='0.1',
iterations='3')

##run generalisation (step: 3 - snake)
gscript.run_command('v.generalize', flags='l', overwrite=True,
input='segments_douglas_slide', output='segments_douglas_slide_snake',
method='snake', threshold='3', alpha='1', beta='1')

(attachments)

vgeneralize_output.png
input_vector.png

I think I have a series of steps that will allow you to separate the “inner” boundaries and generalize only those. The idea is based on using the v.to.db module, with the “sides” option to add the cat number of each area to the left and right of each boundary. Outer boundaries will have “-1” (nothing on that side) for the left or right sides. Then you can split out the inner boundaries with a v.extract using a “where” clause.

Somewhat convoluted, but here you are as regular grass command, not in python.

(My example below is from the sample nc_basic_spm_grass7 location. I tested with the geology map.)

# Make a copy and add cats to the boundaries in layer 2
GRASS 7.4.0 (nc_basic_spm_grass7):~ > g.copy vect=geology,my_geol
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.category my_geol layer=2 type=boundary option=add output=my_geol2

# Add attribute columns for the left and right sides in layer 2, and populate from the areas in *layer 1*
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.db.addtable my_geol2 layer=2 column="left integer,right integer"
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.to.db my_geol2 layer=2 option=sides column=left,right query_layer=1

# Now use the left and right cat value to separate the inner and outer boundaries
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.extract my_geol2 layer=2 out=inner_bndry type=boundary where="left<>-1 and right<>-1"
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.extract my_geol2 layer=2 out=outer_bndry type=boundary where="left=-1 or right=-1"

# Convert inner boundaries to lines for smoothing, and run generalize
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.type input=inner_bndry out=inner_lines layer=2 from=boundary to=line
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.generalize inner_lines method=douglas output=inner_lines_smooth thresh=1000 --o

# Convert back to boundary and merge back with the outer boundary`` and recreate area centroids
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.type inner_lines_smooth out=inner_bndry_smooth from=line to=boundary layer=2 --o
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.patch input=outer_bndry,inner_bndry_smooth output=merge_smooth --o
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.centroids merge_smooth output=merged_areas layer=2 option=add

``
You probably will have to do some manual cleaning of the result, since the smoothed inner boundaries might no longer exactly intersect with the untouched outer boundary due to overshoots, etc.

If you try this, let us know how it went.

Regards, Micha

···

On 08/24/2018 06:43 PM, Daniel McInerney wrote:

Hi List,

I'm using v.generalize in a script (excerpt included below) to smooth
the boundaries of a polygon vector dataset. In the attached example
(input_vector.png), I would like to *only* generalize the internal lines
(blue), and leave the external boundary (green line) unchanged. I
thought that the flag, '-l' might provide this functionality, but
unfortunately the resulting external boundary is changed significantly
(attached vgeneralize_output.png).

Is this functionality available in v.generalize or is there another way
that this could be achieved in GRASS?

Thanks in advance.

Best regards,
Daniel.

##run generalisation (step: 1 - douglas)
gscript.run_command('v.generalize', flags='l', overwrite=True,
input='segments', output='segments_douglas', method='douglas', threshold=1)

##run generalisation (step: 2 - sliding average)
gscript.run_command('v.generalize', flags='l', overwrite=True,
input='segments_douglas', output='segments_douglas_slide',
method='sliding_averaging', threshold='2', look_ahead='9', slide='0.1',
iterations='3')

##run generalisation (step: 3 - snake)
gscript.run_command('v.generalize', flags='l', overwrite=True,
input='segments_douglas_slide', output='segments_douglas_slide_snake',
method='snake', threshold='3', alpha='1', beta='1')
 
 

_______________________________________________
grass-user mailing list
[grass-user@lists.osgeo.org](mailto:grass-user@lists.osgeo.org)
[https://lists.osgeo.org/mailman/listinfo/grass-user](https://lists.osgeo.org/mailman/listinfo/grass-user)
-- 
Micha Silver
Ben Gurion Univ.
Sde Boker, Remote Sensing Lab
cell: +972-523-665918

On Sat, Aug 25, 2018 at 10:56 AM Micha Silver <tsvibar@gmail.com> wrote:

I think I have a series of steps that will allow you to separate the “inner” boundaries and generalize only those. The idea is based on using the v.to.db module, with the “sides” option to add the cat number of each area to the left and right of each boundary. Outer boundaries will have “-1” (nothing on that side) for the left or right sides. Then you can split out the inner boundaries with a v.extract using a “where” clause.

nice approach, but it could be simplified because v.generalize has a where option, i.e. no need for v.extract:

Somewhat convoluted, but here you are as regular grass command, not in python.

(My example below is from the sample nc_basic_spm_grass7 location. I tested with the geology map.)

Make a copy and add cats to the boundaries in layer 2

GRASS 7.4.0 (nc_basic_spm_grass7):~ > g.copy vect=geology,my_geol
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.category my_geol layer=2 type=boundary option=add output=my_geol2

Add attribute columns for the left and right sides in layer 2, and populate from the areas in layer 1

GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.db.addtable my_geol2 layer=2 column=“left integer,right integer”
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.to.db my_geol2 layer=2 option=sides column=left,right query_layer=1

generalize inner boundaries
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.generalize input=my_geol2 method=douglas output=my_geol2_smooth thresh=1000 type=boundary layer=2 where=“left > -1 and right > -1” --o

done

Markus M

Now use the left and right cat value to separate the inner and outer boundaries

GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.extract my_geol2 layer=2 out=inner_bndry type=boundary where=“left<>-1 and right<>-1”
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.extract my_geol2 layer=2 out=outer_bndry type=boundary where=“left=-1 or right=-1”

Convert inner boundaries to lines for smoothing, and run generalize

GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.type input=inner_bndry out=inner_lines layer=2 from=boundary to=line
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.generalize inner_lines method=douglas output=inner_lines_smooth thresh=1000 --o

Convert back to boundary and merge back with the outer boundary and recreate area centroids

GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.type inner_lines_smooth out=inner_bndry_smooth from=line to=boundary layer=2 --o
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.patch input=outer_bndry,inner_bndry_smooth output=merge_smooth --o
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.centroids merge_smooth output=merged_areas layer=2 option=add

You probably will have to do some manual cleaning of the result, since the smoothed inner boundaries might no longer exactly intersect with the untouched outer boundary due to overshoots, etc.

If you try this, let us know how it went.

Regards, Micha

On 08/24/2018 06:43 PM, Daniel McInerney wrote:

Hi List,

I’m using v.generalize in a script (excerpt included below) to smooth
the boundaries of a polygon vector dataset. In the attached example
(input_vector.png), I would like to only generalize the internal lines
(blue), and leave the external boundary (green line) unchanged. I
thought that the flag, ‘-l’ might provide this functionality, but
unfortunately the resulting external boundary is changed significantly
(attached vgeneralize_output.png).

Is this functionality available in v.generalize or is there another way
that this could be achieved in GRASS?

Thanks in advance.

Best regards,
Daniel.

##run generalisation (step: 1 - douglas)
gscript.run_command(‘v.generalize’, flags=‘l’, overwrite=True,
input=‘segments’, output=‘segments_douglas’, method=‘douglas’, threshold=1)

##run generalisation (step: 2 - sliding average)
gscript.run_command(‘v.generalize’, flags=‘l’, overwrite=True,
input=‘segments_douglas’, output=‘segments_douglas_slide’,
method=‘sliding_averaging’, threshold=‘2’, look_ahead=‘9’, slide=‘0.1’,
iterations=‘3’)

##run generalisation (step: 3 - snake)
gscript.run_command(‘v.generalize’, flags=‘l’, overwrite=True,
input=‘segments_douglas_slide’, output=‘segments_douglas_slide_snake’,
method=‘snake’, threshold=‘3’, alpha=‘1’, beta=‘1’)


grass-user mailing list
grass-user@lists.osgeo.org
https://lists.osgeo.org/mailman/listinfo/grass-user


Micha Silver
Ben Gurion Univ.
Sde Boker, Remote Sensing Lab
cell: +972-523-665918


grass-user mailing list
grass-user@lists.osgeo.org
https://lists.osgeo.org/mailman/listinfo/grass-user

Hi Markus, Micha,

Many thanks for your emails, the combined solution that you suggested
worked perfectly.

best regards,

Daniel.

On 25/08/18 11:03, Markus Metz wrote:

On Sat, Aug 25, 2018 at 10:56 AM Micha Silver <tsvibar@gmail.com
<mailto:tsvibar@gmail.com>> wrote:
>
> I think I have a series of steps that will allow you to separate the
"inner" boundaries and generalize only those. The idea is based on
using the v.to.db module, with the "sides" option to add the cat
number of each area to the left and right of each boundary. Outer
boundaries will have "-1" (nothing on that side) for the left or right
sides. Then you can split out the inner boundaries with a v.extract
using a "where" clause.

nice approach, but it could be simplified because v.generalize has a
where option, i.e. no need for v.extract:
>
> Somewhat convoluted, but here you are as regular grass command, not
in python.
>
> (My example below is from the sample nc_basic_spm_grass7 location. I
tested with the geology map.)
>
> # Make a copy and add cats to the boundaries in layer 2
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > g.copy vect=geology,my_geol
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.category my_geol layer=2
type=boundary option=add output=my_geol2
>
> # Add attribute columns for the left and right sides in layer 2, and
populate from the areas in *layer 1*
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.db.addtable my_geol2 layer=2
column="left integer,right integer"
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.to.db my_geol2 layer=2
option=sides column=left,right query_layer=1

generalize inner boundaries
GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.generalize input=my_geol2
method=douglas output=my_geol2_smooth thresh=1000 type=boundary
layer=2 where="left > -1 and right > -1" --o

done

Markus M

>
> # Now use the left and right cat value to separate the inner and
outer boundaries
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.extract my_geol2 layer=2
out=inner_bndry type=boundary where="left<>-1 and right<>-1"
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.extract my_geol2 layer=2
out=outer_bndry type=boundary where="left=-1 or right=-1"
>
> # Convert inner boundaries to lines for smoothing, and run generalize
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.type input=inner_bndry
out=inner_lines layer=2 from=boundary to=line
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.generalize inner_lines
method=douglas output=inner_lines_smooth thresh=1000 --o
>
> # Convert back to boundary and merge back with the outer boundary
and recreate area centroids
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.type inner_lines_smooth
out=inner_bndry_smooth from=line to=boundary layer=2 --o
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.patch
input=outer_bndry,inner_bndry_smooth output=merge_smooth --o
> GRASS 7.4.0 (nc_basic_spm_grass7):~ > v.centroids merge_smooth
output=merged_areas layer=2 option=add
>
>
> You probably will have to do some manual cleaning of the result,
since the smoothed inner boundaries might no longer exactly intersect
with the untouched outer boundary due to overshoots, etc.
>
> If you try this, let us know how it went.
>
> Regards, Micha
>
>
>
> On 08/24/2018 06:43 PM, Daniel McInerney wrote:
>
> Hi List,
>
> I'm using v.generalize in a script (excerpt included below) to smooth
> the boundaries of a polygon vector dataset. In the attached example
> (input_vector.png), I would like to *only* generalize the internal lines
> (blue), and leave the external boundary (green line) unchanged. I
> thought that the flag, '-l' might provide this functionality, but
> unfortunately the resulting external boundary is changed significantly
> (attached vgeneralize_output.png).
>
> Is this functionality available in v.generalize or is there another way
> that this could be achieved in GRASS?
>
> Thanks in advance.
>
> Best regards,
> Daniel.
>
> ##run generalisation (step: 1 - douglas)
> gscript.run_command('v.generalize', flags='l', overwrite=True,
> input='segments', output='segments_douglas', method='douglas',
threshold=1)
>
> ##run generalisation (step: 2 - sliding average)
> gscript.run_command('v.generalize', flags='l', overwrite=True,
> input='segments_douglas', output='segments_douglas_slide',
> method='sliding_averaging', threshold='2', look_ahead='9', slide='0.1',
> iterations='3')
>
> ##run generalisation (step: 3 - snake)
> gscript.run_command('v.generalize', flags='l', overwrite=True,
> input='segments_douglas_slide', output='segments_douglas_slide_snake',
> method='snake', threshold='3', alpha='1', beta='1')
>
>
>
>
>
> _______________________________________________
> grass-user mailing list
> grass-user@lists.osgeo.org <mailto:grass-user@lists.osgeo.org>
> https://lists.osgeo.org/mailman/listinfo/grass-user
>
>
> --
> Micha Silver
> Ben Gurion Univ.
> Sde Boker, Remote Sensing Lab
> cell: +972-523-665918
>
> _______________________________________________
> grass-user mailing list
> grass-user@lists.osgeo.org <mailto:grass-user@lists.osgeo.org>
> https://lists.osgeo.org/mailman/listinfo/grass-user