GRASS Vector Layers: Difference between revisions

From GRASS-Wiki
Jump to navigation Jump to search
 
(45 intermediate revisions by 3 users not shown)
Line 2: Line 2:


Grass documentation provides basic information about vector attribute management,
Grass documentation provides basic information about vector attribute management,
categories of vector features and vector layers, see
categories of vector features and vector layers.
<ref>Vector data processing in GRASS GIS</ref>.
<ref>http://grass.osgeo.org/grass64/manuals/html64_user/vectorintro.html</ref>


The aim of this tutorial is to show how to create, manipulate and
The aim of this tutorial is to show how to create, manipulate and
display different layers of a vector using relational database.
display different layers of a vector map using relational database.


== Problem Description ==
== Problem Description ==
Line 12: Line 12:
by drivers. The organization's database consists of
by drivers. The organization's database consists of
* roads (road network)
* roads (road network)
* routes driven on that roads
* routes driven on these roads


Simple approach can be taken to present the routes to drivers.  
Simple approach can be taken to present the routes to drivers.  
For every route a vector map could be created and overlayed over
For every route a vector map could be created and overlayed over
the road network vector, i.e.
the road network vector map, i.e.


     $ d.vect map=roads
     $ d.vect map=roads
     $ d.vect map=route01 color=green width=2
     $ d.vect map=route01 color=green width=2


Above idea has a major flaw. If route data changes or new route is added
Above idea has a major flaw. If route data change or new route is added
then vector maps has to be regenerated or removed.
then vector maps has to be regenerated or removed.


Line 31: Line 31:
     $ d.vect map=roads layer=2 where="route_id=1" color=green width=2
     $ d.vect map=roads layer=2 where="route_id=1" color=green width=2


The tutorial reuses road network provided with Spearfish data. To solve
== Datamodel Discussion ==
problem defined above, the roads data and sample routes needs to be prepared.
This is described in next section.
 
== Road Network and Routes Data ==
 
=== Database Tables ===
Relation database should contain two tables
Relation database should contain two tables
* road network table
* road network table
* driven routes table
* driven routes table


Road network table has to contain at least two columns
Road network table has to have at least two columns
* road segment id usually provided with road network data by vendor
* road segment id usually provided with road network data by vendor
* vectory category required by Grass to identify vector features
* vectory category required by Grass to identify vector features


Road network table can be defined like
Routes table shall consist of
    create table road_network (
* route identifier
        cat integer,
* id of road segment driven on a route, which references road segment id in road network table
        id integer  -- road segment id
    );
 
Routes table contains route identifier and id of road segment driven
on a route
    create table route (
        route_id integer,
        rn_id integer    -- references road_network.id
    );


Routes table also has to provide vector category information. This can be
Routes table also has to provide vector category information. This can be
realized with a SQL view
realized with a SQL view, i.e.
     create view route_rn as
     create view route_rn as
     select rn.cat as cat, rn.id as id, r.route_id as route_id
     select rn.cat as cat,
     from route r left join road_network rn on r.rn_id = rn.id;
        rn.id as id,
        r.route_id as route_id
     from route r
        left join road_network rn on r.rn_id = rn.id;


Above tables and view allow to provide road network and driven routes information. They
Above tables and view allow to provide road network and driven routes information. They
Line 69: Line 57:
such minimal approach is being kept.
such minimal approach is being kept.


=== Road Network Data ===
== Creating Grass Vector Layers ==
=== Sample Data ===
Sample data can be downloaded using one of the links
* http://entropy.echelon.pl/wrobell/grass/gvl-0.1.zip
* http://wrobell.it-zone.org/grass/gvl-0.1.zip
 
The archive contains basic relational database  and Grass
data based on Spearfish data
* '''gvl.sqlite''' file is SQLite relational database file with tables and view described above
* vector map '''roads''' containing road network map data
 
To start processing sample data unpack the archive and start Grass
within PERMANENT location
 
    $ unzip gvl-0.1.zip
    $ cd gvl-0.1
    $ grass PERMANENT
 
=== Creating Layers ===
Vector map '''roads''' provided with sample data has one layer of categories and
it is not connected to any database table. This can be checked with commands
 
    $ v.db.connect -p map=roads
    ERROR: Database connection for map <roads> is not defined in DB file
    $ v.category option=report input=roads
    Layer: 1
    type      count        min        max
    point          0          0          0
    line        825          1        825
    boundary      0          0          0
    centroid      0          0          0
    area          0          0          0
    all          825          1        825


Spearfish data provides road network map in '''roads''' vector.
To connect vector map with two layers of data, vector categories
It contains few hundred vector lines - road network segments.
have to be populated into these layers using following commands
Data associated with this vector are very simple and they have to be
extended
* unique category id for every vector road segment needs to generated
* unique id has to be assigned to every road segment


