[GRASSLIST:6430] Re: Computing polygon area after/during v.overlay

Hamish hamish_nospam at yahoo.com
Tue Apr 12 08:15:56 EDT 2005

> > I would like to know the "coastline" lengths of some vector areas.
> > I'm trying to figure out a method to do this:
> > 
> > v.to.db -p option=length type=boundary
> > 
> > only works for lines (that is cat number -1 does report a length; if
> > type=boundary is not used then all real cats are listed with zero
> > length). I assume -1 length is sum of all boundaries? If so, I could
> > exploit the -1 length via v.extract in a loop for each cat, but that
> > seems like a bad solution.
> v.to.db works also for boundaries, but they must have a category
> (v.category type=boundary).

Yes, but how to assign the correct categories to them? (**see below**)
v.category just does step++, I want to use cat of touching area.

Note help page gives example with "v.to.db option=area" which doesn't 
seem to be possible.

> How do you want to report length for elements without category?

Ok, understood. Just like v.extract will only grab features with a cat.

This works for sum of all boundaries in a normal area vector map where
only centroid has a cat:

  # col= is needed with "-p"?

G6.1> v.to.db -p stew_sel op=length col=dummy

maybe v.extract for each AREA then above would work as a hack for what
I want to do (just report the perimeter length, not add to table).

> > so I use v.type to turn boundaries into lines, but as boundaries do
> > not have category numbers so result isn't worth much.
> > 
> > How do I assign the category of the area next to the boundary as the
> > boundary's cat value? (all areas are islands which do not touch, so
> > no left/right side issues) v.distance?
> v.to.db option=sides, where is a problem?

v.to.db was failing because my boundaries did not have cats, but back
to the central problem:

To make a report of the perimeters of all areas it takes the following,
which is not easy! (maybe a bit simpler with use of 'v.reclass rules=' ?)

# calc the coastline lengths of island groups
# (assume same fractal-depth; use for ratios only; yada, yada, yada)

# add categories to boundaries, starting with 1000 (something bigger
#  than number of existing cats for clarity).
v.category in=t_area out=t_area_lab_bdy type=boundary cat=1000 step=1

# export sides to a text file; keep only existing side
#  (areas do not touch so we can get away with this)
v.to.db t_area_lab_bdy -p op=sides col=l,r type=boundary | \
  sed -e 's/|-1//' | sed -e 1d > t_area_bdy.prn

# extract only boundaries
v.extract in=t_area_lab_bdy out=t_area_bdy type=boundary

# convert to lines (optional)
v.type in=t_area_bdy out=t_area_line type=boundary,line

# add new column to hold the original area's cat number
echo "ALTER TABLE $map ADD area_cat integer" | db.execute

# create SQL command file
cat t_area_bdy.prn | \
  awk -F'|' '{ printf("echo \"INSERT INTO $map (cat, area_cat) VALUES (%d, %d)\" | db.execute\n", $1, $2) }' \
    > t_area_bdy_exe

# run the SQL command file (populate with a series of db.execute commands)
. t_area_bdy_exe

# make a new vector using the area_cat column from 'v.to.db op=sides' as
#  the cat number
v.reclass in=t_area_line out=t_area_line2 column=area_cat

# copy original table to the new vector and connect it
db.copy from_table=t_area to_table=t_area_line2
v.db.connect map=t_area_line2 table=t_area_line2

# we now have a line vector file with the category numbers belonging to
#   the original touching area as the cat!

# calculate the perimeter length for each area into new cstln_mtr column
echo "ALTER TABLE t_area_line2 ADD cstln_mtr double" | db.execute
v.to.db t_area_line2 option=length col=cstln_mtr

#remove cruft
rm t_area_bdy.prn t_area_bdy_exe
g.remove v=t_area_bdy,t_area_lab_bdy,t_area_line

# print results
v.db.select t_area_line2 | sort -n

# output:
#1|island group 1|15829.356619
#2|island group 2|19672.841857
# success!

I'm sure you will now show me a way to do this in 1-2 commands.


More information about the grass-user mailing list