def polygons_to_geometry(self, polygons): """Returns a QgsGeometry object from a list of polygons""" geoms = QgsMultiPolygon() for polygon in polygons: g = self.read_polygon(polygon) geoms.addGeometry(g) return QgsGeometry(geoms)
def convertToPolygons(self, geometry): surfaces = self.getSurfaces(geometry.constGet()) output_wkb = self.convertWkbToPolygons(geometry.wkbType()) out_geom = None if QgsWkbTypes.flatType(output_wkb) == QgsWkbTypes.MultiPolygon: out_geom = QgsMultiPolygon() else: out_geom = QgsMultiSurface() for surface in surfaces: out_geom.addGeometry(surface) return out_geom
def convertToPolygons(self, geometry): surfaces = self.getSurfaces(geometry.constGet()) output_wkb = self.convertWkbToPolygons(geometry.wkbType()) out_geom = None if QgsWkbTypes.flatType(output_wkb) == QgsWkbTypes.MultiPolygon: out_geom = QgsMultiPolygon() else: out_geom = QgsMultiSurface() for surface in surfaces: out_geom.addGeometry(surface) return out_geom
def tzf_to_qgis_polygon(tzdata): if not tzdata or len(tzdata) < 1: return None multi_poly = QgsMultiPolygon() for tzpoly in tzdata: holes = [] poly = QgsPolygon() for x, part in enumerate(tzpoly): if x == 0: outer_ls = QgsLineString(part[0], part[1]) poly.setExteriorRing(outer_ls) else: hole_ls = QgsLineString(part[0], part[1]) holes.append(hole_ls) poly.setInteriorRings(holes) multi_poly.addGeometry(poly) return (QgsGeometry(multi_poly))
def process(self, name, desc, alt_mode, begin, end, when): if self.extDataSize > 0: extAttr = [''] * self.extDataSize for key in self.extendedData.keys(): if key in self.extDataMap: extAttr[self.extDataMap[key]] = self.extendedData[key] # POINTS if len(self.ptPts) != 0: for x, pt in enumerate(self.ptPts): feature = QgsFeature() feature.setGeometry(QgsGeometry(pt)) attr = [ name, self.folderString(), desc, self.ptAltitude[x], alt_mode, begin, end, when ] if self.extDataSize > 0: attr.extend(extAttr) feature.setAttributes(attr) self.addpoint.emit(feature) # LINES - lineStrings is a list of QgsLineString if len(self.lineStrings) != 0: feature = QgsFeature() if len(self.lineStrings) == 1: feature.setGeometry(QgsGeometry(self.lineStrings[0])) else: g = QgsMultiLineString() for lineStr in self.lineStrings: g.addGeometry(lineStr) feature.setGeometry(QgsGeometry(g)) attr = [ name, self.folderString(), desc, 0, alt_mode, begin, end, when ] if self.extDataSize > 0: attr.extend(extAttr) feature.setAttributes(attr) self.addline.emit(feature) # POLYGONS if len(self.polygons) != 0: feature = QgsFeature() if len(self.polygons) == 1: feature.setGeometry(QgsGeometry(self.polygons[0])) else: g = QgsMultiPolygon() for poly in self.polygons: g.addGeometry(poly) feature.setGeometry(QgsGeometry(g)) attr = [ name, self.folderString(), desc, 0, alt_mode, begin, end, when ] if self.extDataSize > 0: attr.extend(extAttr) feature.setAttributes(attr) self.addpolygon.emit(feature)
def splitPolygon(self, geom): z_func = lambda x, y: self.valueOnSurface(x, y) or 0 cache = FunctionCacheXY(z_func) z_func = cache.func polygons = QgsMultiPolygon() for poly in self._splitPolygon(geom): p = QgsPolygon() ring = QgsLineString() for pt in poly[0]: ring.addVertex(QgsPoint(pt.x(), pt.y(), z_func(pt.x(), pt.y()))) p.setExteriorRing(ring) for bnd in poly[1:]: ring = QgsLineString() for pt in bnd: ring.addVertex(QgsPoint(pt.x(), pt.y(), z_func(pt.x(), pt.y()))) p.addInteriorRing(ring) polygons.addGeometry(p) return QgsGeometry(polygons)
def get_constraint_geometry(self): """Returns the geometry from the constraint layer and rule :return: the constraint geometry and the number of matched records :rtype: tuple( MultiPolygon, integer) """ constraint_layer = get_qgis_layer(self.constraint.constraint_layer) layer = get_qgis_layer(self.constraint.layer) # Get the geometries from constraint layer and rule qgis_feature_request = QgsFeatureRequest() qgis_feature_request.setFilterExpression(self.rule) features = get_qgis_features(constraint_layer, qgis_feature_request, exclude_fields='__all__') if not features: return '', 0 geometry = QgsMultiPolygon() for feature in features: geom = feature.geometry() if geom.isMultipart(): geom = [g for g in geom.constGet()] else: geom = [geom.constGet()] i = 0 for g in geom: geometry.insertGeometry(g.clone(), 0) i += 1 # Now, transform into a GEOS geometry if constraint_layer.crs() != layer.crs(): ct = QgsCoordinateTransform( QgsCoordinateReferenceSystem(constraint_layer.crs()), QgsCoordinateReferenceSystem(layer.crs()), QgsCoordinateTransformContext()) geometry.transform(ct) constraint_geometry = MultiPolygon.from_ewkt( 'SRID=%s;' % layer.crs().postgisSrid() + geometry.asWkt()) return constraint_geometry, constraint_geometry.num_geom
def getRings(self, geometry): rings = [] # TODO: remove when the error is resolved # Error: The expected object type is a QgsCurvePolygon but it receives a QgsPoint, however the WKT of the # QgsPoint corresponds to either a QgsPolygon or QgsMultiPolygon (yeap, it must be a bug in QGIS) if type(geometry) == QgsPoint or type(geometry) == QgsLineString: geom = QgsGeometry().fromWkt(geometry.asWkt()) curve = None if geom.isMultipart(): curve = QgsMultiPolygon() curve.fromWkt(geom.asWkt()) else: curve = QgsPolygon() curve.fromWkt(geom.asWkt()) geometry = curve.toCurveType() if isinstance(geometry, QgsGeometryCollection): # collection for i in range(geometry.numGeometries()): if QgsWkbTypes.geometryType(geometry.geometryN( i).wkbType()) == QgsWkbTypes.PolygonGeometry: rings.extend(self.getRings(geometry.geometryN(i))) else: # Converts geometry to curve, because exteriorRing is a method from curve polygons if isinstance(geometry, QgsPolygon): geom = geometry.toCurveType() geometry = geom # not collection rings.append(geometry.exteriorRing().clone()) for i in range(geometry.numInteriorRings()): rings.append(geometry.interiorRing(i).clone()) return rings
def txestGeometryRendering(self): '''Tests rendering a bunch of different geometries, including bad/odd geometries.''' empty_multipolygon = QgsMultiPolygon() empty_multipolygon.addGeometry(QgsPolygon()) empty_polygon = QgsPolygon() empty_linestring = QgsLineString() tests = [ { 'name': 'Point', 'wkt': 'Point (1 2)', 'reference_image': 'point' }, { 'name': 'MultiPoint', 'wkt': 'MultiPoint ((10 30),(40 20),(30 10),(20 10))', 'reference_image': 'multipoint' }, { 'name': 'LineString', 'wkt': 'LineString (0 0,3 4,4 3)', 'reference_image': 'linestring' }, { 'name': 'Empty LineString', 'geom': QgsGeometry(empty_linestring), 'reference_image': 'empty' }, { 'name': 'MultiLineString', 'wkt': 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 1, 5 1, 5 0, 6 0))', 'reference_image': 'multilinestring' }, { 'name': 'Polygon', 'wkt': 'Polygon ((0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5))', 'reference_image': 'polygon' }, { 'name': 'Empty Polygon', 'geom': QgsGeometry(empty_polygon), 'reference_image': 'empty' }, { 'name': 'MultiPolygon', 'wkt': 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))', 'reference_image': 'multipolygon' }, { 'name': 'Empty MultiPolygon', 'geom': QgsGeometry(empty_multipolygon), 'reference_image': 'empty' }, { 'name': 'CircularString', 'wkt': 'CIRCULARSTRING(268 415,227 505,227 406)', 'reference_image': 'circular_string' }, { 'name': 'CompoundCurve', 'wkt': 'COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))', 'reference_image': 'compound_curve' }, { 'name': 'CurvePolygon', 'wkt': 'CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3))', 'reference_image': 'curve_polygon' }, { 'name': 'MultiCurve', 'wkt': 'MultiCurve((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0, 2 1,2 2))', 'reference_image': 'multicurve' }, { 'name': 'CurvePolygon_no_arc', # refs #14028 'wkt': 'CURVEPOLYGON(LINESTRING(1 3, 3 5, 4 7, 7 3, 1 3))', 'reference_image': 'curve_polygon_no_arc' } ] for test in tests: def get_geom(): if 'geom' not in test: geom = QgsGeometry.fromWkt(test['wkt']) assert geom and not geom.isNull( ), 'Could not create geometry {}'.format(test['wkt']) else: geom = test['geom'] return geom geom = get_geom() rendered_image = self.renderGeometry(geom) assert self.imageCheck(test['name'], test['reference_image'], rendered_image) # Note - each test is repeated with the same geometry and reference image, but with added # z and m dimensions. This tests that presence of the dimensions does not affect rendering # test with Z geom_z = get_geom() geom_z.get().addZValue(5) rendered_image = self.renderGeometry(geom_z) assert self.imageCheck(test['name'] + 'Z', test['reference_image'], rendered_image) # test with ZM geom_z.get().addMValue(15) rendered_image = self.renderGeometry(geom_z) assert self.imageCheck(test['name'] + 'ZM', test['reference_image'], rendered_image) # test with M geom_m = get_geom() geom_m.get().addMValue(15) rendered_image = self.renderGeometry(geom_m) assert self.imageCheck(test['name'] + 'M', test['reference_image'], rendered_image)
def get_inner_rings_layer(self, plot_layer, id_field=ID_FIELD, use_selection=False): id_field_idx = plot_layer.fields().indexFromName(id_field) request = QgsFeatureRequest().setSubsetOfAttributes([id_field_idx]) polygons = plot_layer.getSelectedFeatures( request) if use_selection else plot_layer.getFeatures(request) layer = QgsVectorLayer("LineString?crs=EPSG:{}".format(DEFAULT_EPSG), "rings", "memory") data_provider = layer.dataProvider() data_provider.addAttributes([QgsField(ID_FIELD, QVariant.Int)]) layer.updateFields() features = [] for polygon in polygons: polygon_geom = polygon.geometry() is_multipart = polygon_geom.isMultipart() # Does the current multipolygon have inner rings? has_inner_rings = False multi_polygon = None single_polygon = None if is_multipart: multi_polygon = polygon_geom.constGet() # TODO: remove when the error is resolved if type(multi_polygon) != QgsMultiPolygon: geom = QgsMultiPolygon() geom.fromWkt(polygon_geom.asWkt()) multi_polygon = geom for part in range(multi_polygon.numGeometries()): if multi_polygon.ringCount(part) > 1: has_inner_rings = True break else: single_polygon = polygon_geom.constGet() # TODO: remove when the error is resolved if type(single_polygon) != QgsPolygon: geom = QgsPolygon() geom.fromWkt(polygon_geom.asWkt()) single_polygon = geom if single_polygon.numInteriorRings() > 0: has_inner_rings = True if has_inner_rings: if is_multipart and multi_polygon: for i in range(multi_polygon.numGeometries()): temp_polygon = multi_polygon.geometryN(i) # TODO: remove when the error is resolved if type(temp_polygon) != QgsPolygon: geom = QgsPolygon() geom.fromWkt(temp_polygon.asWkt()) temp_polygon = geom for j in range(temp_polygon.numInteriorRings()): new_feature = QgsVectorLayerUtils().createFeature( layer, QgsGeometry( temp_polygon.interiorRing(j).clone()), {0: polygon[id_field]}) features.append(new_feature) elif not is_multipart and single_polygon: for j in range(single_polygon.numInteriorRings()): new_feature = QgsVectorLayerUtils().createFeature( layer, QgsGeometry( single_polygon.interiorRing(j).clone()), {0: polygon[id_field]}) features.append(new_feature) layer.dataProvider().addFeatures(features) layer.updateExtents() layer.reload() return layer
def txestGeometryRendering(self): '''Tests rendering a bunch of different geometries, including bad/odd geometries.''' empty_multipolygon = QgsMultiPolygon() empty_multipolygon.addGeometry(QgsPolygon()) empty_polygon = QgsPolygon() empty_linestring = QgsLineString() tests = [{'name': 'Point', 'wkt': 'Point (1 2)', 'reference_image': 'point'}, {'name': 'MultiPoint', 'wkt': 'MultiPoint ((10 30),(40 20),(30 10),(20 10))', 'reference_image': 'multipoint'}, {'name': 'LineString', 'wkt': 'LineString (0 0,3 4,4 3)', 'reference_image': 'linestring'}, {'name': 'Empty LineString', 'geom': QgsGeometry(empty_linestring), 'reference_image': 'empty'}, {'name': 'MultiLineString', 'wkt': 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 1, 5 1, 5 0, 6 0))', 'reference_image': 'multilinestring'}, {'name': 'Polygon', 'wkt': 'Polygon ((0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5))', 'reference_image': 'polygon'}, {'name': 'Empty Polygon', 'geom': QgsGeometry(empty_polygon), 'reference_image': 'empty'}, {'name': 'MultiPolygon', 'wkt': 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))', 'reference_image': 'multipolygon'}, {'name': 'Empty MultiPolygon', 'geom': QgsGeometry(empty_multipolygon), 'reference_image': 'empty'}, {'name': 'CircularString', 'wkt': 'CIRCULARSTRING(268 415,227 505,227 406)', 'reference_image': 'circular_string'}, {'name': 'CompoundCurve', 'wkt': 'COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))', 'reference_image': 'compound_curve'}, {'name': 'CurvePolygon', 'wkt': 'CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3))', 'reference_image': 'curve_polygon'}, {'name': 'MultiCurve', 'wkt': 'MultiCurve((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0, 2 1,2 2))', 'reference_image': 'multicurve'}, {'name': 'CurvePolygon_no_arc', # refs #14028 'wkt': 'CURVEPOLYGON(LINESTRING(1 3, 3 5, 4 7, 7 3, 1 3))', 'reference_image': 'curve_polygon_no_arc'}] for test in tests: def get_geom(): if 'geom' not in test: geom = QgsGeometry.fromWkt(test['wkt']) assert geom and not geom.isNull(), 'Could not create geometry {}'.format(test['wkt']) else: geom = test['geom'] return geom geom = get_geom() rendered_image = self.renderGeometry(geom) assert self.imageCheck(test['name'], test['reference_image'], rendered_image) # Note - each test is repeated with the same geometry and reference image, but with added # z and m dimensions. This tests that presence of the dimensions does not affect rendering # test with Z geom_z = get_geom() geom_z.get().addZValue(5) rendered_image = self.renderGeometry(geom_z) assert self.imageCheck(test['name'] + 'Z', test['reference_image'], rendered_image) # test with ZM geom_z.get().addMValue(15) rendered_image = self.renderGeometry(geom_z) assert self.imageCheck(test['name'] + 'ZM', test['reference_image'], rendered_image) # test with M geom_m = get_geom() geom_m.get().addMValue(15) rendered_image = self.renderGeometry(geom_m) assert self.imageCheck(test['name'] + 'M', test['reference_image'], rendered_image)
def createGeom(self, coords): crsDest = self.__layer.crs() rc = ReprojectCoordinates(self.crsId, crsDest.srsid(), self.__hasZ, self.__hasM) if self.crsId != crsDest.srsid(): coordsPoint = list(rc.reproject(coords, True)) else: coordsPoint = list(rc.copyCoordstoPoints(coords)) # Point and multipoint Geometry # Always 1 part, 0 element of matrix if self.__layergeometryType == QgsWkbTypes.PointGeometry: if self.__isMultiType: multipoint = QgsMultiPoint() for coords_item in coordsPoint[0][1]: multipoint.addGeometry(coords_item) geom = QgsGeometry(multipoint) self.createFeature(geom) else: geom = QgsGeometry(coordsPoint[0][1][0]) self.createFeature(geom) elif self.__layergeometryType == QgsWkbTypes.LineGeometry: if self.__isMultiType: multiline = QgsGeometry(QgsMultiLineString()) for j in range(len(coordsPoint)): line = QgsLineString(coordsPoint[j][1]) multiline.addPart(line) self.createFeature(multiline) else: line = QgsGeometry(QgsLineString(coordsPoint[0][1])) self.createFeature(line) elif self.__layergeometryType == QgsWkbTypes.PolygonGeometry: if self.__isMultiType: multipoly = QgsGeometry(QgsMultiPolygon()) for i in range(len(coordsPoint)): if int(coordsPoint[i][0]) > 0: mycurve = QgsLineString(coordsPoint[i][1]) poly = QgsPolygon() poly.setExteriorRing(mycurve) polyGeometry = QgsGeometry(QgsPolygon(poly)) for j in range(len(coordsPoint)): if int(coordsPoint[j][0]) < 0: containsAllPoints = True for k in range(len(coordsPoint[j][1])): containsAllPoints = True curPoint = coordsPoint[j][1][k].clone() containsAllPoints = containsAllPoints \ and polyGeometry.contains(QgsPointXY(curPoint.x(), curPoint.y())) if containsAllPoints: mycurve = QgsLineString(coordsPoint[j][1]) poly.addInteriorRing(mycurve) multipoly.addPart(poly) self.createFeature(multipoly) else: extRing = 0 for i in range(len(coordsPoint)): if int(coordsPoint[i][0]) > 0: extRing = i mycurve = QgsLineString(coordsPoint[extRing][1]) poly = QgsPolygon() poly.setExteriorRing(mycurve) polyGeometry = QgsGeometry(QgsPolygon(poly)) for i in range(len(coordsPoint)): if int(coordsPoint[i][0]) < 0: containsAllPoints = True for j in range(len(coordsPoint[i][1])): containsAllPoints = True curPoint = coordsPoint[i][1][j].clone() containsAllPoints = containsAllPoints \ and polyGeometry.contains(QgsPointXY(curPoint.x(), curPoint.y())) if containsAllPoints: mycurve = QgsLineString(coordsPoint[i][1]) poly.addInteriorRing(mycurve) else: QMessageBox.question(self.iface.mainWindow(), self.translate_str("Ring not in exterior contour"), self.translate_str("The new geometry of the feature" " isn't valid. Do you want to use it anyway?"), QMessageBox.Yes, QMessageBox.No) self.createFeature(QgsGeometry(poly))