[GRASS-user] v.centroids and cat values

GRASS modules that create area type features should already be generating
centroids and adding categories to them automatically, shouldn't they?
As far as I am aware, e.g., v.in.ogr does this, so we are talking mainly
about adding centroid generation to the interactive digitizing tool, aren't we?
The GRASS Vector lib API should have a function that finds a good centroid automatically.
Or am I misled here (guess I am getting a bit confused myself, now)?

To be quite honest, I have always been a bit bewildered about the choice
of using a centroid point for linking attributes to area features.
Could anyone here fill me in on what advantage that has?

Cheers (and a good New Year, btw.),

Ben

Michael Barton wrote:

On Jan 6, 2009, at 10:00 AM, <grass-user-request@lists.osgeo.org> wrote:

Date: Tue, 06 Jan 2009 17:19:58 +0100
From: Moritz Lennert <mlennert@club.worldonline.be>
Subject: Re: [GRASS-user] v.centroids and cat values
To: Micha Silver <micha@arava.co.il>
Cc: GRASS user list <grass-user@lists.osgeo.org>
Message-ID: <496384AE.4000204@club.worldonline.be>
Content-Type: text/plain; charset=UTF-8; format=flowed

On 03/01/09 17:29, Micha Silver wrote:

I'd like to better understand the way cat values are assigned to
centroids when using v.centroids. I came across a problem when I created
a new vector and digitized boundaries (v.digit -n) . Before beginning
to digitize, I added some columns to the attribute table within v.digit,
so that on completing each feature, I could fill in the values for that
feature. I had one column for the label, and one column, GRASSRGB for
coloring. I did not bother to digitize centroids, but rather, after
completing the boundaries, and exiting v.digit, I ran v.centroids.

I was surprised to see that the cat value assigned to each centroid
*does not correspond* to the cat values of the surrounding boundary.
This has the unfortunate effect of showing incorrect labels when running
d.vect with the display=shape,attr option, since the attribute is taken
from centroid, and not from its surrounding boundary. In addition, when
coloring with the d.vect -a option, the boundaries get the correct color
from the GRASSRGB column, but the fill color is also wrong, since the
fill color is again taken from the attributes of the centroid. And the
centroid, with a different cat value, goes to the wrong row of the
attached attribute table. This behavior is certainly undesirable,
unless I'm missing something basic??

My workaround was to delete all centroids, then go back into v.digit,
and digitize each centroid, while being careful to choose it's cat value
manually, and set each one to the correct cat of the surrounding
boundary by choosing "Manual Entry" instead of "Next not used" mode for
categories.

So, is there some way to create centroids, such that they automatically
get the same cat value as the boundary?

Normally, the "best practice" is to digitize boundaries without category
values (unless you specifically want information concerning the
boundary, not the area it contains) and then digitize the centroids with
category values and relevant attribute data.

In your case, the easiest way out would seem to be v.distance, i.e.:

- v.centroid in=YourBoundaries out=YourMap
- v.db.addcol YourMap column="b_cat int"
- v.distance from=YourMap from_type=centroid to=YourMap to_type=boundary
upload=cat column=b_cat #this should find the nearest boundary for each
centroid
- v.category in=YourMap out=YourMap2 option=del type=boundary
- v.reclass in=YourMap2 out=YourMap3 type=centroid column=b_cat
- db.copy from_table=YourMap2 to_table=YourMap3
- db.dropcol YourMap3 col=b_cat
- Now you should have a YourMap3 with centroids that are linked to the
correct attributes. If this is the case, you can safely do the next step:
- g.remove vect=YourMap,YourMap2

This should be quite easy to make into a script module, or maybe extend
v.centroids to optionally do this for you.

I still think that when an area is created, a centroid should
automatically be placed at some standard and logical place for each
area. Area centroids should be an integral component of area topology,
not a separate point that must be manually placed and manipulated.

Michael
_______________________________________________
grass-user mailing list
grass-user@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/grass-user

--
Benjamin Ducke
Senior Applications Support and Development Officer

Oxford Archaeological Unit Limited
Janus House
Osney Mead
OX2 0ES
Oxford, U.K.

Tel.: ++44 (0)1865 263 800
benjamin.ducke@oxfordarch.co.uk

------
Files attached to this email may be in ISO 26300 format (OASIS Open Document Format). If you have difficulty opening them, please visit http://iso26300.info for more information.

Thanks for the suggestions. Some additional comments below:

Benjamin Ducke wrote:

GRASS modules that create area type features should already be generating
centroids and adding categories to them automatically, shouldn't they? As far as I am aware, e.g., v.in.ogr does this, so we are talking mainly about adding centroid generation to the interactive digitizing tool, aren't we?
The GRASS Vector lib API should have a function that finds a good centroid automatically.
Or am I misled here (guess I am getting a bit confused myself, now)?

As far as I know, v.in.ogr creates centroids automatically when you import a vector as type=boundary, and gives the centroids the same cat values as the boundaries.

To be quite honest, I have always been a bit bewildered about the choice
of using a centroid point for linking attributes to area features.
Could anyone here fill me in on what advantage that has?

Cheers (and a good New Year, btw.),

Ben

Michael Barton wrote:
  

Normally, the "best practice" is to digitize boundaries without category
values (unless you specifically want information concerning the
boundary, not the area it contains) and then digitize the centroids with
category values and relevant attribute data.

Yes, I understand that now.

In your case, the easiest way out would seem to be v.distance, i.e.:

- v.centroid in=YourBoundaries out=YourMap
- v.db.addcol YourMap column="b_cat int"
- v.distance from=YourMap from_type=centroid to=YourMap to_type=boundary
upload=cat column=b_cat #this should find the nearest boundary for each
centroid
- v.category in=YourMap out=YourMap2 option=del type=boundary
- v.reclass in=YourMap2 out=YourMap3 type=centroid column=b_cat
- db.copy from_table=YourMap2 to_table=YourMap3
- db.dropcol YourMap3 col=b_cat
- Now you should have a YourMap3 with centroids that are linked to the
correct attributes. If this is the case, you can safely do the next step:
- g.remove vect=YourMap,YourMap2

This should be quite easy to make into a script module, or maybe extend
v.centroids to optionally do this for you.
      

I follow what you're suggesting, but as a general solution it seems like quite a convoluted process to go thru just to get attribute values, which were already entered, to display correctely.

I still think that when an area is created, a centroid should automatically be placed at some standard and logical place for each area. Area centroids should be an integral component of area topology, not a separate point that must be manually placed and manipulated.

Michael
    

Michael: I think you brought this up in the past? This seems to me the most "natural" approach. So what would be needed is:
1- v.digit should automatically add a centroid in some reasonable place for each closed boundary, and give it the boundary's cat value.
2- v.centroid should also automatically assign cat values identical to the surrounding boundary's values.

Regards,
Micha