1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
|
/*! \page vlibTopology Topology
by GRASS Development Team (https://grass.osgeo.org)
\tableofcontents
\section vlibTopoManagement Vector library topology management
Topology general characteristics:
- geometry and attributes are stored separately
(don't read both if it is not necessary - usually it is not)
- the format is topological (areas build from boundaries)
- currently only 2D topology is supported
Topology is written for native GRASS vector format; in case of
linked OGR sources (see <tt>v.external</tt> module), only
pseudo-topology (boundaries constructed from polygons) is written.
The following rules apply to the vector data:
- Boundaries should not cross each other (i.e., boundaries which would
cross must be split at their intersection to form distict boundaries).
On the contrary, lines can cross each other, e.g. bridges over rivers.
- Lines and boundaries share nodes only if their endpoints are identical.
Lines or boundaries can be forced to share a common node by snapping
them together. This is particularly important since nodes
are not represented in the coor file, but only implicitly as
endpoints of lines and boundaries.
- Common area boundaries should appear only once (i.e., should not be
double digitized).
- Areas must be explicitly closed. This means that it must be possible
to complete each area by following one or more boundaries that are
connected by common nodes, and that such tracings result in closed
areas.
- It is recommended that area features and linear features be placed
in separate layers. However if area features and linear features
must appear in one layer, common boundaries should be digitized only
once. For example, a boundary that is also a line (e.g., a road which
is also a field boundary), should be digitized as a boundary to
complete the area(s), and a boundary which is functionally also a line
should be labeled as a line by a distinct category number.
Vector map topology can be cleaned at user level by <tt>v.clean</tt>
command.
\subsection vlibTopoFileFormat Topo file format specification
Topo file is read by Vect_open_topo().
\subsubsection vlibTopoFileHead Header
<i>Note:</i> <tt>plus</tt> is an instance of \ref Plus_head data structure.
<table border="1" style="border-collapse: collapse" cellpadding="5">
<tr><td><b>Name</b></td><td><b>Type</b></td><td><b>Number</b></td><td><b>Description</b></td></tr>
<tr><td>plus->Version_Major </td><td>C</td><td>1</td><td>file version (major)</td></tr>
<tr><td>plus->Version_Minor </td><td>C</td><td>1</td><td>file version (minor)</td></tr>
<tr><td>plus->Back_Major</td><td>C</td><td>1</td><td>supported from GRASS version (major)</td></tr>
<tr><td>plus->Back_Minor</td><td>C</td><td>1</td><td>supported from GRASS version (minor)</td></tr>
<tr><td>plus->port->byte_order</td><td>C</td><td>1</td><td>little or big endian
flag; files are written in machine native order but
files in both little and big endian order may be
readl; zero for little endian</td></tr>
<tr><td>plus->head_size</td><td>L</td><td>1</td><td>header size</td></tr>
<tr><td>plus->with_z</td><td>C</td><td>1</td><td>2D or 3D flag; zero for 2D</td></tr>
<tr><td>plus->box</td><td>D</td><td>6</td><td>Bounding box coordinates (N,S,E,W,T,B)</td></tr>
<tr><td>plus->n_nodes, plus->n_lines, etc.</td><td>I</td><td>7</td><td>Number of
nodes, edges, lines, areas, isles, volumes and holes</td></tr>
<tr><td>plus->n_plines, plus->n_llines, etc.</td><td>I</td><td>7</td><td>Number of
points, lines, boundaries, centroids, faces and kernels</td></tr>
<tr><td>plus->Node_offset, plus->Edge_offset,
etc.</td><td>L</td><td>7</td><td>Offset value for nodes, edges, lines,
areas, isles, volumes and holes</td></tr>
<tr><td>plus->coor_size</td><td>L</td><td>1</td><td>File size</td></tr>
</table>
\subsubsection vlibTopoFileBody Body (nodes, lines, areas, isles)
<b>Nodes</b>
For each node (plus->n_nodes):
<table border="1" style="border-collapse: collapse" cellpadding="5">
<tr><td><b>Name</b></td><td><b>Type</b></td><td><b>Number</b></td><td><b>Description</b></td></tr>
<tr><td>n_lines</td><td>I</td><td>1</td><td>Number of lines (0 for dead node)</td></tr>
<tr><td>lines</td><td>I</td><td>n_lines</td><td>Line ids (negative id for line which ends at the node)</td></tr>
<tr><td>angles</td><td>D</td><td>n_lines</td><td>Angle value</td></tr>
<tr><td>n_edges</td><td>I</td><td>1</td><td>Reserved for edges (only for <tt>with_z</tt>)</td></tr>
<tr><td>x,y</td><td>D</td><td>2</td><td>Coordinate pair (2D)</td></tr>
<tr><td>z</td><td>D</td><td>1</td><td>Only for <tt>with_z</tt> (3D)</td></tr>
</table>
See \ref P_node data structure.
<b>Lines</b>
For each line (plus->n_lines):
<table border="1" style="border-collapse: collapse" cellpadding="5">
<tr><td><b>Name</b></td><td><b>Type</b></td><td><b>Number</b></td><td><b>Description</b></td></tr>
<tr><td>feature type</td><td>C</td><td>1</td><td>0 for dead line</td></tr>
<tr><td>offset</td><td>L</td><td>1</td><td>Line offset</td></tr>
<tr><td>N1</td><td>I</td><td>1</td><td>Start node id (only if feature type is GV_LINE or GV_BOUNDARY)</td></tr>
<tr><td>N2</td><td>I</td><td>1</td><td>End node id (only if feature type is GV_LINE or GV_BOUNDARY)</td></tr>
<tr><td>left</td><td>I</td><td>1</td><td>Left area id for feature type GV_BOUNDARY / Area id for feature type GV_CENTROID</td></tr>
<tr><td>right</td><td>I</td><td>1</td><td>Right area id (for feature type GV_BOUNDARY)</td></tr>
<tr><td>vol</td><td>I</td><td>1</td><td>Reserved for kernel (volume number, for feature type GV_KERNEL)</td></tr>
</table>
See \ref P_line data structure.
<b>Areas</b>
For each area (plus->n_areas):
<table border="1" style="border-collapse: collapse" cellpadding="5">
<tr><td><b>Name</b></td><td><b>Type</b></td><td><b>Number</b></td><td><b>Description</b></td></tr>
<tr><td>n_lines</td><td>I</td><td>1</td><td>number of boundaries</td></tr>
<tr><td>lines</td><td>I</td><td>n_lines</td><td>Line ids forming exterior boundary (clockwise order, negative id for backward direction)</td></tr>
<tr><td>n_isles</td><td>I</td><td>1</td><td>Number of isles</td></tr>
<tr><td>isles</td><td>I</td><td>n_isles</td><td>Isle ids</td></tr>
<tr><td>centroid</td><td>I</td><td>1</td><td>Centroid id</td></tr>
</table>
See \ref P_area data structure.
<b>Isles</b>
For each isle (plus->n_isle):
<table border="1" style="border-collapse: collapse" cellpadding="5">
<tr><td><b>Name</b></td><td><b>Type</b></td><td><b>Number</b></td><td><b>Description</b></td></tr>
<tr><td>n_lines</td><td>I</td><td>1</td><td>number of boundaries</td></tr>
<tr><td>lines</td><td>I</td><td>n_lines</td><td>Line ids forming exterior boundary (counter-clockwise order, negative id for backward direction)</td></tr>
<tr><td>area</td><td>I</td><td>1</td><td>Outer area id</td></tr>
</table>
See \ref P_isle data structure.
\subsection vlibTopoLevels Topology levels
The vector library defines more <i>topology levels</i> (only for level
of access 2):
- GV_BUILD_NONE
- GV_BUILD_BASE
- GV_BUILD_AREAS
- GV_BUILD_ATTACH_ISLES
- GV_BUILD_CENTROIDS
- GV_BUILD_ALL
<i>Note:</i> Only the geometry type GV_BOUNDARY is used to build
areas. The geometry type GV_LINE cannot form an area.
\subsection vlibTopoExamples Topology examples
<b>Points</b>
\verbatim
One point (nodes: 0, lines: 1, areas: 0, isles: 0)
+ L1
\endverbatim
Line L1 (see \ref P_line)
\verbatim
line = 1, type = 1 (GV_POINT)
\endverbatim
<b>Lines</b>
\verbatim
One line (nodes: 2, lines: 1, areas: 0, isles: 0)
+----L1----+
N1 N2
\endverbatim
%Node N1 (see \ref P_node)
\verbatim
node = 1, n_lines = 1, xyz = 634624.746450, 223557.302231, 0.000000
line = 1, type = 2 (GV_LINE), angle = -0.436257
\endverbatim
%Node N2 (see \ref P_node)
\verbatim
node = 2, n_lines = 1, xyz = 638677.484787, 221667.849899, 0.000000
line = -1, type = 2 (GV_LINE), angle = 2.705335
\endverbatim
Line L1 (see \ref P_line)
\verbatim
line = 1, type = 2 (GV_LINE), n1 = 1, n2 = 2
\endverbatim
<b>Areas without holes</b>
\verbatim
Two lines (nodes: 1, lines: 2, areas: 1, isles: 1)
+N1
/ \
/ \
/ \
/ +L2 \
/ \
-------L1------
\endverbatim
%Node N1 (see \ref P_node)
\verbatim
node = 1, n_lines = 2, xyz = 635720.081136, 225063.387424, 0.000000
line = 1, type = 4 (GV_BOUNDARY), angle = -2.245537
line = -1, type = 4 (GV_BOUNDARY), angle = -0.842926
\endverbatim
Line L1 (see \ref P_line)
\verbatim
line = 1, type = 4 (GV_BOUNDARY), n1 = 1, n2 = 1, left = 1, right = -1
\endverbatim
Line L2 (see \ref P_line)
\verbatim
line = 2, type = 8 (GV_CENTROID), area = 1
\endverbatim
Area A1 (see \ref P_area)
\verbatim
area = 1, n_lines = 1, n_isles = 0 centroid = 2
line = -1
\endverbatim
Isle I1 (see \ref P_isle)
\verbatim
isle = 1, n_lines = 1 area = 0
line = 1
\endverbatim
<b>Areas with holes</b>
\verbatim
Three lines (nodes: 2, lines: 3, areas: 2, isles: 2)
+N1
/ \
/ \
/ \
/ \
/ +L2 \
/ \
/ +N2 \
/ /\ \
/ / \ \
/ / \ \
/ ---L3-- \
/ \
------------L1-------------
\endverbatim
%Node N1 (see \ref P_node)
\verbatim
node = 1, n_lines = 2, xyz = 635720.081136, 225063.387424, 0.000000
line = 1, type = 4 (GV_BOUNDARY), angle = -2.245537
line = -1, type = 4 (GV_BOUNDARY), angle = -0.842926
\endverbatim
%Node N2 (see \ref P_node)
\verbatim
node = 2, n_lines = 2, xyz = 636788.032454, 223173.935091, 0.000000
line = 3, type = 4 (GV_BOUNDARY), angle = -2.245537
line = -3, type = 4 (GV_BOUNDARY), angle = -0.866302
\endverbatim
Line L1 (see \ref P_line)
\verbatim
line = 1, type = 4 (GV_BOUNDARY), n1 = 1, n2 = 1, left = 1, right = -1
\endverbatim
Line L2 (see \ref P_line)
\verbatim
line = 2, type = 8 (GV_CENTROID), area = 1
\endverbatim
Line L3 (see \ref P_line)
\verbatim
line = 3, type = 4 (GV_BOUNDARY), n1 = 3, n2 = 3, left = 2, right = -2
\endverbatim
Area A1 (see \ref P_area)
\verbatim
area = 1, n_lines = 1, n_isles = 1 centroid = 2
line = -1
isle = 2
\endverbatim
Area A2 (see \ref P_area)
\verbatim
area = 2, n_lines = 1, n_isles = 0 centroid = 0
line = -3
\endverbatim
Isle I1 (see \ref P_isle)
\verbatim
isle = 1, n_lines = 1 area = 0
line = 1
\endverbatim
Isle I2 (see \ref P_isle)
\verbatim
isle = 2, n_lines = 1 area = 1
line = 3
\endverbatim
<b>Example 1</b>
A polygon may be formed by many boundaries (several connected primitives).
One boundary is shared by adjacent areas.
\verbatim
+--1--+--5--+
| | |
2 A 4 B 6
| | |
+--3--+--7--+
1,2,3,4,5,6,7 = 7 boundaries (primitives)
A,B = 2 areas
A+B = 1 isle
\endverbatim
<b>Example 2</b>
This is handled correctly in GRASS: A can be filled, B filled differently.
\verbatim
+---------+
| A |
+-----+ |
| B | |
+-----+ |
| |
+---------+
A, B = 2 areas
A+B = 1 isle
\endverbatim
In GRASS, whenever an 'inner' ring touches the boundary of an outside
area, even in one point, it is no longer an 'inner' ring (isle in
GRASS topology), it is simply another area. A, B above can never be
exported from GRASS as polygon A with inner ring B because there are
only 2 areas A and B and one island formed by A and B together.
<b>Example 3</b>
This is handled correctly in GRASS: Areas A1, A2, and A3 can be filled differently.
\verbatim
+---------------------+
| A1 |
+ +------+------+ |
| | A2 | A3 | |
+ +------+------+ |
| I1 |
+---------------------+
A1,A2,A3 = 3 areas
A1,A2+A3 = 2 isles
\endverbatim
In GRASS, whenever an 'inner' ring does not touch the boundary of an
outside area, also not in one point, it is an 'inner' ring (isle). The
areas A2 and A3 form a single isle I1 located within area A1. The size
of isle I1 is subtracted from the size of area A1 when calculating
the size of area A1. Any centroids falling into isle I1 are excluded
when searching for a centroid that can be attached to area A1. A1
above can be exported from GRASS as polygon A1 with inner ring I1.
<b>Example 4</b>
<tt>v.in.ogr/v.clean</tt> can identify dangles and change the type
from boundary to line (in TIGER data for example). Distinction
between line and boundary isn't important only for dangles. Example:
\verbatim
+-----+-----+
| . |
| . |
+.....+.....+
| . |
| x . |
+-----+-----+
---- road + boundary of one parcel => type boundary
.... road => type line
x parcel centroid (identifies whole area)
\endverbatim
Because lines are not used to build areas, we have only one
area/centroid, instead of 4 which would be necessary in TIGER.
\subsection vlibTopoMemory Topology memory management
Topology is generated for all kinds of vector types. Memory is not
released by default. The programmer can force the library to release
the memory by using Vect_set_release_support(). But: The programmer
cannot run Vect_set_release_support() in mid process because all
vectors are needed in the spatial index, which is needed to build topology.
Topology is also necessary for points in case of a vector network
because the graph is built using topology information about lines
and points.
The topology structure does not only store the topology but also
the 'line' bounding box and line offset in coor file (index).
The existing spatial index is using line ID in 'topology' structure
to identify lines in 'coor' file. Currently it is not possible to build
spatial index without topology.
*/
|