def explodeMultiPartFeature(self, provider, feat): tmpFeat = QgsFeature() # Get attributes from original feature # Because of changes in the way the 1.9 api handle attributes if QGis.QGIS_VERSION_INT < 10900: newAttribs = feat.attributeMap() for j in range(newAttribs.__len__()): if not provider.defaultValue(j).isNull(): newAttribs[j] = provider.defaultValue(j) tmpFeat.setAttributeMap(newAttribs) else: #pyqtRemoveInputHook() #pdb.set_trace() newAttribs = feat.attributes() for j in range(newAttribs.__len__()): #if not provider.defaultValue(j).isNull(): # newAttribs[j] = provider.defaultValue(j) newAttribs[j] = provider.defaultValue(j) tmpFeat.setAttributes(newAttribs) parts = feat.geometry().asGeometryCollection() newFeats = [] for part in parts: if part.isGeosEmpty() is False: tmpFeat.setGeometry(part) newFeat = QgsFeature(tmpFeat) #if newFeat.isValid() is True: newFeats.append(newFeat) return newFeats
def testAddFeatures(self): layer = QgsVectorLayer("Point", "test", "memory") provider = layer.dataProvider() res = provider.addAttributes([ QgsField( "name", QVariant.String, ), QgsField("age", QVariant.Int), QgsField("size", QVariant.Double) ]) assert res, "Failed to add attributes" myMessage = ('Expected: %s\nGot: %s\n' % (3, provider.fieldCount())) assert provider.fieldCount() == 3, myMessage ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) ft.setAttributeMap({ 0: QVariant("Johny"), 1: QVariant(20), 2: QVariant(0.3) }) res, t = provider.addFeatures([ft]) assert res, "Failed to add feature" myMessage = ('Expected: %s\nGot: %s\n' % (1, provider.featureCount())) assert provider.featureCount() == 1, myMessage f = QgsFeature() provider.select() while provider.nextFeature(f): attrMap = f.attributeMap() myMessage = ('Expected: %s\nGot: %s\n' % ("Johny", str(attrMap[0].toString()))) assert str(attrMap[0].toString()) == "Johny", myMessage myMessage = ('Expected: %s\nGot: %s\n' % (20, attrMap[1].toInt()[0])) assert attrMap[1].toInt()[0] == 20, myMessage myMessage = ('Expected: %s\nGot: %s\n' % (0.3, attrMap[2].toFloat()[0])) assert (attrMap[0].toFloat()[0] - 0.3) < 0.0000001, myMessage geom = f.geometry() myMessage = ( 'Expected: %s\nGot: %s\n' % ("POINT(10.000000 10.000000)", str(geom.exportToWkt()))) assert str( geom.exportToWkt()) == "POINT(10.000000 10.000000)", myMessage
def _extentsToLayer(self): """Memory layer for aggregation by using canvas extents as feature. We do this because the user elected to use no aggregation layer so we make a 'dummy' one which covers the whole study area extent. This layer is needed when postprocessing because we always want a vector layer to store aggregation information in. Returns: QgsMapLayer - a memory layer representing the extents of the clip. """ # Note: this code duplicates from Dock.viewportGeoArray - make DRY. TS myRect = self.iface.mapCanvas().extent() myCrs = QgsCoordinateReferenceSystem() myCrs.createFromEpsg(4326) myGeoExtent = extent_to_geo_array(myRect, myCrs) if not self.layer.isValid(): myMessage = self.tr( 'An exception occurred when creating the entire area layer.') raise (Exception(myMessage)) myProvider = self.layer.dataProvider() myAttrName = self.tr('Area') myProvider.addAttributes( [QgsField(myAttrName, QtCore.QVariant.String)]) self.layer.startEditing() # add a feature the size of the impact layer bounding box myFeature = QgsFeature() # noinspection PyCallByClass,PyTypeChecker,PyArgumentList myFeature.setGeometry(QgsGeometry.fromRect( QgsRectangle( QgsPoint(myGeoExtent[0], myGeoExtent[1]), QgsPoint(myGeoExtent[2], myGeoExtent[3])))) myFeature.setAttributeMap({0: QtCore.QVariant( self.tr('Entire area'))}) myProvider.addFeatures([myFeature]) self.layer.commitChanges() try: self.keywordIO.update_keywords( self.layer, {self.defaults['AGGR_ATTR_KEY']: myAttrName}) except InvalidParameterError: self.keywordIO.write_keywords( self.layer, {self.defaults['AGGR_ATTR_KEY']: myAttrName}) except KeywordDbError, e: raise e
def asFeature(self): feature = QgsFeature() feature.setGeometry(self._geometry) # The Uuid as trimmed string id = self._id.toString() feature.setAttributeMap({ 0: QVariant(id), 1: QVariant(self._version) }) return feature
def testAddFeatures(self): layer = QgsVectorLayer("Point", "test", "memory") provider = layer.dataProvider() res = provider.addAttributes([QgsField("name", QVariant.String,), QgsField("age", QVariant.Int), QgsField("size", QVariant.Double)]) assert res, "Failed to add attributes" myMessage = ('Expected: %s\nGot: %s\n' % (3, provider.fieldCount())) assert provider.fieldCount() == 3, myMessage ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10,10))) ft.setAttributeMap({0 : QVariant("Johny"), 1 : QVariant(20), 2 : QVariant(0.3)}) res, t = provider.addFeatures([ft]) assert res, "Failed to add feature" myMessage = ('Expected: %s\nGot: %s\n' % (1, provider.featureCount())) assert provider.featureCount() == 1, myMessage f = QgsFeature() provider.select() while provider.nextFeature(f): attrMap = f.attributeMap() myMessage = ('Expected: %s\nGot: %s\n' % ("Johny", str(attrMap[0].toString()))) assert str(attrMap[0].toString()) == "Johny", myMessage myMessage = ('Expected: %s\nGot: %s\n' % (20, attrMap[1].toInt()[0])) assert attrMap[1].toInt()[0] == 20, myMessage myMessage = ('Expected: %s\nGot: %s\n' % (0.3, attrMap[2].toFloat()[0])) assert (attrMap[0].toFloat()[0] - 0.3) < 0.0000001, myMessage geom = f.geometry() myMessage = ('Expected: %s\nGot: %s\n' % ("POINT(10.0 10.0)", str(geom.exportToWkt()))) assert str(geom.exportToWkt()) == "POINT(10.0 10.0)", myMessage
def do_operation(self): """ perform footprint load operation """ grid_layer = self.inputs[0].value # make sure input is correct # NOTE: these checks cannot be performed at set input time # because the data layer maybe is not loaded yet self._test_layer_loaded(grid_layer) grid_fields = grid_layer.dataProvider().fields() output_layername = 'grid_%s' % get_unique_filename() output_file = self._tmp_dir + output_layername + '.shp' half_grid = DEFAULT_GRID_SIZE / 2.0 try: writer = QgsVectorFileWriter(output_file, "utf-8", grid_fields, QGis.WKBPolygon, grid_layer.crs(), "ESRI Shapefile") out_f = QgsFeature() for in_f in layer_features(grid_layer): in_point = in_f.geometry().asPoint() out_geom = QgsGeometry.fromRect( QgsRectangle(in_point.x() - half_grid, in_point.y() - half_grid, in_point.x() + half_grid, in_point.y() + half_grid)) out_f.setGeometry(out_geom) out_f.setAttributeMap(in_f.attributeMap()) writer.addFeature(out_f) del writer except Exception as err: logAPICall.log(str(err), logAPICall.ERROR) raise OperatorError('error writing out grid: %s' % err, self.__class__) # load shapefile as layer output_layer = load_shapefile(output_file, output_layername) if not output_layer: raise OperatorError( 'Error loading generated file %s' % (output_file), self.__class__) # store data in output self.outputs[0].value = output_layer self.outputs[1].value = output_file
def createPointsAt(distance, geom): length = geom.length() currentdistance = distance feats = [] while currentdistance < length: # Get a point along the line at the current distance point = geom.interpolate(currentdistance) # Create a new QgsFeature and assign it the new geometry fet = QgsFeature() fet.setAttributeMap( { 0 : currentdistance } ) fet.setGeometry(point) feats.append(fet) # Increase the distance currentdistance = currentdistance + distance return feats
def createPointsAt(distance, geom): length = geom.length() currentdistance = distance feats = [] while currentdistance < length: # Get a point along the line at the current distance point = geom.interpolate(currentdistance) # Create a new QgsFeature and assign it the new geometry fet = QgsFeature() fet.setAttributeMap({0: currentdistance}) fet.setGeometry(point) feats.append(fet) # Increase the distance currentdistance = currentdistance + distance return feats
def _createOutputLayer(self, name, data, longFieldIdx, latFieldIdx, isOrigLayer=False): """ create the declustered event layer: param: **isOrigLayer** whether True the layer will contain unclustered data """ from qgis.core import QgsField, QgsFeature, QgsPoint, QgsGeometry clusterNum = "clusterNum" sizeField = "eventCount" fields = map( lambda x: x[1], sorted(Utils.classifiedVl().dataProvider().fields().iteritems()) ) fields += [ QgsField(clusterNum, QVariant.Int) ] # add the cluster num field if not isOrigLayer: fields += [ QgsField(sizeField, QVariant.Int) ] # add the event count as last field # create the layer vl = Utils.createMemoryLayer( 'Point', 'epsg:4326', fields, name ) if vl is None: return # add features pr = vl.dataProvider() for row in data: attrs = dict(enumerate(row[1:].tolist())) point = QgsPoint( row[longFieldIdx].toDouble()[0], row[latFieldIdx].toDouble()[0] ) f = QgsFeature() f.setAttributeMap( attrs ) f.setGeometry( QgsGeometry.fromPoint( point ) ) pr.addFeatures( [f] ) # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer vl.updateExtents() # set layer style if isOrigLayer: LayerStyler.setSimpleStyle( vl, color=QColor('blue'), size=1.0 ) else: # we need to scale markers by area LayerStyler.setDeclusteredStyle( vl, sizeField ) return vl
def testWrite(self): """Check we can write a vector file.""" self.mMemoryLayer = QgsVectorLayer( ('Point?crs=epsg:4326&field=name:string(20)&' 'field=age:integer&field=size:double&index=yes'), 'test', 'memory') assert self.mMemoryLayer is not None, 'Provider not initialised' myProvider = self.mMemoryLayer.dataProvider() assert myProvider is not None ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10,10))) ft.setAttributeMap({0 : QVariant('Johny'), 1 : QVariant(20), 2 : QVariant(0.3)}) myResult, myFeatures = myProvider.addFeatures([ft]) assert myResult == True assert len(myFeatures) > 0 myFileName = os.path.join(str(QDir.tempPath()), 'writetest.shp') print myFileName # Explicitly giving all options, not really needed but nice for clarity myErrorMessage = QString() myOptions = QStringList() myLayerOptions = QStringList() mySelectedOnlyFlag = False mySkipAttributesFlag = False myGeoCrs = QgsCoordinateReferenceSystem() myGeoCrs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) myResult = QgsVectorFileWriter.writeAsVectorFormat( self.mMemoryLayer, myFileName, 'utf-8', myGeoCrs, 'ESRI Shapefile', mySelectedOnlyFlag, myErrorMessage, myOptions, myLayerOptions, mySkipAttributesFlag) assert myResult == QgsVectorFileWriter.NoError
def testWrite(self): """Check we can write a vector file.""" self.mMemoryLayer = QgsVectorLayer( ("Point?crs=epsg:4326&field=name:string(20)&" "field=age:integer&field=size:double&index=yes"), "test", "memory", ) assert self.mMemoryLayer is not None, "Provider not initialised" myProvider = self.mMemoryLayer.dataProvider() assert myProvider is not None ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) ft.setAttributeMap({0: QVariant("Johny"), 1: QVariant(20), 2: QVariant(0.3)}) myResult, myFeatures = myProvider.addFeatures([ft]) assert myResult == True assert len(myFeatures) > 0 writeShape(self.mMemoryLayer, "writetest.shp")
def do_operation(self): """ perform footprint load operation """ grid_layer = self.inputs[0].value # make sure input is correct # NOTE: these checks cannot be performed at set input time # because the data layer maybe is not loaded yet self._test_layer_loaded(grid_layer) grid_fields = grid_layer.dataProvider().fields() output_layername = 'grid_%s' % get_unique_filename() output_file = self._tmp_dir + output_layername + '.shp' half_grid = DEFAULT_GRID_SIZE / 2.0 try: writer = QgsVectorFileWriter(output_file, "utf-8", grid_fields, QGis.WKBPolygon, grid_layer.crs(), "ESRI Shapefile") out_f = QgsFeature() for in_f in layer_features(grid_layer): in_point = in_f.geometry().asPoint() out_geom = QgsGeometry.fromRect(QgsRectangle(in_point.x()-half_grid, in_point.y()-half_grid, in_point.x()+half_grid, in_point.y()+half_grid)) out_f.setGeometry(out_geom) out_f.setAttributeMap(in_f.attributeMap()) writer.addFeature(out_f) del writer except Exception as err: logAPICall.log(str(err), logAPICall.ERROR) raise OperatorError('error writing out grid: %s' % err, self.__class__) # load shapefile as layer output_layer = load_shapefile(output_file, output_layername) if not output_layer: raise OperatorError('Error loading generated file %s' % (output_file), self.__class__) # store data in output self.outputs[0].value = output_layer self.outputs[1].value = output_file
def testWrite(self): """Check we can write a vector file.""" self.mMemoryLayer = QgsVectorLayer( ('Point?crs=epsg:4326&field=name:string(20)&' 'field=age:integer&field=size:double&index=yes'), 'test', 'memory') assert self.mMemoryLayer is not None, 'Provider not initialised' myProvider = self.mMemoryLayer.dataProvider() assert myProvider is not None ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) ft.setAttributeMap({ 0: QVariant('Johny'), 1: QVariant(20), 2: QVariant(0.3) }) myResult, myFeatures = myProvider.addFeatures([ft]) assert myResult == True assert len(myFeatures) > 0 myFileName = os.path.join(str(QDir.tempPath()), 'writetest.shp') print myFileName # Explicitly giving all options, not really needed but nice for clarity myErrorMessage = QString() myOptions = QStringList() myLayerOptions = QStringList() mySelectedOnlyFlag = False mySkipAttributesFlag = False myGeoCrs = QgsCoordinateReferenceSystem() myGeoCrs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) myResult = QgsVectorFileWriter.writeAsVectorFormat( self.mMemoryLayer, myFileName, 'utf-8', myGeoCrs, 'ESRI Shapefile', mySelectedOnlyFlag, myErrorMessage, myOptions, myLayerOptions, mySkipAttributesFlag) assert myResult == True
def testClipping(self): """Test that we can clip geometries using other geometries.""" myMemoryLayer = QgsVectorLayer( ('LineString?crs=epsg:4326&field=name:string(20)&index=yes'), 'clip-in', 'memory') assert myMemoryLayer is not None, 'Provider not initialised' myProvider = myMemoryLayer.dataProvider() assert myProvider is not None myFeature1 = QgsFeature() myFeature1.setGeometry(QgsGeometry.fromPolyline([ QgsPoint(10,10), QgsPoint(20,10), QgsPoint(30,10), QgsPoint(40,10), ] )) myFeature1.setAttributeMap({0 : QVariant('Johny')}) myFeature2 = QgsFeature() myFeature2.setGeometry(QgsGeometry.fromPolyline([ QgsPoint(10,10), QgsPoint(20,20), QgsPoint(30,30), QgsPoint(40,40), ] )) myFeature2.setAttributeMap({0 : QVariant('Be')}) myFeature3 = QgsFeature() myFeature3.setGeometry(QgsGeometry.fromPolyline([ QgsPoint(10,10), QgsPoint(10,20), QgsPoint(10,30), QgsPoint(10,40), ] )) myFeature3.setAttributeMap({0 : QVariant('Good')}) myResult, myFeatures = myProvider.addFeatures( [myFeature1, myFeature2, myFeature3]) assert myResult == True assert len(myFeatures) == 3 myClipPolygon = QgsGeometry.fromPolygon([[ QgsPoint(20,20), QgsPoint(20,30), QgsPoint(30,30), QgsPoint(30,20), QgsPoint(20,20), ]] ) print 'Clip: %s' % myClipPolygon.exportToWkt() writeShape(myMemoryLayer, 'clipGeometryBefore.shp') myProvider.rewind() myProvider.select(myProvider.attributeIndexes()) myFeatures = [] myFeature = QgsFeature() while myProvider.nextFeature(myFeature): myGeometry = myFeature.geometry() if myGeometry.intersects(myClipPolygon): # Adds nodes where the clip and the line intersec myCombinedGeometry = myGeometry.combine(myClipPolygon) # Gives you the areas inside the clip mySymmetricalGeometry = myGeometry.symDifference( myCombinedGeometry) # Gives you areas outside the clip area # myDifferenceGeometry = myCombinedGeometry.difference( # myClipPolygon) #print 'Original: %s' % myGeometry.exportToWkt() #print 'Combined: %s' % myCombinedGeometry.exportToWkt() #print 'Difference: %s' % myDifferenceGeometry.exportToWkt() print 'Symmetrical: %s' % mySymmetricalGeometry.exportToWkt() myExpectedWkt = 'LINESTRING(20.0 20.0, 30.0 30.0)' # There should only be one feature that intersects this clip # poly so this assertion should work. self.assertEqual(myExpectedWkt, mySymmetricalGeometry.exportToWkt()) myNewFeature = QgsFeature() myNewFeature.setAttributeMap(myFeature.attributeMap()) myNewFeature.setGeometry(mySymmetricalGeometry) myFeatures.append(myNewFeature) myNewMemoryLayer = QgsVectorLayer( ('LineString?crs=epsg:4326&field=name:string(20)&index=yes'), 'clip-out', 'memory') myNewProvider = myNewMemoryLayer.dataProvider() myResult, myFeatures = myNewProvider.addFeatures(myFeatures) self.assertTrue(myResult) self.assertEqual(len(myFeatures), 1) myNewMemoryLayer.commitChanges() writeShape(myNewMemoryLayer, 'clipGeometryAfter.shp')
def _preparePolygonLayer(self, theQgisLayer): """Create a new layer with no intersecting features to self.layer. A helper function to align the polygons to the postprocLayer polygons. If one input polygon is in two or more postprocLayer polygons then it is divided so that each part is within only one of the postprocLayer polygons. this allows to aggregate in postrocessing using centroid in polygon. The function assumes EPSG:4326 but no checks are enforced Args: theQgisLayer of the file to be processed Returns: QgisLayer of the processed file Raises: Any exceptions raised by the InaSAFE library will be propagated. """ # import time # startTime = time.clock() myMessage = m.Message( m.Heading(self.tr('Preclipping input data...')), m.Paragraph(self.tr( 'Modifying %1 to avoid intersections with the aggregation ' 'layer' ).arg(theQgisLayer.name()))) self._sendMessage(myMessage) theLayerFilename = str(theQgisLayer.source()) myPostprocPolygons = self.safeLayer.get_geometry() myPolygonsLayer = safe_read_layer(theLayerFilename) myRemainingPolygons = numpy.array(myPolygonsLayer.get_geometry()) # myRemainingAttributes = numpy.array(myPolygonsLayer.get_data()) myRemainingIndexes = numpy.array(range(len(myRemainingPolygons))) #used for unit tests only self.preprocessedFeatureCount = 0 # FIXME (MB) the intersecting array is used only for debugging and # could be safely removed myIntersectingPolygons = [] myInsidePolygons = [] # FIXME (MB) maybe do raw geos without qgis #select all postproc polygons with no attributes aggregationProvider = self.layer.dataProvider() aggregationProvider.select([]) # copy polygons to a memory layer myQgisMemoryLayer = create_memory_layer(theQgisLayer) polygonsProvider = myQgisMemoryLayer.dataProvider() allPolygonAttrs = polygonsProvider.attributeIndexes() polygonsProvider.select(allPolygonAttrs) myQgisPostprocPoly = QgsFeature() myQgisFeat = QgsFeature() myInsideFeat = QgsFeature() fields = polygonsProvider.fields() myTempdir = temp_dir(sub_dir='preprocess') myOutFilename = unique_filename(suffix='.shp', dir=myTempdir) self.keywordIO.copy_keywords(theQgisLayer, myOutFilename) mySHPWriter = QgsVectorFileWriter(myOutFilename, 'UTF-8', fields, polygonsProvider.geometryType(), polygonsProvider.crs()) if mySHPWriter.hasError(): raise InvalidParameterError(mySHPWriter.errorMessage()) # end FIXME for (myPostprocPolygonIndex, myPostprocPolygon) in enumerate(myPostprocPolygons): LOGGER.debug('PostprocPolygon %s' % myPostprocPolygonIndex) myPolygonsCount = len(myRemainingPolygons) aggregationProvider.featureAtId( myPostprocPolygonIndex, myQgisPostprocPoly, True, []) myQgisPostprocGeom = QgsGeometry(myQgisPostprocPoly.geometry()) # myPostprocPolygon bounding box values A = numpy.array(myPostprocPolygon) minx = miny = sys.maxint maxx = maxy = -minx myPostprocPolygonMinx = min(minx, min(A[:, 0])) myPostprocPolygonMaxx = max(maxx, max(A[:, 0])) myPostprocPolygonMiny = min(miny, min(A[:, 1])) myPostprocPolygonMaxy = max(maxy, max(A[:, 1])) # create an array full of False to store if a BB vertex is inside # or outside the myPostprocPolygon myAreVerticesInside = numpy.zeros(myPolygonsCount * 4, dtype=numpy.bool) # Create Nx2 vector of vertices of bounding boxes myBBVertices = [] # Compute bounding box for each geometry type for myPoly in myRemainingPolygons: minx = miny = sys.maxint maxx = maxy = -minx # Do outer ring only as the BB is outside anyway A = numpy.array(myPoly) minx = min(minx, numpy.min(A[:, 0])) maxx = max(maxx, numpy.max(A[:, 0])) miny = min(miny, numpy.min(A[:, 1])) maxy = max(maxy, numpy.max(A[:, 1])) myBBVertices.extend([(minx, miny), (minx, maxy), (maxx, maxy), (maxx, miny)]) # see if BB vertices are in myPostprocPolygon myBBVertices = numpy.array(myBBVertices) inside, _ = points_in_and_outside_polygon(myBBVertices, myPostprocPolygon) # make True if the vertice was in myPostprocPolygon myAreVerticesInside[inside] = True # myNextIterPolygons has the 0:count indexes # myOutsidePolygons has the mapped to original indexes # and is overwritten at every iteration because we care only of # the outside polygons remaining after the last iteration myNextIterPolygons = [] myOutsidePolygons = [] for i in range(myPolygonsCount): k = i * 4 myMappedIndex = myRemainingIndexes[i] # memory layers counting starts at 1 instead of 0 as in our # indexes myFeatId = myMappedIndex + 1 doIntersection = False # summ the isInside bool for each of the boundingbox vertices # of each poygon. for example True + True + False + True is 3 myPolygonLocation = numpy.sum(myAreVerticesInside[k:k + 4]) if myPolygonLocation == 4: # all vertices are inside -> polygon is inside #ignore this polygon from further analysis myInsidePolygons.append(myMappedIndex) polygonsProvider.featureAtId(myFeatId, myQgisFeat, True, allPolygonAttrs) mySHPWriter.addFeature(myQgisFeat) self.preprocessedFeatureCount += 1 # LOGGER.debug('Polygon %s is fully inside' %myMappedIndex) # tmpWriter.addFeature(myQgisFeat) elif myPolygonLocation == 0: # all vertices are outside # check if the polygon BB is completely outside of the # myPostprocPolygon BB. myPolyMinx = numpy.min(myBBVertices[k:k + 4, 0]) myPolyMaxx = numpy.max(myBBVertices[k:k + 4, 0]) myPolyMiny = numpy.min(myBBVertices[k:k + 4, 1]) myPolyMaxy = numpy.max(myBBVertices[k:k + 4, 1]) # check if myPoly is all E,W,N,S of myPostprocPolygon if ((myPolyMinx > myPostprocPolygonMaxx) or (myPolyMaxx < myPostprocPolygonMinx) or (myPolyMiny > myPostprocPolygonMaxy) or (myPolyMaxy < myPostprocPolygonMiny)): #polygon is surely outside myOutsidePolygons.append(myMappedIndex) # we need this polygon in the next iteration myNextIterPolygons.append(i) else: # polygon might be outside or intersecting. consider # it intersecting so it goes into further analysis doIntersection = True else: # some vertices are outside some inside -> polygon is # intersecting doIntersection = True #intersect using qgis if doIntersection: # LOGGER.debug('Intersecting polygon %s' % myMappedIndex) myIntersectingPolygons.append(myMappedIndex) ok = polygonsProvider.featureAtId(myFeatId, myQgisFeat, True, allPolygonAttrs) if not ok: LOGGER.debug('Couldn\'t fetch feature: %s' % myFeatId) LOGGER.debug([str(error) for error in polygonsProvider.errors()]) myQgisPolyGeom = QgsGeometry(myQgisFeat.geometry()) myAtMap = myQgisFeat.attributeMap() # for (k, attr) in myAtMap.iteritems(): # LOGGER.debug( "%d: %s" % (k, attr.toString())) # make intersection of the myQgisFeat and the postprocPoly # write the inside part to a shp file and the outside part # back to the original QGIS layer try: myIntersec = myQgisPostprocGeom.intersection( myQgisPolyGeom) # if myIntersec is not None: myIntersecGeom = QgsGeometry(myIntersec) #from ftools myUnknownGeomType = 0 if myIntersecGeom.wkbType() == myUnknownGeomType: int_com = myQgisPostprocGeom.combine( myQgisPolyGeom) int_sym = myQgisPostprocGeom.symDifference( myQgisPolyGeom) myIntersecGeom = QgsGeometry( int_com.difference(int_sym)) # LOGGER.debug('wkbType type of intersection: %s' % # myIntersecGeom.wkbType()) polygonTypesList = [QGis.WKBPolygon, QGis.WKBMultiPolygon] if myIntersecGeom.wkbType() in polygonTypesList: myInsideFeat.setGeometry(myIntersecGeom) myInsideFeat.setAttributeMap(myAtMap) mySHPWriter.addFeature(myInsideFeat) self.preprocessedFeatureCount += 1 else: pass # LOGGER.debug('Intersection not a polygon so ' # 'the two polygons either touch ' # 'only or do not intersect. Not ' # 'adding this to the inside list') #Part of the polygon that is outside the postprocpoly myOutside = myQgisPolyGeom.difference(myIntersecGeom) # if myOutside is not None: myOutsideGeom = QgsGeometry(myOutside) if myOutsideGeom.wkbType() in polygonTypesList: # modifiy the original geometry to the part # outside of the postproc polygon polygonsProvider.changeGeometryValues( {myFeatId: myOutsideGeom}) # we need this polygon in the next iteration myOutsidePolygons.append(myMappedIndex) myNextIterPolygons.append(i) except TypeError: LOGGER.debug('ERROR with FID %s', myMappedIndex) # LOGGER.debug('Inside %s' % myInsidePolygons) # LOGGER.debug('Outside %s' % myOutsidePolygons) # LOGGER.debug('Intersec %s' % myIntersectingPolygons) if len(myNextIterPolygons) > 0: #some polygons are still completely outside of the postprocPoly #so go on and reiterate using only these nextIterPolygonsIndex = numpy.array(myNextIterPolygons) myRemainingPolygons = myRemainingPolygons[ nextIterPolygonsIndex] # myRemainingAttributes = myRemainingAttributes[ # nextIterPolygonsIndex] myRemainingIndexes = myRemainingIndexes[nextIterPolygonsIndex] LOGGER.debug('Remaining: %s' % len(myRemainingPolygons)) else: print 'no more polygons to be checked' break # del tmpWriter # here the full polygon set is represented by: # myInsidePolygons + myIntersectingPolygons + myNextIterPolygons # the a polygon intersecting multiple postproc polygons appears # multiple times in the array # noinspection PyUnboundLocalVariable LOGGER.debug('Results:\nInside: %s\nIntersect: %s\nOutside: %s' % ( myInsidePolygons, myIntersectingPolygons, myOutsidePolygons)) #add in- and outside polygons for i in myOutsidePolygons: myFeatId = i + 1 polygonsProvider.featureAtId(myFeatId, myQgisFeat, True, allPolygonAttrs) mySHPWriter.addFeature(myQgisFeat) self.preprocessedFeatureCount += 1 del mySHPWriter # LOGGER.debug('Created: %s' % self.preprocessedFeatureCount) myName = '%s %s' % (theQgisLayer.name(), self.tr('preprocessed')) myOutLayer = QgsVectorLayer(myOutFilename, myName, 'ogr') if not myOutLayer.isValid(): #TODO (MB) use a better exception raise Exception('Invalid qgis Layer') if self.showIntermediateLayers: self.keywordIO.update_keywords(myOutLayer, {'title': myName}) QgsMapLayerRegistry.instance().addMapLayer(myOutLayer) return myOutLayer
def spFeature(attrs, geom): feat = QgsFeature() feat.setAttributeMap(attrs) feat.setGeometry(geom) return feat