| 1 | =Introduction |
|---|
| 2 | |
|---|
| 3 | This module contains support for topological geometry modelling. |
|---|
| 4 | Functions exist to satisfy the ISO/SQLMM topology-geometry model |
|---|
| 5 | and more are provided to add an additional abstraction level for |
|---|
| 6 | topological features and layers, both simple and hierarchical. |
|---|
| 7 | |
|---|
| 8 | You can see an ER diagram of the full conceptual model in the ER dir. |
|---|
| 9 | You need xfig (http://epb.lbl.gov/xfig/). |
|---|
| 10 | |
|---|
| 11 | All routines, types and other management objects are stored in the |
|---|
| 12 | "topology" SCHEMA. |
|---|
| 13 | |
|---|
| 14 | Comments welcome --strk(2012-03-13); |
|---|
| 15 | |
|---|
| 16 | =Requirements |
|---|
| 17 | |
|---|
| 18 | Many ISO/SQLMM functions use GEOS-3.3.0+ signatures. |
|---|
| 19 | The script is still buildable with previous GEOS versions |
|---|
| 20 | but you'll need 3.3.0+ at runtime for most uses. |
|---|
| 21 | |
|---|
| 22 | =Building |
|---|
| 23 | |
|---|
| 24 | To build the topology support: |
|---|
| 25 | |
|---|
| 26 | $ make |
|---|
| 27 | |
|---|
| 28 | =Testing |
|---|
| 29 | |
|---|
| 30 | To run regression tests: |
|---|
| 31 | |
|---|
| 32 | $ make check |
|---|
| 33 | |
|---|
| 34 | =Install, upgrade, uninstall |
|---|
| 35 | |
|---|
| 36 | To enable topology support: |
|---|
| 37 | |
|---|
| 38 | $ psql -f topology.sql <your_postgis_enabled_db> |
|---|
| 39 | |
|---|
| 40 | It will create a 'topology' schema in <your_postgis_enabled_db> |
|---|
| 41 | hosting all the topology functions. To be run with db-owner perms. |
|---|
| 42 | Remember to grant execute to users. |
|---|
| 43 | |
|---|
| 44 | To uninstall: |
|---|
| 45 | |
|---|
| 46 | $ psql -c 'drop schema topology cascade' |
|---|
| 47 | |
|---|
| 48 | To upgrade between minor releases: |
|---|
| 49 | |
|---|
| 50 | $ psql -f topology_upgrade_<version>_minor.sql <your_postgis_enabled_db> |
|---|
| 51 | |
|---|
| 52 | Major releases upgrades should follow the "HARD UPGRADE" procedure |
|---|
| 53 | described in main postgis manual. |
|---|
| 54 | |
|---|
| 55 | =Usage |
|---|
| 56 | |
|---|
| 57 | Topology data are stored in named SCHEMAs, where the topology |
|---|
| 58 | name is the name of the SCHEMA containing its data. |
|---|
| 59 | |
|---|
| 60 | A catalogue of avalable topologies is kept under the |
|---|
| 61 | "topology"."topology" table. |
|---|
| 62 | |
|---|
| 63 | ==Creating a topology |
|---|
| 64 | |
|---|
| 65 | To create a topology: |
|---|
| 66 | |
|---|
| 67 | SELECT topology.CreateTopology(<name>, [srid], [tolerance]); |
|---|
| 68 | |
|---|
| 69 | Example: |
|---|
| 70 | |
|---|
| 71 | SELECT topology.CreateTopology('test_schema', 4326 , 0.0001); |
|---|
| 72 | or |
|---|
| 73 | -- unknown srid, 0 tolerance |
|---|
| 74 | SELECT topology.CreateTopology('test_schema'); |
|---|
| 75 | |
|---|
| 76 | NOTE: the new schema ('test_schema' in example) will be create |
|---|
| 77 | so it must not exist before. |
|---|
| 78 | |
|---|
| 79 | ==Destroying a topology |
|---|
| 80 | |
|---|
| 81 | To destroy a topology: |
|---|
| 82 | |
|---|
| 83 | SELECT topology.DropTopology(<name>); |
|---|
| 84 | |
|---|
| 85 | ==Loading topology data |
|---|
| 86 | |
|---|
| 87 | To load topology data in a topology you can use INSERT |
|---|
| 88 | statements filling up the Edge, Node and Face relations |
|---|
| 89 | under you topology schema: |
|---|
| 90 | |
|---|
| 91 | |
|---|
| 92 | * Edge |
|---|
| 93 | * edge_id integer PRIMARY KEY |
|---|
| 94 | * start_node integer REFERENCES Node.node_id) |
|---|
| 95 | * end_node integer REFERENCES Node.node_id) |
|---|
| 96 | * next_left_edge integer REFERENCES abs(Edge.edge_id) |
|---|
| 97 | * next_right_edge integer REFERENCES abs(Edge.edge_id) |
|---|
| 98 | * left_face integer REFERENCES Face.face_id |
|---|
| 99 | * right_face integer REFERENCES Face.face_id |
|---|
| 100 | * geom geometry ( a linestring ) |
|---|
| 101 | |
|---|
| 102 | |
|---|
| 103 | * Node |
|---|
| 104 | * node_id integer PRIMARY KEY |
|---|
| 105 | * containing_face integer REFERENCES Face.face_id |
|---|
| 106 | * geom geometry ( a point ) |
|---|
| 107 | |
|---|
| 108 | * Face |
|---|
| 109 | * face_id integer PRIMARY KEY |
|---|
| 110 | * mbr box2d ( can be NULL ) |
|---|
| 111 | |
|---|
| 112 | The next_*_edge of an edge is the edge you encounter next while going |
|---|
| 113 | around the specified face (right or left) in counterclockwise order |
|---|
| 114 | (so that the face is on your left). Note that due to this definition |
|---|
| 115 | the edge being considered is traversed in reverse order when traversing |
|---|
| 116 | its "right" face. The values are signed to indicate wheter the next edge |
|---|
| 117 | will be traversed in its original or reversed orientation. |
|---|
| 118 | |
|---|
| 119 | More details on semantic are contained in the SQL/MM specification, which |
|---|
| 120 | this implementation follows as for these views structure. |
|---|
| 121 | |
|---|
| 122 | ==Validating topology data |
|---|
| 123 | |
|---|
| 124 | To verify validity of a topology: |
|---|
| 125 | |
|---|
| 126 | SELECT * FROM topology.ValidateTopology(name); |
|---|
| 127 | |
|---|
| 128 | ==Defining TopoGeometry objects |
|---|
| 129 | |
|---|
| 130 | Currently, TopoGeometry objects can only be defined by specifying their |
|---|
| 131 | component topology elements. We do support both basic TopoGeometry |
|---|
| 132 | and hierarchical TopoGeometry. Basic TopoGeometry objects are those |
|---|
| 133 | composed by base topolocal elements (faces, edges, nodes). Hierarchical |
|---|
| 134 | TopoGeometry objects are composed by other TopoGeometry objects. |
|---|
| 135 | |
|---|
| 136 | Each TopoGeometry object belongs to a specific Layer of a specific |
|---|
| 137 | Topology. Before creating a TopoGeometry object you need to create |
|---|
| 138 | its Layer in the Topology. A Topology Layer is an association of |
|---|
| 139 | a feature-table with the topology. It also contain type and hierarchy |
|---|
| 140 | information. We create a layer using the AddTopoGeometryColumn() function: |
|---|
| 141 | |
|---|
| 142 | topology.AddTopoGeometryColumn(topology_name, |
|---|
| 143 | schema_name, table_name, column_name, feature_type, |
|---|
| 144 | [child_layer]) |
|---|
| 145 | |
|---|
| 146 | The function will both add the requested column to the table and add |
|---|
| 147 | a record to the topology.layer table with all the given info. |
|---|
| 148 | |
|---|
| 149 | If you don't specify [child_layer] (or set it to NULL) this layer |
|---|
| 150 | would contain Basic TopoGeometries (composed by primitive topology |
|---|
| 151 | elements). Otherwise this layer will contain hierarchical TopoGeometries |
|---|
| 152 | (composed by TopoGeometries from the child_layer). |
|---|
| 153 | |
|---|
| 154 | Once the layer is created (it's id is returned by the AddTopoGeometryColumn |
|---|
| 155 | function) you're ready to construct TopoGeometry objects in it: |
|---|
| 156 | |
|---|
| 157 | topology.CreateTopoGeom( |
|---|
| 158 | |
|---|
| 159 | topology_name, |
|---|
| 160 | |
|---|
| 161 | feature_type, -- 1:[multi]point, 2:[multi]line, |
|---|
| 162 | -- 3:[multi]poly, 4:collection |
|---|
| 163 | |
|---|
| 164 | layer_id, -- as returned by AddTopoGeometryColumn |
|---|
| 165 | |
|---|
| 166 | TopoElementArray); |
|---|
| 167 | |
|---|
| 168 | The TopoElementArray type is a bidimensional array of integers. |
|---|
| 169 | Value semantics depend on the type of the layer associated with |
|---|
| 170 | the TopoGeometry object. For Basic TopoGeometry objects this would |
|---|
| 171 | be: |
|---|
| 172 | {{element_type, element_id}, ...} |
|---|
| 173 | |
|---|
| 174 | For Hierarchical TopoGeometry objects this would be: |
|---|
| 175 | |
|---|
| 176 | {{child_layer_id, topogeoemtry_id}, ...} |
|---|
| 177 | |
|---|
| 178 | ==Converting Geometry to TopoGeometry while populating the topology |
|---|
| 179 | |
|---|
| 180 | You can import a Geometry into an existing topology and at the same |
|---|
| 181 | time get its topological definition (its TopoGeometry equivalent) |
|---|
| 182 | using the toTopoGeom function: |
|---|
| 183 | |
|---|
| 184 | topology.toTopoGeom( |
|---|
| 185 | |
|---|
| 186 | geometry, -- the simple geometry |
|---|
| 187 | |
|---|
| 188 | topology_name, |
|---|
| 189 | |
|---|
| 190 | layer_id -- as returned by AddTopoGeometryColumn |
|---|
| 191 | ); |
|---|
| 192 | |
|---|
| 193 | ==Getting simple Geometry values from TopoGeometry objects |
|---|
| 194 | |
|---|
| 195 | TopoGeometry to Geometry casting is implicit, so any function accepting |
|---|
| 196 | a Geometry would transparently also accept a TopoGeometry. Some functions |
|---|
| 197 | may be optimized for TopoGeometry. |
|---|
| 198 | |
|---|
| 199 | =Issues |
|---|
| 200 | |
|---|
| 201 | ==Topology tolerance |
|---|
| 202 | |
|---|
| 203 | GEOS (and JTS) often fail due to input precision. |
|---|
| 204 | The CreateTopogeo() function currently accept a precision |
|---|
| 205 | specification, we might use this to enforce a precision |
|---|
| 206 | to the topology element geometries, by mean of SnapToGrid |
|---|
| 207 | calls, or alternatively, force use of a specific PrecisionModel |
|---|
| 208 | when using GEOS function. The former seems cleaner, but would |
|---|
| 209 | require a trigger to run on all inserts, even when the geometry |
|---|
| 210 | being input has already been snapped by caller. |
|---|
| 211 | |
|---|
| 212 | ==ST_GetFaceGeometry() implementation |
|---|
| 213 | |
|---|
| 214 | The ST_GetFaceGeometry() function is currently implemented |
|---|
| 215 | as a call to polygonize() receiving all edges with the |
|---|
| 216 | given Face on the left or right side. This reduces the number |
|---|
| 217 | of SQL queries to 1, but makes it hard to detect any |
|---|
| 218 | inconsistency in the underlying topology. |
|---|
| 219 | Also, the polygonize() function does not use *any* of the |
|---|
| 220 | metadata informations in the Edge table, so replacing it |
|---|
| 221 | with a more topology-aware function could speed it up. |
|---|
| 222 | |
|---|
| 223 | ==ValidateTopology() performance |
|---|
| 224 | |
|---|
| 225 | The ValidateTopology() function, as for SQL/MM specification |
|---|
| 226 | uses ST_GetFaceGeometry() to check for Within() and Overlap() |
|---|
| 227 | conditions. This is an expensive task, and might be replaced |
|---|
| 228 | by topology-aware replacement of the two predicates. The |
|---|
| 229 | Face geometries might also be cached, but that might still |
|---|
| 230 | be slower then overloading the predicates. |
|---|
| 231 | |
|---|
| 232 | ==Topology table constraints |
|---|
| 233 | |
|---|
| 234 | In addition to the constraints defined in SQL/MM specification, |
|---|
| 235 | this implementation adds constraints to enforce Node and Edge |
|---|
| 236 | geometry types to be 'POINT' and 'LINESTRING' respectively. |
|---|