Below, vector '''rn''' is created with every vector line having unique
    $ v.category --o input=roads layer=2 output=tmprn
category
    $ g.remove vect=roads
    $ g.rename vect=tmprn,roads
    $ v.category option=report input=roads
    Layer: 1
    type      count        min        max
    point          0          0          0
    line        825          1        825
    boundary      0          0          0
    centroid      0          0          0
    area          0          0          0
    all          825          1        825
    Layer: 2
    type      count        min        max
    point          0          0          0
    line         825          1        825
    boundary      0          0          0
    centroid      0          0          0
    area          0          0          0
    all          825          1        825


    $ v.category --o in=roads out=tmpmap option=del
    $ v.category --o in=tmpmap out=rn option=add
    $ g.remove vect=tmpmap


Vector '''rn''' is connected to DBF file, which is no longer required. Therefore
Now, database tables have to be connected to Grass vector map using '''v.db.connect'''
it has to be removed.
command
    $ v.db.connect -o map=roads driver=sqlite database=gvl.sqlite table=road_network
    $ v.db.connect -o map=roads layer=2 driver=sqlite database=gvl.sqlite table=route_rn
    $ v.db.connect -p map=roads
    Vector map <roads> is connected by:
    layer <1> table <road_network> in database <gvl.sqlite> through driver <sqlite> with key <cat>
    layer <2> table <route_rn> in database <gvl.sqlite> through driver <sqlite> with key <cat>
Road network table is connected as first layer and route information as second layer.


    $ v.db.droptable -f rn
=== Using Layers ===
Almost all Grass commands accept '''layer''' parameter, which determines
layer to be used by a command. Below, some examples are provided.


Road network table needs to be associated with road network vector
==== Displaying ====
(SQLite driver is used with database located in '''data.sqlite''' file; of course,
To display road network map and routes number 1 and 4
any other RDBMS can be used)
    $ d.mon x0
    $ d.vect map=roads
    $ d.vect map=roads layer=2 color=green width=8 where='route_id=1'
    $ d.vect map=roads layer=2 color=red width=4 where='route_id=4'


     $ v.db.connect -o map=rn driver=sqlite database=data.sqlite table=road_network
==== Creating Separate Route Map ====
To create separate vector map of route number 4
     $ v.extract -t input=roads layer=2 output=r4 where='route_id=4'


Categories of vector '''rn''' has to be uploaded into road network table
Please note '''-t''' parameter, which forces Grass to ''not'' copy database
table, which can be very costly operation.


     $ v.to.db map=rn option=cat
To display vector '''r4''', '''layer''' parameter has to be used as routing
information is still in second layer
     $ d.mon x0
    $ d.vect map=r4 layer=2


As it was said above, road network data usually is provided with some road
== Appendix: Creating Tutorial's Road Network and Routes Data ==
segment identifiers. There is no road segment ids in case of Spearfish data.
Sample data for this tutorial were extracted from Spearfish data.
Therefore, for the purpose of this tutorial they will be generated from categories
As it was quite interesting excersise, detailed information
of vector '''rn'''. It can be done easily with SQL query
describing the process is provided below.


    update road_network set id = cat;
=== Road Network Data ===
Spearfish data provides road network map in '''roads''' vector.
It contains few hundred vector lines - road network segments.
Data associated with this vector map are very simple and they have to be
extended
* unique category id for every vector road segment needs to generated
* unique id has to be assigned to every road segment


=== Routes Data ===
Below, vector '''roads''' is created with every vector line having unique
SQL queries below create four sample routes driven on road network provided
category
in Spearfish data.


     insert into route (route_id, rn_id) values (1, 10);
     $ v.category --o in=roads out=tmpmap option=del
     insert into route (route_id, rn_id) values (1, 411);
     $ v.category --o in=tmpmap out=roads option=add
     insert into route (route_id, rn_id) values (1, 412);
     $ g.remove vect=tmpmap
    insert into route (route_id, rn_id) values (1, 413);
    insert into route (route_id, rn_id) values (1, 414);
    insert into route (route_id, rn_id) values (2, 407);
    insert into route (route_id, rn_id) values (2, 408);
    insert into route (route_id, rn_id) values (2, 410);
    insert into route (route_id, rn_id) values (2, 413);
    insert into route (route_id, rn_id) values (2, 414);
    insert into route (route_id, rn_id) values (3, 10);
    insert into route (route_id, rn_id) values (3, 408);
    insert into route (route_id, rn_id) values (3, 409);
    insert into route (route_id, rn_id) values (3, 415);
    insert into route (route_id, rn_id) values (4, 407);
    insert into route (route_id, rn_id) values (4, 415);
    insert into route (route_id, rn_id) values (4, 9);


