|
14 | 14 |
|
15 | 15 | import qgis |
16 | 16 | import os |
| 17 | +import csv |
17 | 18 |
|
18 | 19 | from qgis.core import (QgsGeometry, |
19 | 20 | QgsVectorLayer, |
|
28 | 29 | TestCase, |
29 | 30 | unittest, |
30 | 31 | compareWkt, |
| 32 | + doubleNear, |
31 | 33 | unitTestDataPath, |
32 | 34 | writeShape) |
33 | 35 |
|
@@ -116,22 +118,78 @@ def testFromMultiPolygon(self): |
116 | 118 | (QGis.WKBMultiPolygon, myMultiPolygon.type())) |
117 | 119 | assert myMultiPolygon.wkbType() == QGis.WKBMultiPolygon, myMessage |
118 | 120 |
|
119 | | - def testExportToWkt(self): |
120 | | - """ Test parsing a whole range of valid wkt formats and variants. |
| 121 | + def testReferenceGeometry(self): |
| 122 | + """ Test parsing a whole range of valid reference wkt formats and variants, and checking |
| 123 | + expected values such as length, area, centroids, bounding boxes, etc of the resultant geometry. |
121 | 124 | Note the bulk of this test data was taken from the PostGIS WKT test data """ |
122 | | - with open(os.path.join(TEST_DATA_DIR, 'wkt_data.csv'), 'r') as d: |
123 | | - for i, t in enumerate(d): |
124 | | - test_data = t.strip().split('|') |
125 | | - wkt = test_data[0].strip() |
126 | | - geom = QgsGeometry.fromWkt(wkt) |
127 | | - assert geom, "WKT conversion {} failed: could not create geom:\n{}\n".format(i + 1, wkt) |
| 125 | + |
| 126 | + with open(os.path.join(TEST_DATA_DIR, 'geom_data.csv'), 'rb') as f: |
| 127 | + reader = csv.DictReader(f) |
| 128 | + for i, row in enumerate(reader): |
| 129 | + |
| 130 | + #test that geometry can be created from WKT |
| 131 | + geom = QgsGeometry.fromWkt(row['wkt']) |
| 132 | + assert geom, "WKT conversion {} failed: could not create geom:\n{}\n".format(i + 1, row['wkt']) |
| 133 | + |
| 134 | + #test exporting to WKT results in expected string |
128 | 135 | result = geom.exportToWkt() |
129 | | - if len(test_data) > 1: |
130 | | - exp = test_data[1] |
131 | | - else: |
132 | | - exp = test_data[0] |
| 136 | + exp = row['valid_wkt'] |
133 | 137 | assert compareWkt(result, exp), "WKT conversion {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
134 | 138 |
|
| 139 | + #test num points in geometry |
| 140 | + exp_nodes = int(row['num_points']) |
| 141 | + assert geom.geometry().nCoordinates() == exp_nodes, "Node count {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp_nodes, geom.geometry().nCoordinates()) |
| 142 | + |
| 143 | + #test num geometries in collections |
| 144 | + exp_geometries = int(row['num_geometries']) |
| 145 | + try: |
| 146 | + assert geom.geometry().numGeometries() == exp_geometries, "Geometry count {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp_geometries, geom.geometry().numGeometries()) |
| 147 | + except: |
| 148 | + #some geometry types don't have numGeometries() |
| 149 | + assert exp_geometries <= 1, "Geometry count {}: Expected:\n{} geometries but could not call numGeometries()\n".format(i + 1, exp_geometries) |
| 150 | + |
| 151 | + #test count of rings |
| 152 | + if row['num_rings']: |
| 153 | + exp_rings = int(row['num_rings']) |
| 154 | + try: |
| 155 | + assert geom.geometry().numInteriorRings() == exp_geometries, "Ring count {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp_geometries, geom.geometry().numInteriorRings()) |
| 156 | + except: |
| 157 | + #some geometry types don't have numInteriorRings() |
| 158 | + assert exp_geometries <= 1, "Ring count {}: Expected:\n{} rings but could not call numInteriorRings()\n".format(i + 1, exp_geometries) |
| 159 | + |
| 160 | + #test geometry centroid |
| 161 | + exp = row['centroid'] |
| 162 | + result = geom.centroid().exportToWkt() |
| 163 | + assert compareWkt(result, exp), "Centroid {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 164 | + |
| 165 | + #test bounding box limits |
| 166 | + bbox = geom.geometry().boundingBox() |
| 167 | + exp = float(row['x_min']) |
| 168 | + result = bbox.xMinimum() |
| 169 | + assert doubleNear(result, exp), "Min X {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 170 | + exp = float(row['y_min']) |
| 171 | + result = bbox.yMinimum() |
| 172 | + assert doubleNear(result, exp), "Min Y {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 173 | + exp = float(row['x_max']) |
| 174 | + result = bbox.xMaximum() |
| 175 | + assert doubleNear(result, exp), "Max X {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 176 | + exp = float(row['y_max']) |
| 177 | + result = bbox.yMaximum() |
| 178 | + assert doubleNear(result, exp), "Max Y {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 179 | + |
| 180 | + #test area calculation |
| 181 | + exp = float(row['area']) |
| 182 | + result = geom.geometry().area() |
| 183 | + assert doubleNear(result, exp), "Area {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 184 | + |
| 185 | + #NOTE - disabled due to misleading length/perimeter calculations for geometry collections |
| 186 | + #exp = float(row['length']) |
| 187 | + #result = geom.geometry().length() |
| 188 | + #assert doubleNear(result, exp), "Length {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 189 | + #exp = float(row['perimeter']) |
| 190 | + #result = geom.geometry().length() |
| 191 | + #assert doubleNear(result, exp), "Length {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result) |
| 192 | + |
135 | 193 | def testArea(self): |
136 | 194 | """ Test area calculations """ |
137 | 195 | with open(os.path.join(TEST_DATA_DIR, 'area_data.csv'), 'r') as d: |
|
0 commit comments