def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.POLYGONS, context) parts = self.parameterAsInt(parameters, self.PARTS, context) fields = source.fields() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), source.wkbType(), source.sourceCrs()) features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, feat in enumerate(features): if feedback.isCanceled(): break geom = feat.geometry() if geom.isMultipart(): out_feature = feat geoms = geom.asGeometryCollection() geom_area = [(i, geoms[i].area()) for i in range(len(geoms))] geom_area.sort(key=itemgetter(1)) if parts == 1: out_feature.setGeometry(geoms[geom_area[-1][0]]) elif parts > len(geoms): out_feature.setGeometry(geom) else: out_feature.setGeometry(geom) geomres = [geoms[i].asPolygon() for i, a in geom_area[-1 * parts:]] out_feature.setGeometry(QgsGeometry.fromMultiPolygonXY(geomres)) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) else: sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def addResultToLayer(self, layer, result, lyrDefault, mode): if len(result) > 0: layer.startEditing() feats = [] if lyrDefault is True: bbox = QgsRectangle() bbox.setMinimal() for res in result: feat = QgsFeature() if mode == 'web': feat.setGeometry( QgsGeometry.fromMultiPolygonXY(res["geom"])) else: feat.setGeometry(QgsGeometry.fromWkt(res["wkt"])) feat.setAttributes([ res["id"], res["partido"], res["partida"], res["nomenclatura"], res["codigo"], res["layer"] ]) feats.append(feat) if lyrDefault is True: bbox.combineExtentWith(feat.geometry().boundingBox()) layer.dataProvider().addFeatures(feats) layer.commitChanges() layer.updateExtents() if lyrDefault is True: self.canvas.setExtent(self.setBboxMap(bbox, layer)) else: self.canvas.setExtent(self.setBboxMap(layer.extent(), layer))
def creator_geometry_changed(self, qgsfId, geom): """ Called when feature is changed @param qgsfId: Id of added feature @type qgsfId: qgis.core.QgsFeature.QgsFeatureId @param geom: geometry of added feature @type geom: qgis.core.QgsGeometry """ if qgsfId in self.added_building_ids: if geom.wkbType() == QgsWkbTypes.Polygon: geom = QgsGeometry.fromMultiPolygonXY([geom.asPolygon()]) wkt = geom.asWkt() if not wkt: self.disable_UI_functions() self.geom = None return sql = general_select.convert_geometry result = self.db.execute_return(sql, (wkt, )) self.geom = result.fetchall()[0][0] else: self.error_dialog = ErrorDialog() self.error_dialog.fill_report( "\n -------------------- WRONG GEOMETRY EDITED ------" "-------------- \n\nOnly current added outline can " "be edited. Please go to [Edit Geometry] to edit " "existing outlines.") self.error_dialog.show()
def saveParcel(self): if not self.layernameValid(): return municipality = self.ui.municipalityCbx.currentText() department = self.ui.departmentCbx.currentText() niscodes = [ n['municipalityCode'] for n in self.municipalities if n['municipalityName'] == municipality ] niscode = (niscodes[0] if len(niscodes) else '') departmentcodes = [ n['departmentCode'] for n in self.departments if n['departmentName'] == department ] departmentcode = (departmentcodes[0] if len(departmentcodes) else '') section = self.ui.sectionCbx.currentText() parcelNr = self.ui.parcelCbx.currentText() if '' in (niscode, departmentcode, section, parcelNr): return parcelInfo = self.parcel.getParcel(niscode, departmentcode, section, parcelNr, 31370, 'full') geojson = self.perc.getPercGeom(parcelInfo['capakey']) if len(geojson['features']) > 0: shape = geojson['features'][0]['geometry'] else: shape = json.loads(parcelInfo['geometry']['shape']) pts = [n.asPolygon() for n in self.PolygonsFromJson(shape)] mPolygon = QgsGeometry.fromMultiPolygonXY(pts) self.ph.save_parcel_polygon( mPolygon, parcelInfo, self.layerName, self.saveToFile, self, os.path.join(self.startDir, self.layerName))
def qgsgeom_from_mpl_collec(collections): polygons = [] for i, polygon in enumerate(collections): mpoly = [] for path in polygon.get_paths(): path.should_simplify = False poly = path.to_polygons() if len(poly) > 0 and len(poly[0]) > 3: exterior = [QgsPointXY(*p.tolist()) for p in poly[0]] holes = [[QgsPointXY(*p.tolist()) for p in h] for h in poly[1:] if len(h) > 3] if len(holes) == 1: mpoly.append([exterior, holes[0]]) elif len(holes) > 1: mpoly.append([exterior] + [h for h in holes]) else: mpoly.append([exterior]) if len(mpoly) == 1: polygons.append(QgsGeometry.fromPolygonXY(mpoly[0])) elif len(mpoly) > 1: polygons.append(QgsGeometry.fromMultiPolygonXY(mpoly)) else: polygons.append(QgsGeometry.fromPolygonXY([])) return polygons
def splitPolygon(self, geom): xmin, ymax, xres, yres = self.xmin, self.ymax, self.xres, self.yres polygons = [] for x, vi in self.vSplit(geom): for y in self.hIntersects(vi): pt0 = QgsPointXY(xmin + x * xres, ymax - y * yres) pt1 = QgsPointXY(xmin + x * xres, ymax - (y + 1) * yres) pt2 = QgsPointXY(xmin + (x + 1) * xres, ymax - (y + 1) * yres) pt3 = QgsPointXY(xmin + (x + 1) * xres, ymax - y * yres) quad = QgsGeometry.fromPolygonXY([[pt0, pt1, pt2, pt3, pt0]]) tris = [[[pt0, pt1, pt3, pt0]], [[pt3, pt1, pt2, pt3]]] if geom.contains(quad): polygons += tris else: for i, tri in enumerate( map(QgsGeometry.fromPolygonXY, tris)): if geom.contains(tri): polygons.append(tris[i]) elif geom.intersects(tri): poly = geom.intersection(tri) if poly.isMultipart(): polygons += poly.asMultiPolygon() else: polygons.append(poly.asPolygon()) return QgsGeometry.fromMultiPolygonXY(polygons)
def _swap_qgs_geometry(qgsgeom): if qgsgeom.wkbType() == QgsWkbTypes.Point: p = qgsgeom.asPoint() qgsgeom = QgsGeometry.fromPointXY(QgsPointXY(p[1], p[0])) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPoint: mp = qgsgeom.asMultiPoint() qgsgeom = QgsGeometry.fromMultiPointXY( [QgsPointXY(p[1], p[0]) for p in mp]) elif qgsgeom.wkbType() == QgsWkbTypes.LineString: pl = qgsgeom.asPolyline() qgsgeom = QgsGeometry.fromPolylineXY( [QgsPointXY(p[1], p[0]) for p in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiLineString: mls = qgsgeom.asMultiPolyline() qgsgeom = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p[1], p[0]) for p in pl] for pl in mls]) elif qgsgeom.wkbType() == QgsWkbTypes.Polygon: pl = qgsgeom.asPolygon() qgsgeom = QgsGeometry.fromPolygonXY( [[QgsPointXY(p[1], p[0]) for p in r] for r in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPolygon: mp = qgsgeom.asMultiPolygon() qgsgeom = QgsGeometry.fromMultiPolygonXY( [[[QgsPointXY(p[1], p[0]) for p in r] for r in pl] for pl in mp]) return qgsgeom
def reprojectPoints(self, geom, xform): if geom.type() == 0: #Point if geom.isMultipart(): pnts = geom.asMultiPoint() newPnts = [] for pnt in pnts: newPnts += [xform.transform(pnt)] newGeom = QgsGeometry.fromMultiPointXY(newPnts) return newGeom else: pnt = geom.asPoint() newPnt = xform.transform(pnt) newGeom = QgsGeometry.fromPointXY(newPnt) return newGeom elif geom.type() == 1: #Line if geom.isMultipart(): linhas = geom.asMultiPolyline() newLines = [] for linha in linhas: newLine = [] for pnt in linha: newLine += [xform.transform(pnt)] newLines += [newLine] newGeom = QgsGeometry.fromMultiPolylineXY(newLines) return newGeom else: linha = geom.asPolyline() newLine = [] for pnt in linha: newLine += [xform.transform(pnt)] newGeom = QgsGeometry.fromPolylineXY(newLine) return newGeom elif geom.type() == 2: #Polygon if geom.isMultipart(): poligonos = geom.asMultiPolygon() newPolygons = [] for pol in poligonos: newPol = [] for anel in pol: newAnel = [] for pnt in anel: newAnel += [xform.transform(pnt)] newPol += [newAnel] newPolygons += [newPol] newGeom = QgsGeometry.fromMultiPolygonXY(newPolygons) return newGeom else: pol = geom.asPolygon() newPol = [] for anel in pol: newAnel = [] for pnt in anel: newAnel += [xform.transform(pnt)] newPol += [newAnel] newGeom = QgsGeometry.fromPolygonXY(newPol) return newGeom else: return None
def flipFeature(self, layer, feature, geomType=None, refreshCanvas=False): """ Inverts the flow from a given feature. THE GIVEN FEATURE IS ALTERED. Standard behaviour is to not refresh canvas map. :param layer: layer containing the target feature for flipping. :param feature: feature to be flipped. :param geomType: if layer geometry type is not given, it'll calculate it (0,1 or 2) :param refreshCanvas: indicates whether the canvas should be refreshed after flipping feature. :returns: flipped feature as of [layer, feature, geometry_type]. """ if not geomType: geomType = layer.geometryType() # getting whether geometry is multipart or not # features not yet commited to layer always have SINGLE geometry isMulti = QgsWkbTypes.isMultiType(int( layer.wkbType())) and feature.id() > 0 geom = feature.geometry() if geomType == 0: if isMulti: nodes = geom.asMultiPoint() # inverting the point list by parts for idx, part in enumerate(nodes): nodes[idx] = part[::-1] # setting flipped geometry flippedFeatureGeom = QgsGeometry.fromMultiPointXY(nodes) else: # inverting the point list nodes = geom.asPoint() nodes = nodes[::-1] flippedFeatureGeom = QgsGeometry.fromPoint(nodes) elif geomType == 1: if isMulti: nodes = geom.asMultiPolyline() for idx, part in enumerate(nodes): nodes[idx] = part[::-1] flippedFeatureGeom = QgsGeometry.fromMultiPolylineXY(nodes) else: nodes = geom.asPolyline() nodes = nodes[::-1] flippedFeatureGeom = QgsGeometry.fromPolylineXY(nodes) elif geomType == 2: if isMulti: nodes = geom.asMultiPolygon() for idx, part in enumerate(nodes): nodes[idx] = part[::-1] flippedFeatureGeom = QgsGeometry.fromMultiPolygonXY(nodes) else: nodes = geom.asPolygon() nodes = nodes[::-1] flippedFeatureGeom = QgsGeometry.fromPolygonXY(nodes) # setting feature geometry to the flipped one # feature.setGeometry(flippedFeatureGeom) # layer.updateFeature(feature) layer.changeGeometry(feature.id(), flippedFeatureGeom) if refreshCanvas: self.iface.mapCanvas().refresh() return [layer, feature, geomType]
def toQgsGeometry(self): count = len(self.polygons) if count > 1: polys = [polygonToQgsPolygon(poly) for poly in self.polygons] return QgsGeometry.fromMultiPolygonXY(polys) if count == 1: return QgsGeometry.fromPolygonXY(polygonToQgsPolygon(self.polygons[0])) return QgsGeometry()
def getGeometry(geometry): def getPolygonPoints(coordinates): polylines = [] for line in coordinates: polyline = [QgsPointXY(p[0], p[1]) for p in line] polylines.append(polyline) return polylines if geometry['type'] == 'Polygon': polygon = getPolygonPoints(geometry['coordinates']) return QgsGeometry.fromMultiPolygonXY([polygon]) elif geometry['type'] == 'MultiPolygon': polygons = [] for polygon in geometry['coordinates']: polygons.append(getPolygonPoints(polygon)) return QgsGeometry.fromMultiPolygonXY(polygons) else: None
def _process_feature(self, source_feature, made_progress=False): if QThread.currentThread().isInterruptionRequested(): self.__commit() self.interrupted.emit(self.layer_found, self.layer_not_found) self.layer_found.stopEditing() return point = source_feature.geometry().asPoint() if self.parcels_geometry.contains(point): if made_progress: self.__commit() self.progressed.emit(self.layer_found, self.layer_not_found, True, 1, False, made_progress) return uldk_point = ULDKPoint(point.x(), point.y(), 2180) found_parcels_geometries = [] saved = False try: uldk_response_row = self.uldk_search.search(uldk_point) additional_attributes = [] for field in self.additional_output_fields: additional_attributes.append(source_feature[field.name()]) try: found_feature = uldk_response_to_qgs_feature( uldk_response_row, additional_attributes) geometry_wkt = found_feature.geometry().asWkt() except BadGeometryException: raise BadGeometryException("Niepoprawna geometria") if geometry_wkt not in self.geometries: saved = True self.layer_found.dataProvider().addFeature(found_feature) self.geometries.append(geometry_wkt) found_parcels_geometries.append( found_feature.geometry().asPolygon()) self.progressed.emit(self.layer_found, self.layer_not_found, True, 0, saved, made_progress) except Exception as e: geometry = source_feature.geometry() geometry_wkt = geometry.asWkt() if geometry_wkt not in self.not_found_geometries: not_found_feature = self.__make_not_found_feature(geometry, e) self.layer_not_found.dataProvider().addFeature( not_found_feature) self.progressed.emit(self.layer_found, self.layer_not_found, False, 0, saved, made_progress) self.not_found_geometries.append(geometry_wkt) self.parcels_geometry.addPartGeometry( QgsGeometry.fromMultiPolygonXY(found_parcels_geometries)) self.__commit() return saved
def testQgsMultipolygonRepr(self): mp = QgsGeometry.fromMultiPolygonXY([ [[QgsPointXY(1, 1), QgsPointXY(2, 2), QgsPointXY(1, 2), QgsPointXY(1, 1)]], [[QgsPointXY(2, 2), QgsPointXY(3, 3), QgsPointXY(3, 1), QgsPointXY(2, 2)]] ]) self.assertEqual(mp.constGet().__repr__(), '<QgsMultiPolygon: MultiPolygon (((1 1, 2 2, 1 2, 1 1)),((2 2, 3 3, 3 1, 2 2)))>')
def TestQgsMultipolygonRepr(self): mp = QgsGeometry.fromMultiPolygonXY([ [[QgsPointXY(1, 1), QgsPointXY(2, 2), QgsPointXY(1, 2), QgsPointXY(1, 1)]], [[QgsPointXY(2, 2), QgsPointXY(3, 3), QgsPointXY(3, 1), QgsPointXY(2, 2)]] ]) self.assertEqual(mp.constGet().__repr__(), '<QgsMultiPolygon: MultiPolygon (((1 1, 2 2, 1 2, 1 1)),((2 2, 3 3, 3 1, 2 2)))>')
def toQgsGeometry(self, polygons=None): if polygons is None: polygons = self.polygons count = len(polygons) if count > 1: polys = [[[QgsPointXY(x, y) for x, y, z in bnd] for bnd in poly] for poly in polygons] return QgsGeometry.fromMultiPolygonXY(polys) if count == 1: poly = [[QgsPointXY(x, y) for x, y, z in bnd] for bnd in polygons[0]] return QgsGeometry.fromPolygonXY(poly) return QgsGeometry()
def _feature_to_points(self, feature, geom_type, additional_attributes): geometry = feature.geometry() if QgsWkbTypes.hasZ(geom_type): geometry, geom_type = self.drop_z_from_geom(geometry, geom_type) features = [] points_number = 0 if self.transformation is not None: geometry.transform(self.transformation) if geom_type == QgsWkbTypes.LineString or geom_type == QgsWkbTypes.MultiLineString: points_number = 10 geometry = geometry.buffer(0.001, 2) if self.parcels_geometry: if self.parcels_geometry.contains(geometry): return [] else: if not geometry.isMultipart(): geometry.convertToMultiType() multi_polygon = QgsGeometry.fromMultiPolygonXY( geometry.asMultiPolygon()) geometry = multi_polygon.difference( self.parcels_geometry.buffer(0.001, 2)) if not geometry: return [] da = QgsDistanceArea() da.setSourceCrs(CRS_2180, QgsProject.instance().transformContext()) da.setEllipsoid(QgsProject.instance().ellipsoid()) points_number = 20 if not points_number else points_number area = int(da.measureArea(geometry)) / 10000 if area > 1: points_number *= area points = geometry.randomPointsInPolygon(points_number) for point in points: feature = QgsFeature() if additional_attributes: feature.setFields(self.fields_to_add) feature.setAttributes(additional_attributes) feature.setGeometry(QgsGeometry.fromPointXY(point)) features.append(feature) return features
def parse_feature_response(self, response): if response.status_code != 200: if not isinstance(response.exception, RequestsExceptionUserAbort): self.info("Error in feature response with status code: " "{} from {}".format(response.status_code, response.url)) return data = json.loads(response.content.decode('utf-8')) self.dbg_info(data.keys()) self.dbg_info(data['properties']) self.dbg_info(data['geometry']) self.dbg_info(data['crs']) self.dbg_info(data['type']) assert data['crs']['properties'][ 'name'] == 'urn:ogc:def:crs:EPSG::2056' geometry_type = data['geometry']['type'] geometry = QgsGeometry() if geometry_type.lower() == 'point': geometry = QgsGeometry.fromPointXY( QgsPointXY(data['geometry']['coordinates'][0], data['geometry']['coordinates'][1])) elif geometry_type.lower() == 'polygon': rings = data['geometry']['coordinates'] for r in range(0, len(rings)): for p in range(0, len(rings[r])): rings[r][p] = QgsPointXY(rings[r][p][0], rings[r][p][1]) geometry = QgsGeometry.fromPolygonXY(rings) elif geometry_type.lower() == 'multipolygon': islands = data['geometry']['coordinates'] for i in range(0, len(islands)): for r in range(0, len(islands[i])): for p in range(0, len(islands[i][r])): islands[i][r][p] = QgsPointXY(islands[i][r][p][0], islands[i][r][p][1]) geometry = QgsGeometry.fromMultiPolygonXY(islands) else: # SoLocator does not handle {geometry_type} yet. Please contact support self.info( 'SoLocator unterstützt den Geometrietyp {geometry_type} nicht.' ' Bitte kontaktieren Sie den Support.'.format( geometry_type=geometry_type), Qgis.Warning) geometry.transform(self.transform_ch) self.highlight(geometry)
def transform(self, meta_features, force_reduction_factor, geometry): """Transform the geometry based on the force reduction factor.""" if geometry.isMultipart(): geometries = [] for polygon in geometry.asMultiPolygon(): new_polygon = self.transform_polygon(polygon, meta_features, force_reduction_factor) geometries.append(new_polygon) return QgsGeometry.fromMultiPolygonXY(geometries) else: polygon = geometry.asPolygon() new_polygon = self.transform_polygon(polygon, meta_features, force_reduction_factor) return QgsGeometry.fromPolygon(new_polygon)
def testMeasureMultiPolygon(self): # +-+-+ +-+-+ # | | | | # + +-+ +-+ + # | | | | # +-+ +-+ polygon = QgsGeometry.fromMultiPolygonXY( [ [[QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0), ]], [[QgsPointXY(4, 0), QgsPointXY(5, 0), QgsPointXY(5, 2), QgsPointXY(3, 2), QgsPointXY(3, 1), QgsPointXY(4, 1), QgsPointXY(4, 0), ]] ] ) da = QgsDistanceArea() area = da.measureArea(polygon) assert area == 6, 'Expected:\n%f\nGot:\n%f\n' % (6, area) perimeter = da.measurePerimeter(polygon) assert perimeter == 16, "Expected:\n%f\nGot:\n%f\n" % (16, perimeter)
def find_geometry(self, g): if self.output_type == "Poly": stat = g.area() if g.isMultipart(): geometry = QgsGeometry.fromMultiPolygonXY(g.asMultiPolygon()) else: geometry = QgsGeometry.fromPolygonXY(g.asPolygon()) elif self.output_type == "Line": stat = g.length() if g.isMultipart(): geometry = QgsGeometry.fromMultiPolylineXY(g.asMultiPolyLine()) else: geometry = QgsGeometry.fromPolyline(g.asPoly()) else: stat = 1 if g.isMultipart(): geometry = QgsGeometry.fromMultiPointXY(g.asMultiPoint()) else: geometry = QgsGeometry.fromPointXY(g.asPoint()) return geometry, stat
def _swap_qgs_geometry(qgsgeom): if qgsgeom.wkbType() == QgsWkbTypes.Point: p = qgsgeom.asPoint() qgsgeom = QgsGeometry.fromPointXY(QgsPointXY(p[1], p[0])) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPoint: mp = qgsgeom.asMultiPoint() qgsgeom = QgsGeometry.fromMultiPointXY([QgsPointXY(p[1], p[0]) for p in mp]) elif qgsgeom.wkbType() == QgsWkbTypes.LineString: pl = qgsgeom.asPolyline() qgsgeom = QgsGeometry.fromPolylineXY([QgsPointXY(p[1],p[0]) for p in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiLineString: mls = qgsgeom.asMultiPolyline() qgsgeom = QgsGeometry.fromMultiPolylineXY([[QgsPointXY(p[1],p[0]) for p in pl] for pl in mls]) elif qgsgeom.wkbType() == QgsWkbTypes.Polygon: pl = qgsgeom.asPolygon() qgsgeom = QgsGeometry.fromPolygonXY([[QgsPointXY(p[1],p[0]) for p in r] for r in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPolygon: mp = qgsgeom.asMultiPolygon() qgsgeom = QgsGeometry.fromMultiPolygonXY([[[QgsPointXY(p[1],p[0]) for p in r] for r in pl] for pl in mp]) return qgsgeom
def makeQgsPolygonFromBounds(self, xmin, ymin, xmax, ymax, isMulti=True): """ Creating a polygon for the given coordinates """ dx = (xmax - xmin) / 3 dy = (ymax - ymin) / 3 polyline = [] point = QgsPointXY(xmin, ymin) polyline.append(point) point = QgsPointXY(xmin + dx, ymin) polyline.append(point) point = QgsPointXY(xmax - dx, ymin) polyline.append(point) point = QgsPointXY(xmax, ymin) polyline.append(point) point = QgsPointXY(xmax, ymin + dy) polyline.append(point) point = QgsPointXY(xmax, ymax - dy) polyline.append(point) point = QgsPointXY(xmax, ymax) polyline.append(point) point = QgsPointXY(xmax - dx, ymax) polyline.append(point) point = QgsPointXY(xmin + dx, ymax) polyline.append(point) point = QgsPointXY(xmin, ymax) polyline.append(point) point = QgsPointXY(xmin, ymax - dy) polyline.append(point) point = QgsPointXY(xmin, ymin + dy) polyline.append(point) point = QgsPointXY(xmin, ymin) polyline.append(point) if isMulti: qgsPolygon = QgsGeometry.fromMultiPolygonXY([[polyline]]) else: qgsPolygon = QgsGeometry.fromPolygonXY([polyline]) return qgsPolygon
def current_layer_selection_changed(self): """PyqtSlot: When the selection of the current layer is changed""" if self.is_wrong_projection: self.projection_error() return selection = self.current_layer.selectedFeatures() if len(selection) == 0: self.le_external_id.setDisabled(True) self.le_area_title.setDisabled(True) elif len(selection) > 1: self.le_external_id.setDisabled(True) self.le_area_title.setDisabled(True) iface.messageBar().pushMessage( "INFO", "More than one feature selected, please re-select.", level=Qgis.Info, duration=3) elif len(selection) == 1: new_geometry = selection[0].geometry() # error pops up if geometry type is not polygon or multipolygon if new_geometry.wkbType() not in [ QgsWkbTypes.Polygon, QgsWkbTypes.MultiPolygon ]: self.error_dialog = ErrorDialog() self.error_dialog.fill_report( "\n -------------------- WRONG GEOMETRY TYPE ------" "-------------- \n\nInserted capture source area " "should be either polygon or multipolygon.") self.error_dialog.show() return self.le_external_id.setEnabled(True) self.le_area_title.setEnabled(True) # convert to correct format if new_geometry.wkbType() == QgsWkbTypes.Polygon: new_geometry = QgsGeometry.fromMultiPolygonXY( [new_geometry.asPolygon()]) wkt = new_geometry.asWkt() sql = general_select.convert_geometry result = self.db.execute_return(sql, (wkt, )) self.geom = result.fetchall()[0][0]
def buildQgsMultipolygon(self,polygon): ''' Construct QgsMultiPolygon from matplotlib version ''' mpoly=[] invalid=0 for path in polygon.get_paths(): path.should_simplify = False poly = path.to_polygons() if len(poly) < 1: continue if len(poly[0]) < 3: # Have had one vertix polygon from matplotlib! continue polypts=[[QgsPointXY(x,y) for x,y in p] for p in poly if len(p) > 3 ] mpoly.append(polypts) geom = None if len(mpoly) > 0: geom=QgsGeometry.fromMultiPolygonXY(mpoly) geom=geom.makeValid() return geom
def creator_feature_added(self, qgsfId): """ Called when feature is added @param qgsfId: Id of added feature @type qgsfId: qgis.core.QgsFeature.QgsFeatureId """ if qgsfId not in self.added_building_ids: self.added_building_ids.append(qgsfId) # get new feature geom request = QgsFeatureRequest().setFilterFid(qgsfId) new_feature = next(self.capture_source_area.getFeatures(request)) new_geometry = new_feature.geometry() # convert to correct format if new_geometry.wkbType() == QgsWkbTypes.Polygon: new_geometry = QgsGeometry.fromMultiPolygonXY( [new_geometry.asPolygon()]) wkt = new_geometry.asWkt() sql = general_select.convert_geometry result = self.db.execute_return(sql, (wkt, )) self.geom = result.fetchall()[0][0] self.le_area_title.setEnabled(True) self.le_external_id.setEnabled(True)
def inv_vertex_order(self, geom): if geom.type() == 1: #Line if geom.isMultipart(): linhas = geom.asMultiPolyline() newLines = [] for linha in linhas: newLine = linha[::-1] newLines += [newLine] newGeom = QgsGeometry.fromMultiPolylineXY(newLines) return newGeom else: linha = geom.asPolyline() newLine = linha[::-1] newGeom = QgsGeometry.fromPolylineXY(newLine) return newGeom elif geom.type() == 2: #Polygon if geom.isMultipart(): poligonos = geom.asMultiPolygon() newPolygons = [] for pol in poligonos: newPol = [] for anel in pol: newAnel = anel[::-1] newPol += [newAnel] newPolygons += [newPol] newGeom = QgsGeometry.fromMultiPolygonXY(newPolygons) return newGeom else: pol = geom.asPolygon() newPol = [] for anel in pol: newAnel = anel[::-1] newPol += [newAnel] newGeom = QgsGeometry.fromPolygonXY(newPol) return newGeom else: return None
def processPoly(source, sink, feedback, maxseglen): layercrs = source.sourceCrs() if layercrs != epsg4326: transto4326 = QgsCoordinateTransform(layercrs, epsg4326, QgsProject.instance()) transfrom4326 = QgsCoordinateTransform(epsg4326, layercrs, QgsProject.instance()) total = 100.0 / source.featureCount() if source.featureCount() else 0 iterator = source.getFeatures() num_bad = 0 for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: if not feature.geometry().isMultipart(): poly = feature.geometry().asPolygon() numpolygons = len(poly) if numpolygons < 1: continue ptset = [] # Iterate through all points in the polygon and if the distance # is greater than the maxseglen, then add additional points. for points in poly: numpoints = len(points) if numpoints < 2: continue # If the input is not 4326 we need to convert it to that and then back to the output CRS ptStart = QgsPointXY(points[0][0], points[0][1]) if layercrs != epsg4326: # Convert to 4326 ptStart = transto4326.transform(ptStart) pts = [ptStart] for x in range(1, numpoints): ptEnd = QgsPointXY(points[x][0], points[x][1]) if layercrs != epsg4326: # Convert to 4326 ptEnd = transto4326.transform(ptEnd) l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x()) # Check to see if the distance is greater than the maximum # segment length and if so lets add additional points. if l.s13 > maxseglen: n = int(math.ceil(l.s13 / maxseglen)) seglen = l.s13 / n for i in range(1, n): s = seglen * i g = l.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) pts.append(QgsPointXY(g['lon2'], g['lat2'])) pts.append(ptEnd) ptStart = ptEnd if layercrs != epsg4326: # Convert each point to the output CRS for x, pt in enumerate(pts): pts[x] = transfrom4326.transform(pt) ptset.append(pts) if len(ptset) > 0: featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY(ptset)) featureout.setAttributes(feature.attributes()) sink.addFeature(featureout) else: multipoly = feature.geometry().asMultiPolygon() multiset = [] for poly in multipoly: ptset = [] for points in poly: numpoints = len(points) if numpoints < 2: continue # If the input is not 4326 we need to convert it to that and then back to the output CRS ptStart = QgsPointXY(points[0][0], points[0][1]) if layercrs != epsg4326: # Convert to 4326 ptStart = transto4326.transform(ptStart) pts = [ptStart] for x in range(1, numpoints): ptEnd = QgsPointXY(points[x][0], points[x][1]) if layercrs != epsg4326: # Convert to 4326 ptEnd = transto4326.transform(ptEnd) l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x()) if l.s13 > maxseglen: n = int(math.ceil(l.s13 / maxseglen)) seglen = l.s13 / n for i in range(1, n): s = seglen * i g = l.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) pts.append(QgsPointXY( g['lon2'], g['lat2'])) pts.append(ptEnd) ptStart = ptEnd if layercrs != epsg4326: # Convert each point to the output CRS for x, pt in enumerate(pts): pts[x] = transfrom4326.transform(pt) ptset.append(pts) multiset.append(ptset) if len(multiset) > 0: featureout = QgsFeature() featureout.setGeometry( QgsGeometry.fromMultiPolygonXY(multiset)) featureout.setAttributes(feature.attributes()) sink.addFeature(featureout) except: num_bad += 1 '''s = traceback.format_exc() feedback.pushInfo(s)''' feedback.setProgress(int(cnt * total)) return num_bad
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. source = self.parameterAsSource(parameters, self.INPUT, context) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), source.wkbType(), source.sourceCrs()) # Compute the number of steps to display within the progress bar and # get features from source total = 100.0 / source.featureCount() if source.featureCount() else 0 features = source.getFeatures() print(features) for current, feature in enumerate(features): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): break # sshuair begin geom = feature.geometry() attrs = feature.attributes() geom_type = geom.wkbType() feature_new = QgsFeature() # Point if geom_type == 1: vertices = geom.asPoint() vert_new = bd2gcj(vertices[0], vertices[1]) feature_new.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(vert_new[0], vert_new[1]))) # LineString elif geom_type == 2: vert_new = [] vertices = geom.asPolyline() for pt in vertices: pt_new = bd2gcj(pt[0], pt[1]) vert_new.append(QgsPointXY(pt_new[0], pt_new[1])) feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new)) # Polygon elif geom_type == 3: vertices = geom.asPolygon() vert_new = [] for ring in vertices: ring_vert = [] for pt in ring: pt_new = bd2gcj(pt[0], pt[1]) ring_vert.append(QgsPointXY(pt_new[0], pt_new[1])) vert_new.append(ring_vert) feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new)) # MultiPoint elif geom_type == 4: vert_new = [] vertices = geom.asMultiPoint() for pt in vertices: pt_new = bd2gcj(pt[0], pt[1]) vert_new.append(QgsPointXY(pt_new[0], pt_new[1])) feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new)) # MultiLineString elif geom_type == 5: vertices = geom.asMultiPolyline() vert_new = [] for part in vertices: linestring = [] for pt in part: pt_new = bd2gcj(pt[0], pt[1]) linestring.append(QgsPointXY(pt_new[0], pt_new[1])) vert_new.append(linestring) feature_new.setGeometry( QgsGeometry.fromMultiPolylineXY(vert_new)) # MultiPolygon elif geom_type == 6: vertices = geom.asMultiPolygon() vert_new = [] for part in vertices: poly = [] for ring in part: ring_vert = [] for pt in ring: pt_new = bd2gcj(pt[0], pt[1]) ring_vert.append(QgsPointXY(pt_new[0], pt_new[1])) poly.append(ring_vert) vert_new.append(poly) feature_new.setGeometry( QgsGeometry.fromMultiPolygonXY(vert_new)) else: continue feature_new.setAttributes(attrs) # sshuair end # feature = feature+0.1 # Add a feature in the sink sink.addFeature(feature_new, QgsFeatureSink.FastInsert) # Update the progress bar feedback.setProgress(int(current * total)) print(feature) # Return the results of the algorithm. In this case our only result is # the feature sink which contains the processed features, but some # algorithms may return multiple feature sinks, calculated numeric # statistics, etc. These should all be included in the returned # dictionary, with keys matching the feature corresponding parameter # or output names. return {self.OUTPUT: dest_id}
def splitPolygonXY(self, geom): return QgsGeometry.fromMultiPolygonXY(list(self._splitPolygon(geom)))
count = Polygons.featureCount() (sink, Biggest_parts) = self.parameterAsSink(parameters, 'Biggest parts', context, Polygons.fields(), QgsWkbTypes.MultiPolygon, Polygons.sourceCrs()) for n, feat in enumerate(Polygons.getFeatures()): if feedback.isCanceled(): break feedback.setProgress(int(100 * n / count)) geom = feat.geometry() if geom.isMultipart(): features = feat geoms = geom.asGeometryCollection() geomarea = [(i, geoms[i].area()) for i in range(len(geoms))] geomarea.sort(key=itemgetter(1)) if To_keep == 1: features.setGeometry(geoms[geomarea[-1][0]]) elif To_keep > len(geoms): features.setGeometry(geom) else: features.setGeometry(geom) geomres = [ geoms[i].asPolygon() for i, a in geomarea[-1 * To_keep:] ] features.setGeometry(QgsGeometry.fromMultiPolygonXY(geomres)) sink.addFeature(features) else: sink.addFeature(feat)
feedback.pushInfo("'To keep' value has been modified to be at least 1.") To_keep = 1 count = Polygons.featureCount() (sink, Biggest_parts) = self.parameterAsSink(parameters, 'Biggest parts', context, Polygons.fields(), QgsWkbTypes.MultiPolygon, Polygons.sourceCrs()) for n, feat in enumerate(Polygons.getFeatures()): if feedback.isCanceled(): break feedback.setProgress(int(100 * n / count)) geom = feat.geometry() if geom.isMultipart(): features = feat geoms = geom.asGeometryCollection() geomarea = [(i, geoms[i].area()) for i in range(len(geoms))] geomarea.sort(key=itemgetter(1)) if To_keep == 1: features.setGeometry(geoms[geomarea[-1][0]]) elif To_keep > len(geoms): features.setGeometry(geom) else: features.setGeometry(geom) geomres = [geoms[i].asPolygon() for i, a in geomarea[-1 * To_keep:]] features.setGeometry(QgsGeometry.fromMultiPolygonXY(geomres)) sink.addFeature(features) else: sink.addFeature(feat)
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ earthRadius = 6370997 # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. source = self.parameterAsVectorLayer( parameters, self.INPUT, context ) #lat centerLatitude = self.parameterAsDouble( parameters, self.CENTER_LATITUDE, context ) #lon centerLongitude = self.parameterAsDouble( parameters, self.CENTER_LONGITUDE, context ) #segment segments = self.parameterAsInt( parameters, self.SEGMENTS, context ) # If source was not found, throw an exception to indicate that the algorithm # encountered a fatal error. The exception text can be any string, but in this # case we use the pre-built invalidSourceError method to return a standard # helper text for when a source cannot be evaluated if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) if centerLatitude is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.CENTER_LATITUDE)) if centerLongitude is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.CENTER_LATITUDE)) if segments is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.SEGMENTS)) output = self.parameterAsOutputLayer( parameters, self.OUTPUT, context ) # Send some information to the user if source.sourceCrs().authid() != 'EPSG:4326': feedback.pushDebugInfo('Input layer for "Clip to Hemisphere" does not use the WGS84 (EPSG:4326) CRS. This can cause unexpected results.') else: feedback.pushInfo('CRS is {}'.format(source.sourceCrs().authid())) sourceCrs = source.sourceCrs() targetProjString = "+proj=ortho +lat_0=" + str(centerLatitude) + \ " +lon_0=" + str(centerLongitude) + \ " +x_0=0 +y_0=0 +a=" + str(earthRadius) + \ " +b=" + str(earthRadius) + \ " +units=m +no_defs" targetCrs = QgsCoordinateReferenceSystem() targetCrs.createFromProj4(targetProjString) transformTargetToSrc = QgsCoordinateTransform(targetCrs,sourceCrs,QgsProject.instance()) transformSrcToTarget = QgsCoordinateTransform(sourceCrs,targetCrs,QgsProject.instance()) clipLayer = QgsVectorLayer("MultiPolygon?crs=epsg:4326", "clipLayer", "memory") pr = clipLayer.dataProvider() """ This part was adapted from (C) 2016 by Juernjakob Dugge Source: https://plugins.qgis.org/plugins/ClipToHemisphere/ """ # Handle edge cases: # Hemisphere centered on the equator if centerLatitude == 0: # Hemisphere centered on the equator and including the antimeridian if abs(centerLongitude) >= 90: edgeEast = -180 - np.sign(centerLongitude) * \ (180 - abs(centerLongitude)) + 90 edgeWest = 180 - np.sign(centerLongitude) * \ (180 - abs(centerLongitude)) - 90 circlePoints = [[ [QgsPointXY(-180.01, latitude) for latitude in np.linspace(90, -90, segments / 8)] + [QgsPointXY(longitude, -90) for longitude in np.linspace(-180, edgeEast, segments / 8)] + [QgsPointXY(edgeEast, latitude) for latitude in np.linspace(-90, 90, segments / 8)] + [QgsPointXY(longitude, 90) for longitude in np.linspace(edgeEast, -180, segments / 8)] ], [ [QgsPointXY(edgeWest, latitude) for latitude in np.linspace(90, -90, segments / 8)] + [QgsPointXY(longitude, -90) for longitude in np.linspace(edgeWest, 180, segments / 8)] + [QgsPointXY(180.01, latitude) for latitude in np.linspace(-90, 90, segments / 8)] + [QgsPointXY(longitude, 90) for longitude in np.linspace(180, edgeWest, segments / 8)] ]] # Hemisphere centered on the equator not including the antimeridian else: edgeWest = centerLongitude - 90 edgeEast = centerLongitude + 90 circlePoints = [[ [QgsPointXY(edgeWest, latitude) for latitude in np.linspace(90, -90, segments / 4)] + [QgsPointXY(longitude, -90) for longitude in np.linspace(edgeWest, edgeEast, segments / 4)] + [QgsPointXY(edgeEast, latitude) for latitude in np.linspace(-90, 90, segments / 4)] + [QgsPointXY(longitude, 90) for longitude in np.linspace(edgeEast, edgeWest, segments / 4)] ]] # Hemisphere centered on one of the poles elif abs(centerLatitude) == 90: circlePoints = [[ [QgsPointXY(-180.01, latitude) for latitude in np.linspace(45 + 0.5 * centerLatitude, -45 + 0.5 * centerLatitude, segments / 4)] + [QgsPointXY(longitude, -45 + 0.5 * centerLatitude) for longitude in np.linspace(-180, 180, segments / 4)] + [QgsPointXY(180.01, latitude) for latitude in np.linspace(-45 + 0.5 * centerLatitude, 45 + 0.5 * centerLatitude, segments / 4)] + [QgsPointXY(longitude, 45 + 0.5 * centerLatitude) for longitude in np.linspace(180, -180, segments / 4)] ]] # All other hemispheres else: # Create a circle in the orthographic projection, convert the # circle coordinates to the source CRS angles = np.linspace(0, 2 * np.pi, segments, endpoint=False) circlePoints = np.array([ transformTargetToSrc.transform( QgsPointXY(np.cos(angle) * earthRadius * 0.9999, np.sin(angle) * earthRadius * 0.9999) ) for angle in angles ]) # Sort the projected circle coordinates from west to east sortIdx = np.argsort(circlePoints[:, 0]) circlePoints = circlePoints[sortIdx, :] circlePoints = [[[QgsPointXY(point[0], point[1]) for point in circlePoints]]] # Find the circle point in the orthographic projection that lies # on the antimeridian by linearly interpolating the angles of the # first and last coordinates startGap = 180 + circlePoints[0][0][0][0] endGap = 180 - circlePoints[0][0][-1][0] totalGap = startGap + endGap startCoordinates = transformSrcToTarget.transform(circlePoints[0][0][0]) endCoordinates = transformSrcToTarget.transform(circlePoints[0][0][-1]) startAngle = np.arctan2(startCoordinates[0], startCoordinates[1]) endAngle = np.arctan2(endCoordinates[0], endCoordinates[1]) antimeridianAngle = cmath.phase( endGap / totalGap * cmath.rect(1, startAngle) + startGap / totalGap * cmath.rect(1, endAngle)) antimeridianPoint = transformTargetToSrc.transform(QgsPointXY( np.sin(antimeridianAngle) * earthRadius * 0.9999, np.cos(antimeridianAngle) * earthRadius * 0.9999 )) # Close the polygon circlePoints[0][0].extend( [QgsPointXY(180.01, latitude) for latitude in np.linspace(antimeridianPoint[1], np.sign(centerLatitude) * 90, segments / 4)] + [QgsPointXY(-180.01, latitude) for latitude in np.linspace(np.sign(centerLatitude) * 90, antimeridianPoint[1], segments / 4)] ) # Create the feature and add it to the layer circle = QgsFeature() circle.setGeometry(QgsGeometry.fromMultiPolygonXY(circlePoints)) pr.addFeatures([circle]) pr.updateExtents() # We need to add the clipping layer to the layer list in order to be # able to use them with processing.runalg() clipLayerReg = QgsProject.instance().addMapLayer(clipLayer) # If sink was not created, throw an exception to indicate that the algorithm # encountered a fatal error. The exception text can be any string, but in this # case we use the pre-built invalidSinkError method to return a standard # helper text for when a sink cannot be evaluated if output is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) #clip the layer processing.run("qgis:clip", {'INPUT': source, 'OVERLAY': clipLayerReg, 'OUTPUT':output}, feedback = feedback, context = context) return {self.OUTPUT: output}
def densify_poly(in_layer, pr): bad_geom = 0 iterator = in_layer.getFeatures() # create empty feature to write to for feature in iterator: try: if feature.geometry().wkbType( ) == QgsWkbTypes.LineString: line_geom = feature.geometry().asPolyline() geom_type = "LineString" elif feature.geometry().wkbType( ) == QgsWkbTypes.MultiLineString: multiline_geom = feature.geometry( ).asMultiPolyline() geom_type = "MultiLineString" elif feature.geometry().wkbType( ) == QgsWkbTypes.Polygon: poly_geom = feature.geometry().asPolygon() geom_type = "Polygon" elif feature.geometry().wkbType( ) == QgsWkbTypes.MultiPolygon: multipoly_geom = feature.geometry().asMultiPolygon( ) geom_type = "MultiPolygon" else: bad_geom += 1 except: bad_geom += 1 if geom_type == "LineString": dense_points = [] point_count = len(line_geom) start_pt = QgsPointXY(line_geom[0][0], line_geom[0][1]) dense_points.append(start_pt) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(line_geom[j][0], line_geom[j][1]) if self.inLayer.crs() != wgs84crs: end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY(g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform(end_pt) dense_points.append(end_pt) start_pt = end_pt elif geom_type == "MultiLineString": dense_features = [] for i in range(len(multiline_geom)): dense_points = [] line = multiline_geom[i] point_count = len(line) start_pt = QgsPointXY(line[0][0], line[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(line[j][0], line[j][1]) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt dense_features.append(dense_points) elif geom_type == "Polygon": for poly in poly_geom: dense_points = [] point_count = len(poly) start_pt = QgsPointXY(poly[0][0], poly[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(poly[j][0], poly[j][1]) if self.inLayer.crs() != wgs84crs: end_pt = transtowgs84.transform(end_pt) start_pt = transtowgs84.transform(start_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt if geom_type == "MultiPolygon": dense_features = [] for i in range(len(multipoly_geom)): dense_points = [] poly = multipoly_geom[i][0] point_count = len(poly) start_pt = QgsPointXY(poly[0][0], poly[0][1]) dense_points.append(start_pt) for j in range(1, point_count): end_pt = QgsPointXY(poly[j][0], poly[j][1]) if self.inLayer.crs() != wgs84crs: start_pt = transtowgs84.transform(start_pt) end_pt = transtowgs84.transform(end_pt) # create a geographiclib line object line_object = self.geod.InverseLine( start_pt.y(), start_pt.x(), end_pt.y(), end_pt.x()) # determine how many densified segments there will be if self.segmentMethod == 'count': n = self.segmentCount else: n = int( math.ceil(line_object.s13 / self.spacing)) if line_object.s13 > self.spacing: seglen = line_object.s13 / n for k in range(1, n): s = seglen * k g = line_object.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) waypoint = QgsPointXY( g['lon2'], g['lat2']) if self.inLayer.crs() != wgs84crs: waypoint = transfromwgs84.transform( waypoint) dense_points.append(waypoint) if self.inLayer.crs() != wgs84crs: end_pt = transfromwgs84.transform( end_pt) dense_points.append(end_pt) start_pt = end_pt dense_features.append(dense_points) new_poly = QgsFeature() if geom_type == "LineString": new_poly.setGeometry( QgsGeometry.fromPolylineXY(dense_points)) elif geom_type == "MultiLineString": new_poly.setGeometry( QgsGeometry.fromMultiPolylineXY(dense_features)) elif geom_type == "Polygon": new_poly.setGeometry( QgsGeometry.fromPolygonXY([dense_points])) elif geom_type == "MultiPolygon": new_poly.setGeometry( QgsGeometry.fromMultiPolygonXY([dense_features])) new_poly.setAttributes(feature.attributes()) pr.addFeatures([new_poly]) if bad_geom > 0: self.iface.messageBar().pushWarning( "", "{} features failed".format(bad_geom))