Vector map '''roads''' is connected to DBF file, which is no longer required,
it has to be removed using command


== Creating Grass Vector Layers ==
    $ v.db.droptable -f roads


Previous section described in detail how to prepare sample data
Road network table needs to be populated with categories and road segment identifiers.
to illustrate problem defined in this tutorial. To summarize
First, road network table has to be connected to vector map
* road network vector map exists in Grass
    $ v.db.connect -o map=roads driver=sqlite database=gvl.sqlite table=road_network
* road network database table is associated with road network map; it has columns
** id - identifies road segment id
** cat - identifies road segment in Grass vector map
* routes table is created, it has route id and road segment id columns; four routes are defined
* routes to road network view exists to associate route information with Grass vector data


Route network table is connected as first layer to '''rn''' vector.
Now, it is possible to upload categories of vector map '''roads''' into road network table
This can be checked with command
    $ v.to.db map=roads option=cat


    $ v.db.connect -p map=rn
Road network data usually is provided with some road segment identifiers.
The identifiers are usually set by vendor of road network data but they
are missing in case of Spearfish data. Therefore, for the purpose of this tutorial
they will be generated from categories of vector map '''roads'''. It can be done easily
with SQL query


Let's disconnect vector '''rn''' from its first layer
    update road_network set id = cat;


    $ v.db.connect -d map=rn layer=1
Finally, vector map '''roads''' is being disconnected from road network table


Now, without copying database table, vector categories can be populated
     $ v.db.connect -d map=road
into two layers (or more if required)
     $ v.category --o input=rn layer=2 output=tmprn
    $ g.remove vect=rn
    $ g.rename vect=tmprn,rn
'''Above step is very important. Vector categories needs to be populated in all layers.'''


Road network table can be reconnected as first layer
=== Routes Data ===
and route information as second layer
Routes data were created using '''d.what.vect''' command.
    $ v.db.connect -o map=rn driver=sqlite database=data.sqlite table=road_network
Road network vector map '''roads''' has to be displayed
    $ v.db.connect -o map=rn layer=2 driver=sqlite database=data.sqlite table=route_rn
     $ d.mon x0
    $ v.db.connect -p map=rn
     $ d.vect map=roads
    Vector map <rn> is connected by:
     layer <1> table <road_network> in database <data.sqlite> through driver <sqlite> with key <cat>
     layer <2> table <route_rn> in database <data.sqlite> through driver <sqlite> with key <cat>


Road network map and routes no 1 and 4 can be displayed
Now, it can be queried for data. Run
     $ d.vect map=rn
     $ d.what.vect -t map=roads > route-01.txt
    $ d.vect map=rn layer=2 color=green width=8 where='route_id=1'
Using mouse pointer, roads segments belonging to first route,
    $ d.vect map=rn layer=2 color=red width=4 where='route_id=4'
can be identified. When done, file '''route.txt''' can be
which is rendered as on the map presented below
processed with '''awk''' or other tool to extract road segment
[[Image:routes.png|frame|Road network and routes 1 and 4]]
information, which can be easily uploaded to database.


http://grass.osgeo.org/grass63/manuals/html63_user/vectorintro.html
== References ==
<references/>
[[Category:Documentation]]
[[Category:Vector]]

Latest revision as of 00:36, 7 December 2011

Introduction

Grass documentation provides basic information about vector attribute management, categories of vector features and vector layers. [1]

The aim of this tutorial is to show how to create, manipulate and display different layers of a vector map using relational database.

Problem Description

An organization provides information about routes to be driven by drivers. The organization's database consists of

  • roads (road network)
  • routes driven on these roads

Simple approach can be taken to present the routes to drivers. For every route a vector map could be created and overlayed over the road network vector map, i.e.

   $ d.vect map=roads
   $ d.vect map=route01 color=green width=2

Above idea has a major flaw. If route data change or new route is added then vector maps has to be regenerated or removed.

Assuming that route network and routes data are stored in relational database, the database tables can be linked to road network map as its layers. Such layer information could be utilized to display maps, i.e.

   $ d.vect map=roads
   $ d.vect map=roads layer=2 where="route_id=1" color=green width=2

Datamodel Discussion

Relation database should contain two tables

  • road network table
  • driven routes table

Road network table has to have at least two columns

  • road segment id usually provided with road network data by vendor
  • vectory category required by Grass to identify vector features

Routes table shall consist of

  • route identifier
  • id of road segment driven on a route, which references road segment id in road network table

Routes table also has to provide vector category information. This can be realized with a SQL view, i.e.

   create view route_rn as
   select rn.cat as cat,
       rn.id as id,
       r.route_id as route_id
   from route r
       left join road_network rn on r.rn_id = rn.id;

Above tables and view allow to provide road network and driven routes information. They can be more complicated depending on application but for purpose of this tutorial such minimal approach is being kept.

Creating Grass Vector Layers

Sample Data

Sample data can be downloaded using one of the links

The archive contains basic relational database and Grass data based on Spearfish data

  • gvl.sqlite file is SQLite relational database file with tables and view described above
  • vector map roads containing road network map data

To start processing sample data unpack the archive and start Grass within PERMANENT location

   $ unzip gvl-0.1.zip
   $ cd gvl-0.1
   $ grass PERMANENT

Creating Layers

Vector map roads provided with sample data has one layer of categories and it is not connected to any database table. This can be checked with commands

   $ v.db.connect -p map=roads
   ERROR: Database connection for map <roads> is not defined in DB file
   $ v.category option=report input=roads
   Layer: 1
   type       count        min        max
   point          0          0          0
   line         825          1        825
   boundary       0          0          0
   centroid       0          0          0
   area           0          0          0
   all          825          1        825

To connect vector map with two layers of data, vector categories have to be populated into these layers using following commands

   $ v.category --o input=roads layer=2 output=tmprn
   $ g.remove vect=roads
   $ g.rename vect=tmprn,roads
   $ v.category option=report input=roads
   Layer: 1
   type       count        min        max
   point          0          0          0
   line         825          1        825
   boundary       0          0          0
   centroid       0          0          0
   area           0          0          0
   all          825          1        825
   Layer: 2
   type       count        min        max
   point          0          0          0
   line         825          1        825
   boundary       0          0          0
   centroid       0          0          0
   area           0          0          0
   all          825          1        825


Now, database tables have to be connected to Grass vector map using v.db.connect command

   $ v.db.connect -o map=roads driver=sqlite database=gvl.sqlite table=road_network
   $ v.db.connect -o map=roads layer=2 driver=sqlite database=gvl.sqlite table=route_rn
   $ v.db.connect -p map=roads
   Vector map <roads> is connected by:
   layer <1> table <road_network> in database <gvl.sqlite> through driver <sqlite> with key <cat>
   layer <2> table <route_rn> in database <gvl.sqlite> through driver <sqlite> with key <cat>

Road network table is connected as first layer and route information as second layer.

Using Layers

Almost all Grass commands accept layer parameter, which determines layer to be used by a command. Below, some examples are provided.

Displaying

To display road network map and routes number 1 and 4

   $ d.mon x0
   $ d.vect map=roads
   $ d.vect map=roads layer=2 color=green width=8 where='route_id=1'
   $ d.vect map=roads layer=2 color=red width=4 where='route_id=4'

Creating Separate Route Map

To create separate vector map of route number 4

   $ v.extract -t input=roads layer=2 output=r4 where='route_id=4'

Please note -t parameter, which forces Grass to not copy database table, which can be very costly operation.

To display vector r4, layer parameter has to be used as routing information is still in second layer

   $ d.mon x0
   $ d.vect map=r4 layer=2

Appendix: Creating Tutorial's Road Network and Routes Data

Sample data for this tutorial were extracted from Spearfish data. As it was quite interesting excersise, detailed information describing the process is provided below.

Road Network Data

Spearfish data provides road network map in roads vector. It contains few hundred vector lines - road network segments. Data associated with this vector map are very simple and they have to be extended

  • unique category id for every vector road segment needs to generated
  • unique id has to be assigned to every road segment

Below, vector roads is created with every vector line having unique category

   $ v.category --o in=roads out=tmpmap option=del
   $ v.category --o in=tmpmap out=roads option=add
   $ g.remove vect=tmpmap

Vector map roads is connected to DBF file, which is no longer required, it has to be removed using command

   $ v.db.droptable -f roads

Road network table needs to be populated with categories and road segment identifiers. First, road network table has to be connected to vector map

   $ v.db.connect -o map=roads driver=sqlite database=gvl.sqlite table=road_network

Now, it is possible to upload categories of vector map roads into road network table

   $ v.to.db map=roads option=cat

Road network data usually is provided with some road segment identifiers. The identifiers are usually set by vendor of road network data but they are missing in case of Spearfish data. Therefore, for the purpose of this tutorial they will be generated from categories of vector map roads. It can be done easily with SQL query

   update road_network set id = cat;

Finally, vector map roads is being disconnected from road network table

   $ v.db.connect -d map=road

Routes Data

Routes data were created using d.what.vect command. Road network vector map roads has to be displayed

   $ d.mon x0
   $ d.vect map=roads

Now, it can be queried for data. Run

   $ d.what.vect -t map=roads > route-01.txt

Using mouse pointer, roads segments belonging to first route, can be identified. When done, file route.txt can be processed with awk or other tool to extract road segment information, which can be easily uploaded to database.

References