Example #1
0
    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
Example #2
0
    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
Example #4
0
    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
Example #5
0
    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
Example #7
0
    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
Example #9
0
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
Example #10
0
	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")
Example #13
0
    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
Example #15
0
    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')
Example #16
0
    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
Example #17
0
def spFeature(attrs, geom):
    feat = QgsFeature()
    feat.setAttributeMap(attrs)
    feat.setGeometry(geom)
    return feat