Ejemplo n.º 1
0
    def testSaveFields(self):
        # Create a new memory layer with no fields
        myMemoryLayer = QgsVectorLayer(("Point?crs=epsg:4326&index=yes"), "test", "memory")

        # Add some fields to the layer
        myFields = [
            QgsField("TestInt", QVariant.Int, "integer", 2, 0),
            QgsField("TestLong", QVariant.LongLong, "long", -1, 0),
            QgsField("TestDbl", QVariant.Double, "double", 8, 6),
            QgsField("TestString", QVariant.String, "string", 50, 0),
            QgsField("TestDate", QVariant.Date, "date"),
            QgsField("TestTime", QVariant.Time, "time"),
            QgsField("TestDateTime", QVariant.DateTime, "datetime"),
        ]
        assert myMemoryLayer.startEditing()
        for f in myFields:
            assert myMemoryLayer.addAttribute(f)
        assert myMemoryLayer.commitChanges()
        myMemoryLayer.updateFields()

        # Export the layer to a layer-definition-XML
        qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer])
        assert qlr is not None

        # Import the layer from the layer-definition-XML
        layers = QgsMapLayer.fromLayerDefinition(qlr)
        assert layers is not None
        myImportedLayer = layers[0]
        assert myImportedLayer is not None

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        assert importedFields is not None
        for f in myFields:
            assert f == importedFields.field(f.name())
Ejemplo n.º 2
0
    def testUpdatedFields(self):
        """Test when referenced layer update its fields
        https://issues.qgis.org/issues/20893
        """

        ml = QgsVectorLayer("Point?srid=EPSG:4326&field=a:int", "mem", "memory")
        self.assertEqual(ml.isValid(), True)
        QgsProject.instance().addMapLayer(ml)

        ml.startEditing()
        f1 = QgsFeature(ml.fields())
        f1.setGeometry(QgsGeometry.fromWkt('POINT(2 3)'))
        ml.addFeatures([f1])
        ml.commitChanges()

        vl = QgsVectorLayer("?query=select a, geometry from mem", "vl", "virtual")
        self.assertEqual(vl.isValid(), True)

        # add one more field
        ml.dataProvider().addAttributes([QgsField('newfield', QVariant.Int)])
        ml.updateFields()

        self.assertEqual(ml.featureCount(), vl.featureCount())
        self.assertEqual(vl.fields().count(), 1)

        geometry = next(vl.getFeatures()).geometry()
        self.assertTrue(geometry)

        point = geometry.asPoint()
        self.assertEqual(point.x(), 2)
        self.assertEqual(point.y(), 3)

        QgsProject.instance().removeMapLayer(ml)
Ejemplo n.º 3
0
def nodeCreateMemoryLayer(nodename, position='bottom',target_node=None,source="Point",crs=None,indexfieldname='id'):
    if target_node == None:
        target_node = QgsProject.instance().layerTreeRoot()
    else:
         if oeq_global.isStringOrUnicode(target_node):
            target_node = nodeByName(target_node)
            if len(target_node) == 0:
                return None
            target_node = target_node[0]

    if path == None:
        path= oeq_global.OeQ_project_path()
    if crs == None:
        crs = config.project_crs
    new_layer = QgsVectorLayer(source + '?crs=' + crs, nodename, "memory")
    new_layer.setProviderEncoding('System')
    QgsMapLayerRegistry.instance().addMapLayer(new_layer, True)
    #oeq_global.OeQ_wait_for_renderer(60000)
    new_node = nodeMove(nodename,position,target_node)
    new_layer = new_node.layer()
    dataprovider = new_layer.dataProvider()
    dataprovider.addAttributes([QgsField(indexfieldname,  QVariant.Int)])
    new_layer.updateFields()
    #oeq_global.OeQ_unlockQgis()

    return new_node
Ejemplo n.º 4
0
    def testSaveFields(self):
        # Create a new memory layer with no fields
        myMemoryLayer = QgsVectorLayer(
            ('Point?crs=epsg:4326&index=yes'),
            'test',
            'memory')

        # Add some fields to the layer
        myFields = [QgsField('TestInt', QVariant.Int, 'integer', 2, 0),
                    QgsField('TestDbl', QVariant.Double, 'double', 8, 6),
                    QgsField('TestString', QVariant.String, 'string', 50, 0),
                    QgsField('TestDate', QVariant.Date, 'date'),
                    QgsField('TestTime', QVariant.Time, 'time'),
                    QgsField('TestDateTime', QVariant.DateTime, 'datetime')]
        assert myMemoryLayer.startEditing()
        for f in myFields:
            assert myMemoryLayer.addAttribute(f)
        assert myMemoryLayer.commitChanges()
        myMemoryLayer.updateFields()

        # Export the layer to a layer-definition-XML
        qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer])
        assert qlr is not None

        # Import the layer from the layer-definition-XML
        layers = QgsMapLayer.fromLayerDefinition(qlr)
        assert layers is not None
        myImportedLayer = layers[0]
        assert myImportedLayer is not None

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        assert importedFields is not None
        for f in myFields:
            assert f == importedFields.field(f.name())
Ejemplo n.º 5
0
def createReprojectedLayer(layer, crs):
    """
    Creates a reprojected layer
    layer: layer used
    crs: crs used
    """
    temp = QgsVectorLayer('%s?crs=%s'% ('Multipolygon', crs.authid()), 'temp', 'memory')
    if not layer.isValid():
        raise GeoAlgorithmExecutionException('Problema ao criar camada reprojetada!')
        return None
    
    provider = temp.dataProvider()
    provider.addAttributes(layer.dataProvider().fields().toList())
    temp.updateFields()
    
    coordinateTransformer = QgsCoordinateTransform(layer.crs(), crs)
    features = []
    for feature in layer.getFeatures():
        feat = QgsFeature(feature)
        geom = feat.geometry()
        geom.transform(coordinateTransformer)
        feat.setGeometry(geom)
        features.append(feat)
        
    provider.addFeatures(features)
    
    return temp
Ejemplo n.º 6
0
    def testStringWithMaxLen(self):
        """ tests that text edit wrappers correctly handle string fields with a maximum length """
        layer = QgsVectorLayer("none?field=fldint:integer", "layer", "memory")
        assert layer.isValid()
        layer.dataProvider().addAttributes([QgsField('max', QVariant.String, 'string', 10),
                                            QgsField('nomax', QVariant.String, 'string', 0)])
        layer.updateFields()
        QgsMapLayerRegistry.instance().addMapLayer(layer)

        reg = QgsEditorWidgetRegistry.instance()
        config = {'IsMultiline': 'True'}

        # first test for field without character limit
        editor = QTextEdit()
        editor.setPlainText('this_is_a_long_string')
        w = reg.create('TextEdit', layer, 2, config, editor, None)
        self.assertEqual(w.value(), 'this_is_a_long_string')

        # next test for field with character limit
        editor = QTextEdit()
        editor.setPlainText('this_is_a_long_string')
        w = reg.create('TextEdit', layer, 1, config, editor, None)

        self.assertEqual(w.value(), 'this_is_a_')

        QgsMapLayerRegistry.instance().removeAllMapLayers()
Ejemplo n.º 7
0
def create_neighbors_layer():
    vl = QgsVectorLayer("Polygon", LAYER_NEIGHBORS, "memory")
    pr = vl.dataProvider()
    vl.startEditing()
    pr.addAttributes( [ QgsField(FIELD_UUID, QVariant.String),
                    QgsField(FIELD_NEIGHBORS_UUID,  QVariant.String),
                    QgsField(FIELD_SV,  QVariant.Double)] )
    vl.updateFields()
    return vl
Ejemplo n.º 8
0
def create_layer(name, attributes):
    layer = QgsVectorLayer("Polygon", name, "memory")
    pr = layer.dataProvider()
    layer.startEditing()
    pr.addAttributes(attributes)
    layer.updateFields()
    layer.commitChanges()
    QgsMapLayerRegistry.instance().addMapLayer(layer) 
    return layer
Ejemplo n.º 9
0
 def createGridLayer(self, name, layerType, crsAuthId):
     layer = QgsVectorLayer('%s?crs=%s'% (layerType, crsAuthId), name, 'memory')
     if not layer.isValid():
         self.aux.errorOccurred.emit(self.aux.getMemoryLayerErrorMessage())
         return
     provider = layer.dataProvider()
     provider.addAttributes([QgsField(self.aux.getIndexFieldName(), QVariant.String), QgsField('mi', QVariant.String)])
     layer.updateFields()
     return layer
Ejemplo n.º 10
0
    def fill_attribute_table(self):

        # Ouvrir le shapefile
        cliffs = QgsVectorLayer(self.output_path + os.sep + "cliffs.shp", "cliffs_points", "ogr")
        caps = cliffs.dataProvider().capabilities()
        prov = cliffs.dataProvider()

        # Ouvrir tous les rasters pour obtenir les coefficients de transformation
        orientation = gdal.Open(self.output_path + os.sep + "slope.tif")
        inclinaison = gdal.Open(self.output_path + os.sep + "aspect.tif")
        prox_wetland = gdal.Open(self.output_path + os.sep + "create_prox_raster_wl.tif")
        prox_water = gdal.Open(self.output_path + os.sep + "create_prox_raster_w.tif")
        score = gdal.Open(self.output_path + os.sep + "raster_output.tif")

        # Ajouter tous les nouveaux attributs
        if caps & QgsVectorDataProvider.AddAttributes:
            cliffs.dataProvider().addAttributes([
                QgsField("ORIENT", QVariant.Int),
                QgsField("INCLIN", QVariant.Int),
                QgsField("PROX_MH", QVariant.Int),
                QgsField("PROX_LAC", QVariant.Int),
                QgsField("POINTAGE", QVariant.Int)
            ])
        cliffs.updateFields()

        patches = cliffs.getFeatures()
        if caps & QgsVectorDataProvider.ChangeAttributeValues:
            for patch in patches:
                pt = patch.geometry().asPoint()

                # Valeurs des attributs
                rept = self.invert_affine(orientation.GetGeoTransform(), pt)
                attr_ori = self.aspect_data[rept[::-1]]

                rept = self.invert_affine(inclinaison.GetGeoTransform(), pt)
                attr_inc = self.falaises_data[rept[::-1]]

                rept = self.invert_affine(prox_wetland.GetGeoTransform(), pt)
                attr_wet = self.wetland_prox_data[rept[::-1]]

                rept = self.invert_affine(prox_water.GetGeoTransform(), pt)
                attr_wat = self.wetland_prox_data[rept[::-1]]

                rept = self.invert_affine(score.GetGeoTransform(), pt)
                attr_sco = self.results_raster[rept[::-1]]

                # Inscrire les modifications
                prov.changeAttributeValues({patch.id(): {prov.fieldNameMap()['ORIENT']: int(attr_ori),
                                                         prov.fieldNameMap()['INCLIN']: int(attr_inc),
                                                         prov.fieldNameMap()['PROX_MH']: int(attr_wet),
                                                         prov.fieldNameMap()['PROX_LAC']: int(attr_wat),
                                                         prov.fieldNameMap()['POINTAGE']: int(attr_sco)
                                                         }})
Ejemplo n.º 11
0
 def copySelected(self, layer, mem_layer, geom_type):
     ''' Copy from selected layer to memory layer 
     '''
     self.manageMemLayers()
     
     # Create memory layer if not already set
     if mem_layer is None: 
         uri = geom_type+"?crs=epsg:25831" 
         mem_layer = QgsVectorLayer(uri, "selected_"+layer.name(), "memory")                     
      
         # Copy attributes from main layer to memory layer
         attrib_names = layer.dataProvider().fields()
         names_list = attrib_names.toList()
         newattributeList = []
         for attrib in names_list:
             aux = mem_layer.fieldNameIndex(attrib.name())
             if aux == -1:
                 newattributeList.append(QgsField(attrib.name(), attrib.type()))
         mem_layer.dataProvider().addAttributes(newattributeList)
         mem_layer.updateFields()
         
         # Insert layer in the top of the TOC           
         root = QgsProject.instance().layerTreeRoot()           
         QgsMapLayerRegistry.instance().addMapLayer(mem_layer, False)
         node_layer = QgsLayerTreeLayer(mem_layer)
         root.insertChildNode(0, node_layer)                 
  
     # Prepare memory layer for editing
     mem_layer.startEditing()
     
     # Iterate over selected features   
     cfeatures = []
     for sel_feature in layer.selectedFeatures():
         attributes = []
         attributes.extend(sel_feature.attributes())
         cfeature = QgsFeature()    
         cfeature.setGeometry(sel_feature.geometry())
         cfeature.setAttributes(attributes)
         cfeatures.append(cfeature)
                  
     # Add features, commit changes and refresh canvas
     mem_layer.dataProvider().addFeatures(cfeatures)             
     mem_layer.commitChanges()
     self.iface.mapCanvas().refresh() 
     self.iface.mapCanvas().zoomToSelected(layer)
     
     # Make sure layer is always visible 
     self.iface.legendInterface().setLayerVisible(mem_layer, True)
                 
     return mem_layer
Ejemplo n.º 12
0
 def generateMemoryLayer(self, targetLayer, fieldDict):
     epsg = 'EPSG:'+ str(targetLayer.crs().postgisSrid())
     if self.geometryText.has_key(targetLayer.wkbType()):
         geometry = self.wkbText[targetLayer.wkbType()]
     else:
         geometry = self.geometryText[targetLayer.geometryType()]
     name = targetLayer.name()
     memoryLayer = QgsVectorLayer(geometry + '?crs=' + epsg, name, "memory")
     memoryLayer.startEditing()#to add field it needs to be in editing mode
     for fieldName in fieldDict:
         field = QgsField(fieldName, fieldDict[fieldName])
         memoryLayer.dataProvider().addAttributes([field])
     memoryLayer.updateFields()
     memoryLayer.commitChanges()
     return  memoryLayer
Ejemplo n.º 13
0
def create_memory_layer(
        layer_name, geometry, coordinate_reference_system=None, fields=None):
    """Create a vector memory layer.

    :param layer_name: The name of the layer.
    :type layer_name: str

    :param geometry: The geometry of the layer.
    :rtype geometry: QGis.WkbType

    :param coordinate_reference_system: The CRS of the memory layer.
    :type coordinate_reference_system: QgsCoordinateReferenceSystem

    :param fields: Fields of the vector layer. Default to None.
    :type fields: QgsFields

    :return: The memory layer.
    :rtype: QgsVectorLayer
    """

    if geometry == QGis.Point:
        type_string = 'MultiPoint'
    elif geometry == QGis.Line:
        type_string = 'MultiLineString'
    elif geometry == QGis.Polygon:
        type_string = 'MultiPolygon'
    elif geometry == QGis.NoGeometry:
        type_string = 'none'
    else:
        raise Exception(
            'Layer is whether Point nor Line nor Polygon, I got %s' % geometry)

    uri = '%s?index=yes&uuid=%s' % (type_string, str(uuid4()))
    if coordinate_reference_system:
        crs = coordinate_reference_system.authid().lower()
        uri += '&crs=%s' % crs
    memory_layer = QgsVectorLayer(uri, layer_name, 'memory')
    memory_layer.keywords = {
        'inasafe_fields': {}
    }

    if fields:
        data_provider = memory_layer.dataProvider()
        data_provider.addAttributes(fields)
        memory_layer.updateFields()

    return memory_layer
Ejemplo n.º 14
0
def duplicateInMemory(layer, newName='', addToRegistry=False):
    """Return a memory copy of a layer

    layer: QgsVectorLayer that shall be copied to memory.
    new_name: The name of the copied layer.
    add_to_registry: if True, the new layer will be added to the QgsMapRegistry

    Returns an in-memory copy of a layer.
    """
    if newName is '':
        newName = layer.name() + ' (Memory)'

    if layer.type() == QgsMapLayer.VectorLayer:
        geomType = layer.geometryType()
        if geomType == QGis.Point:
            strType = 'Point'
        elif geomType == QGis.Line:
            strType = 'Line'
        elif geomType == QGis.Polygon:
            strType = 'Polygon'
        else:
            raise RuntimeError('Layer is whether Point nor Line nor Polygon')
    else:
        raise RuntimeError('Layer is not a VectorLayer')

    crs = layer.crs().authid().lower()
    myUuid = unicode(uuid.uuid4())
    uri = '%s?crs=%s&index=yes&uuid=%s' % (strType, crs, myUuid)
    memLayer = QgsVectorLayer(uri, newName, 'memory')
    memProvider = memLayer.dataProvider()

    provider = layer.dataProvider()
    fields = provider.fields().toList()
    memProvider.addAttributes(fields)
    memLayer.updateFields()

    for ft in provider.getFeatures():
        memProvider.addFeatures([ft])

    if addToRegistry:
        if memLayer.isValid():
            QgsMapLayerRegistry.instance().addMapLayer(memLayer)
        else:
            raise RuntimeError('Layer invalid')

    return memLayer
Ejemplo n.º 15
0
def duplicateInMemory(layer, newName="", addToRegistry=False):
    """Return a memory copy of a layer

    layer: QgsVectorLayer that shall be copied to memory.
    new_name: The name of the copied layer.
    add_to_registry: if True, the new layer will be added to the QgsMapRegistry

    Returns an in-memory copy of a layer.
    """
    if newName is "":
        newName = layer.name() + " (Memory)"

    if layer.type() == QgsMapLayer.VectorLayer:
        geomType = layer.geometryType()
        if geomType == QgsWkbTypes.PointGeometry:
            strType = "Point"
        elif geomType == QgsWkbTypes.LineGeometry:
            strType = "Line"
        elif geomType == QgsWkbTypes.PolygonGeometry:
            strType = "Polygon"
        else:
            raise RuntimeError("Layer is whether Point nor Line nor Polygon")
    else:
        raise RuntimeError("Layer is not a VectorLayer")

    crs = layer.crs().authid().lower()
    myUuid = str(uuid.uuid4())
    uri = "%s?crs=%s&index=yes&uuid=%s" % (strType, crs, myUuid)
    memLayer = QgsVectorLayer(uri, newName, "memory")
    memProvider = memLayer.dataProvider()

    provider = layer.dataProvider()
    fields = layer.fields().toList()
    memProvider.addAttributes(fields)
    memLayer.updateFields()

    for ft in provider.getFeatures():
        memProvider.addFeatures([ft])

    if addToRegistry:
        if memLayer.isValid():
            QgsProject.instance().addMapLayer(memLayer)
        else:
            raise RuntimeError("Layer invalid")

    return memLayer
Ejemplo n.º 16
0
class LayerMaker(object):
    def __init__(self, layer_name):
        self.layer = QgsVectorLayer("LineString", layer_name, "memory")
        self.pr = self.layer.dataProvider()
        self.layer.startEditing()
        self.pr.addAttributes([QgsField("elevation", QVariant.Double)])
        self.layer.updateFields()

    def add_features(self, feature_descr_list):
        features = []
        for fd in feature_descr_list:
            feature = QgsFeature()
            feature.setGeometry(fd.geom)
            feature.setAttributes([fd.elev])
            features.append(feature)
        self.pr.addFeatures(features)
        self.layer.commitChanges()
Ejemplo n.º 17
0
    def testRenameAttributes(self):
        """ Test renameAttributes() """

        tmpdir = tempfile.mkdtemp()
        self.dirs_to_cleanup.append(tmpdir)
        srcpath = os.path.join(TEST_DATA_DIR, "provider")
        for file in glob.glob(os.path.join(srcpath, "shapefile.*")):
            shutil.copy(os.path.join(srcpath, file), tmpdir)
        datasource = os.path.join(tmpdir, "shapefile.shp")

        vl = QgsVectorLayer("{}|layerid=0".format(datasource), "test", "ogr")
        provider = vl.dataProvider()

        # bad rename
        self.assertFalse(provider.renameAttributes({-1: "not_a_field"}))
        self.assertFalse(provider.renameAttributes({100: "not_a_field"}))
        # already exists
        self.assertFalse(provider.renameAttributes({2: "cnt"}))

        # rename one field
        self.assertTrue(provider.renameAttributes({2: "newname"}))
        self.assertEqual(provider.fields().at(2).name(), "newname")
        vl.updateFields()
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[2].name(), "newname")

        # rename two fields
        self.assertTrue(provider.renameAttributes({2: "newname2", 3: "another"}))
        self.assertEqual(provider.fields().at(2).name(), "newname2")
        self.assertEqual(provider.fields().at(3).name(), "another")
        vl.updateFields()
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[2].name(), "newname2")
        self.assertEqual(fet.fields()[3].name(), "another")

        # close file and reopen, then recheck to confirm that changes were saved to file
        del vl
        vl = None
        vl = QgsVectorLayer("{}|layerid=0".format(datasource), "test", "ogr")
        provider = vl.dataProvider()
        self.assertEqual(provider.fields().at(2).name(), "newname2")
        self.assertEqual(provider.fields().at(3).name(), "another")
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[2].name(), "newname2")
        self.assertEqual(fet.fields()[3].name(), "another")
Ejemplo n.º 18
0
    def testRenameAttributes(self):
        ''' Test renameAttributes() '''

        tmpdir = tempfile.mkdtemp()
        self.dirs_to_cleanup.append(tmpdir)
        srcpath = os.path.join(TEST_DATA_DIR, 'provider')
        for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
            shutil.copy(os.path.join(srcpath, file), tmpdir)
        datasource = os.path.join(tmpdir, 'shapefile.shp')

        vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        provider = vl.dataProvider()

        # bad rename
        self.assertFalse(provider.renameAttributes({-1: 'not_a_field'}))
        self.assertFalse(provider.renameAttributes({100: 'not_a_field'}))
        # already exists
        self.assertFalse(provider.renameAttributes({2: 'cnt'}))

        # rename one field
        self.assertTrue(provider.renameAttributes({2: 'newname'}))
        self.assertEqual(provider.fields().at(2).name(), 'newname')
        vl.updateFields()
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[2].name(), 'newname')

        # rename two fields
        self.assertTrue(provider.renameAttributes({2: 'newname2', 3: 'another'}))
        self.assertEqual(provider.fields().at(2).name(), 'newname2')
        self.assertEqual(provider.fields().at(3).name(), 'another')
        vl.updateFields()
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[2].name(), 'newname2')
        self.assertEqual(fet.fields()[3].name(), 'another')

        # close file and reopen, then recheck to confirm that changes were saved to file
        del vl
        vl = None
        vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        provider = vl.dataProvider()
        self.assertEqual(provider.fields().at(2).name(), 'newname2')
        self.assertEqual(provider.fields().at(3).name(), 'another')
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[2].name(), 'newname2')
        self.assertEqual(fet.fields()[3].name(), 'another')
 def _create_layer(self, geometry_type, srid, attributes, title, tag):
     """
     Creates an empty memory layer
     :param geometry_type: 'Point', 'LineString', 'Polygon', etc.
     :param srid: CRS ID of the layer
     :param attributes: list of (attribute_name, attribute_type)
     :param title: title of the layer
     """
     if srid:
         layer = QgsVectorLayer("{}?crs=EPSG:{}&field=id:string".format(geometry_type, srid), title, "memory")
     else:
         layer = QgsVectorLayer("none?field=id:string", title, "memory")
     pr = layer.dataProvider()
     pr.addAttributes([QgsField("fid", QVariant.String)])
     pr.addAttributes([QgsField("_xml_", QVariant.String)])
     for aname, atype in attributes:
         pr.addAttributes([QgsField(aname, atype)])
     layer.updateFields()
     return layer
Ejemplo n.º 20
0
    def debug_arcs(self):
        """Helper to debug arcs in a graph.

        :return: The debug layer.
        :rtype: QgsVectorLayer
        """
        srs = self.crs.toWkt()
        layer = QgsVectorLayer(
            'LineString?crs=' + srs, 'Debug edges', 'memory')
        dp = layer.dataProvider()
        fields = list()
        fields.append(QgsField('id_arc', QVariant.Int))
        for i, strategy in enumerate(self.properties):
            fields.append(QgsField('%s_%s' % (i, strategy), QVariant.Double))
        fields.append(QgsField('in_vertex', QVariant.Int))
        fields.append(QgsField('out_vertex', QVariant.Int))

        dp.addAttributes(fields)
        layer.updateFields()

        for arc_id in self.get_id_arcs():
            # noinspection PyCallByClass
            geom = QgsGeometry.fromPolyline(self.get_arc_linestring(arc_id))
            arc = self.get_arc(arc_id)
            out_vertex_id = self.get_out_vertex_id(arc_id)
            in_vertex_id = self.get_in_vertex_id(arc_id)

            attributes = list()
            attributes.append(arc_id)
            attributes = attributes + arc.properties()
            attributes.append(in_vertex_id)
            attributes.append(out_vertex_id)

            feature = QgsFeature()
            feature.setAttributes(attributes)
            feature.setGeometry(geom)

            dp.addFeatures([feature])

        layer.updateExtents()
        return layer
Ejemplo n.º 21
0
    def create_qlayer(self):
        qlayer=QgsVectorLayer("LineString"+self.crs,self.prefix+"-edges","memory")
        
        pr = qlayer.dataProvider()

        # add fields - eventually would be tied in with g.edge_dtype
        e_attrs=[QgsField("edge_id",QVariant.Int)]

        for fidx,fdesc in enumerate(self.grid.edge_dtype.descr):
            # descr gives string reprs of the types, use dtype
            # to get back to an object.
            fname=fdesc[0] ; ftype=np.dtype(fdesc[1])
            if len(fdesc)>2:
                fshape=fdesc[2]
            else:
                fshape=None

            if fname=='nodes':
                continue
            elif fname=='cells':
                e_attrs += [QgsField("c0", QVariant.Int),
                            QgsField("c1", QVariant.Int)]
            else:
                if np.issubdtype(ftype,np.int):
                    e_attrs.append( QgsField(fname,QVariant.Int) )
                elif np.issubdtype(ftype,np.float):
                    e_attrs.append( QgsField(fname,QVariant.Double) )
                else:
                    self.log.info("Not ready for other datatypes")
        self.e_attrs=e_attrs # violates functional nature ...
        pr.addAttributes(e_attrs)
        qlayer.updateFields() # tell the vector layer to fetch changes from the provider
        
        # clean, thin black style
        symbol = QgsLineSymbolV2.createSimple({'line_style':'solid',
                                                 'line_width':'0.2',
                                                 'line_width_unit':'MM',
                                                 'line_color': 'black'})
        qlayer.rendererV2().setSymbol(symbol)
        return qlayer
Ejemplo n.º 22
0
    def testRenameAttributes(self):
        layer = QgsVectorLayer("Point", "test", "memory")
        provider = layer.dataProvider()

        res = provider.addAttributes(
            [QgsField("name", QVariant.String), QgsField("age", QVariant.Int), QgsField("size", QVariant.Double)]
        )
        layer.updateFields()
        assert res, "Failed to add attributes"
        ft = QgsFeature()
        ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10)))
        ft.setAttributes(["Johny", 20, 0.3])
        res, t = provider.addFeatures([ft])

        # bad rename
        self.assertFalse(provider.renameAttributes({-1: "not_a_field"}))
        self.assertFalse(provider.renameAttributes({100: "not_a_field"}))
        # already exists
        self.assertFalse(provider.renameAttributes({1: "name"}))

        # rename one field
        self.assertTrue(provider.renameAttributes({1: "this_is_the_new_age"}))
        self.assertEqual(provider.fields().at(1).name(), "this_is_the_new_age")
        layer.updateFields()
        fet = next(layer.getFeatures())
        self.assertEqual(fet.fields()[1].name(), "this_is_the_new_age")

        # rename two fields
        self.assertTrue(provider.renameAttributes({1: "mapinfo_is_the_stone_age", 2: "super_size"}))
        self.assertEqual(provider.fields().at(1).name(), "mapinfo_is_the_stone_age")
        self.assertEqual(provider.fields().at(2).name(), "super_size")
        layer.updateFields()
        fet = next(layer.getFeatures())
        self.assertEqual(fet.fields()[1].name(), "mapinfo_is_the_stone_age")
        self.assertEqual(fet.fields()[2].name(), "super_size")
Ejemplo n.º 23
0
def checkCartoDBId(layer, convert=False):
    """Check if layer has cartodb_id field"""
    new_layer = layer

    if convert and layer.fieldNameIndex('cartodb_id') == -1:
        checkTempDir()
        temp = tempfile.NamedTemporaryFile()
        error = QgsVectorFileWriter.writeAsVectorFormat(layer, temp.name, 'utf-8', None, 'ESRI Shapefile')
        if error == QgsVectorFileWriter.NoError:
            new_layer = QgsVectorLayer(temp.name + '.shp', layer.name(), 'ogr')
            new_layer.dataProvider().addAttributes([QgsField('cartodb_id', QVariant.Int)])
            new_layer.updateFields()
            features = new_layer.getFeatures()
            i = 1
            for feature in features:
                fid = feature.id()
                aid = new_layer.fieldNameIndex('cartodb_id')
                attrs = {aid: i}
                new_layer.dataProvider().changeAttributeValues({fid : attrs})
                i = i + 1
                new_layer.updateFeature(feature)
    return new_layer
Ejemplo n.º 24
0
def show_qgis_feature(feature):
    """Show a QGIS feature.

    :param feature: The feature to display.
    :type feature: QgsFeature
    """

    geometries = ['Point', 'Line', 'Polygon']
    geometry = geometries[feature.geometry().type()]

    layer = QgsVectorLayer(geometry, 'Debug', 'memory')
    data_provider = layer.dataProvider()

    for i, attr in enumerate(feature.attributes()):
        data_provider.addAttributes(
            [QgsField('attribute %s' % i, QVariant.String)])

    layer.updateFields()

    data_provider.addFeatures([feature])
    layer.updateExtents()
    show_qgis_layer(layer)
 def createLayer(self):
     '''Create a memory layer from the zoom to locations'''
     rowcnt = self.resultsTable.rowCount()
     if rowcnt == 0:
         return
     attr = []
     for item, label in enumerate(LABELS[0:self.numCol]):
         label = label.lower()
         if item <= 1:
             attr.append(QgsField(label, QVariant.Double))
         else:
             attr.append(QgsField(label, QVariant.String))
     ptLayer = QgsVectorLayer("Point?crs=epsg:4326", u"Lat Lon Locations", "memory")
     provider = ptLayer.dataProvider()
     provider.addAttributes(attr)
     ptLayer.updateFields()
     
     for id in range(rowcnt):
         item = self.resultsTable.item(id, 0).data(Qt.UserRole)
         feature = QgsFeature()
         feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(item.lon, item.lat)))
         attr = [item.lat, item.lon, item.label]
         for i in range(3, self.numCol):
             attr.append(item.data[i-3])
         feature.setAttributes(attr)
         provider.addFeatures([feature])
     
     ptLayer.updateExtents()
     if self.settings.multiZoomStyleID == 1:
         settings = QgsPalLayerSettings()
         settings.fieldName = 'label'
         settings.placement = QgsPalLayerSettings.AroundPoint
         labeling = QgsVectorLayerSimpleLabeling(settings)
         ptLayer.setLabeling(labeling)
         ptLayer.setLabelsEnabled(True)
     elif self.settings.multiZoomStyleID == 2 and os.path.isfile(self.settings.customQMLFile()):
         ptLayer.loadNamedStyle(self.settings.customQMLFile())
         
     QgsProject.instance().addMapLayer(ptLayer)
    def createLayer(self, dim=2, name="imaer layer"):
        """Creates a map layer of polygon (2) or point (0) type, and returns both the layer and the provider as a tuple.

        :param dim: dimension of the geometry
        :type dim: int

        :param name: layer name (defaults to 'imaer layer'
        :type ft: str
        """
        # create layer
        if dim == 2:
            vl = QgsVectorLayer("Polygon?crs=EPSG:28992", name, "memory")
        else:
            vl = QgsVectorLayer("Point?crs=EPSG:28992", name, "memory")
        pr = vl.dataProvider()
        
        # add fields
        pr.addAttributes([QgsField("id", QVariant.String)])
        for subst in self.attributes:
            pr.addAttributes([QgsField(subst, QVariant.Double)])
        vl.updateFields()
        return (vl,pr)
Ejemplo n.º 27
0
    def testRenameAttributes(self):
        ''' Test renameAttributes() '''
        vl = QgsVectorLayer('%s table="qgis_test"."rename_table" sql=' % (self.dbconn), "renames", "postgres")
        provider = vl.dataProvider()
        provider.renameAttributes({1: 'field1', 2: 'field2'})

        # bad rename
        self.assertFalse(provider.renameAttributes({-1: 'not_a_field'}))
        self.assertFalse(provider.renameAttributes({100: 'not_a_field'}))
        # already exists
        self.assertFalse(provider.renameAttributes({1: 'field2'}))

        # rename one field
        self.assertTrue(provider.renameAttributes({1: 'newname'}))
        self.assertEqual(provider.fields().at(1).name(), 'newname')
        vl.updateFields()
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[1].name(), 'newname')

        # rename two fields
        self.assertTrue(provider.renameAttributes({1: 'newname2', 2: 'another'}))
        self.assertEqual(provider.fields().at(1).name(), 'newname2')
        self.assertEqual(provider.fields().at(2).name(), 'another')
        vl.updateFields()
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[1].name(), 'newname2')
        self.assertEqual(fet.fields()[2].name(), 'another')

        # close layer and reopen, then recheck to confirm that changes were saved to db
        del vl
        vl = None
        vl = QgsVectorLayer('%s table="qgis_test"."rename_table" sql=' % (self.dbconn), "renames", "postgres")
        provider = vl.dataProvider()
        self.assertEqual(provider.fields().at(1).name(), 'newname2')
        self.assertEqual(provider.fields().at(2).name(), 'another')
        fet = next(vl.getFeatures())
        self.assertEqual(fet.fields()[1].name(), 'newname2')
        self.assertEqual(fet.fields()[2].name(), 'another')
Ejemplo n.º 28
0
    def debug_vertices(self):
        """Helper to debug vertices in a graph.

        :return: The debug layer.
        :rtype: QgsVectorLayer
        """
        srs = self.crs.toWkt()
        layer = QgsVectorLayer(
            'Point?crs=' + srs, 'Debug point', 'memory')
        layer_dp = layer.dataProvider()

        layer_dp.addAttributes([
            QgsField('id_vertex', QVariant.Int),
            QgsField('in_arcs_nb', QVariant.Int),
            QgsField('out_arcs_nb', QVariant.Int),
            QgsField('arcs_nb', QVariant.Int)
        ])
        layer.updateFields()

        for id_vertex in self.get_id_vertices():
            vertex = self.get_vertex(id_vertex)

            feature = QgsFeature()
            # noinspection PyCallByClass
            geom = QgsGeometry.fromPoint(self.get_vertex_point(id_vertex))
            in_arcs_id = vertex.inArc()
            out_arcs_id = vertex.outArc()
            attributes = [
                id_vertex,
                len(in_arcs_id),
                len(out_arcs_id),
                len(in_arcs_id) + len(out_arcs_id)]
            feature.setAttributes(attributes)
            feature.setGeometry(geom)
            layer_dp.addFeatures([feature])
        layer.updateExtents()
        return layer
Ejemplo n.º 29
0
def createLayer(data, lname='default', extra_attrs=[]):
    feature = data[0]
    geomtag = {
            'PSK':'PSK_OBRAZ'
            , 'BZL':'BZL_OBRAZ'
            , 'JP':'JP_OBRAZ'
            , 'OP':'OP_OBRAZ'
            , 'KLO':'LIN_OBRAZ'
            , 'KTO':'TXT_OBRAZ'
            , 'KBO':'BOD_OBRAZ'
            , 'KPO':'PLO_OBRAZ'
            }[feature.tag]
    
    geomtype = {
            'L':'Linestring'
            , 'P':'Polygon'
            , 'B':'Point'
            , 'MB':'MultiPoint'
            , 'ML':'Multilinestring'
            , 'MP':'MultiPolygon'
            }[list(feature.find(geomtag))[0].tag]

    layer = QgsVectorLayer(geomtype + '?crs=EPSG:5514', lname, 'memory')
    
    attnames = feature.keys()
    attnames = attnames + extra_attrs
 
    pr = layer.dataProvider()
    
    pr.addAttributes(
            [QgsField(a, QVariant.String) for a in attnames])
            
    layer.updateFields()
    
    #populateLayer(layer, data)
       
    return(layer)
Ejemplo n.º 30
0
def nodeCreateVectorLayer(nodename, position='bottom',target_node=None,path=None,source="Point",crs=None,providertype="ESRI Shapefile",indexfieldname='id'):
    if target_node == None:
        target_node = QgsProject.instance().layerTreeRoot()
    else:
         if oeq_global.isStringOrUnicode(target_node):
            target_node = nodeByName(target_node)
            if len(target_node) == 0:
                return None
            target_node = target_node[0]

    if path == None:
        path= oeq_global.OeQ_project_path()
    if crs == None:
        crs = config.project_crs
    new_layer = QgsVectorLayer(source + '?crs=' + crs, nodename, "memory")
    new_layer.setProviderEncoding('System')
    #test
    dataprovider = new_layer.dataProvider()
    dataprovider.addAttributes([QgsField(indexfieldname, QVariant.Int)])
    new_layer.updateFields()
    writer = QgsVectorFileWriter.writeAsVectorFormat(new_layer, os.path.join(path , nodename+'.shp'), "System", new_layer.crs(), providertype)
    if writer != QgsVectorFileWriter.NoError:
        oeq_global.OeQ_push_error(title='Write Error:', message=os.path.join(path , nodename+'.shp'))
        return None
    del writer
    oeq_global.OeQ_wait_for_file(os.path.join(path , nodename+'.shp'))
    iface.addVectorLayer(os.path.join(path , nodename+'.shp'),nodename, 'ogr')
    #oeq_global.OeQ_wait_for_renderer(60000)
    new_node = nodeMove(nodename,position,target_node)
    new_layer = new_node.layer()
    #dataprovider = new_layer.dataProvider()
    #dataprovider.addAttributes([QgsField(indexfieldname,  QVariant.Int)])
    #new_layer.updateFields()

    #oeq_global.OeQ_unlockQgis()

    return new_node
Ejemplo n.º 31
0
    def testRenameAttributes(self):
        layer = QgsVectorLayer("Point", "test", "memory")
        provider = layer.dataProvider()

        res = provider.addAttributes([
            QgsField("name", QVariant.String),
            QgsField("age", QVariant.Int),
            QgsField("size", QVariant.Double)
        ])
        layer.updateFields()
        assert res, "Failed to add attributes"
        ft = QgsFeature()
        ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10)))
        ft.setAttributes(["Johny", 20, 0.3])
        res, t = provider.addFeatures([ft])

        # bad rename
        self.assertFalse(provider.renameAttributes({-1: 'not_a_field'}))
        self.assertFalse(provider.renameAttributes({100: 'not_a_field'}))
        # already exists
        self.assertFalse(provider.renameAttributes({1: 'name'}))

        # rename one field
        self.assertTrue(provider.renameAttributes({1: 'this_is_the_new_age'}))
        self.assertEqual(provider.fields().at(1).name(), 'this_is_the_new_age')
        layer.updateFields()
        fet = next(layer.getFeatures())
        self.assertEqual(fet.fields()[1].name(), 'this_is_the_new_age')

        # rename two fields
        self.assertTrue(
            provider.renameAttributes({
                1: 'mapinfo_is_the_stone_age',
                2: 'super_size'
            }))
        self.assertEqual(provider.fields().at(1).name(),
                         'mapinfo_is_the_stone_age')
        self.assertEqual(provider.fields().at(2).name(), 'super_size')
        layer.updateFields()
        fet = next(layer.getFeatures())
        self.assertEqual(fet.fields()[1].name(), 'mapinfo_is_the_stone_age')
        self.assertEqual(fet.fields()[2].name(), 'super_size')
Ejemplo n.º 32
0
class RFUDockWidget(QDockWidget, gui_dckwdgt_rfu_connector):

    closed = pyqtSignal()
    downloaded = pyqtSignal()
    uploaded = pyqtSignal()
    rfureset = pyqtSignal()

    def __init__(self, iface, canvas, project, conn=None, parent=None):

        super(RFUDockWidget, self).__init__(parent)
        self.setupUi(self)

        self.iface = iface
        self.canvas = canvas
        self.project = project
        self.conn = conn
        self.zone = None
        self.precision_class = []
        self.ellips_acronym = []
        self.dflt_ellips_acronym = None
        self.selected_ellips_acronym = None
        self.nature = []
        self.typo_nature_som = []
        self.typo_nature_lim = []
        self.auth_creator = []
        self.tol_same_pt = 0.0
        self.config = Configuration()
        self.url_rfu = self.config.base_url_rfu
        self.url = None
        self.refdoss_cmt = None

        self.l_vertex = None
        self.l_edge = None
        self.layers = [self.l_vertex, self.l_edge]

        # Initialize dicts which contains changed datasets
        self.edges_added = {}
        self.edges_added_ft = {}
        self.vertices_added = {}
        self.vertices_added_ft = {}
        self.edges_removed = {}
        self.vertices_removed = {}
        self.edges_modified = {}
        self.vertices_modified = {}

        self.downloadPushButton.clicked.connect(self.on_downloaded)
        # self.permalinkLineEdit.returnPressed.connect(self.on_downloaded)
        self.projComboBox.currentIndexChanged.connect(self.set_destination_crs)

        # Loads permalinks into the permalink combox
        self.load_permalinks()

        # Create the WMS layer (from Geofoncier)
        self.wms_urlwithparams = 'contextualWMSLegend=0&crs=EPSG:4326&dpiMode=1&featureCount=10&format=image/png&layers=RFU&styles=default&url='
        self.wms_urlwithparams += 'https://api.geofoncier.fr'  # self.url_rfu
        self.wms_urlwithparams += '/referentielsoge/ogc/wxs/?'
        self.l_wms = QgsRasterLayer(self.wms_urlwithparams,
                                    'Fond de plan RFU WMS', 'wms')
        # Define the contrast filter
        contrast_filter = QgsBrightnessContrastFilter()
        contrast_filter.setContrast(-100)
        # Assign filter to raster pipe
        self.l_wms.pipe().set(contrast_filter)

        # Add WMS layer to the registry
        self.project.addMapLayer(self.l_wms, True)

        # Apply changes to the WMS layer
        self.l_wms.triggerRepaint()

    def closeEvent(self, event):

        self.closed.emit()

    def on_downloaded(self):

        widget = self.iface.messageBar().createMessage(
            "Géofoncier", "Téléchargement du RFU.")

        progress_bar = QProgressBar()
        progress_bar.setMinimum(0)
        progress_bar.setMaximum(2)
        widget.layout().addWidget(progress_bar)

        self.iface.messageBar().pushWidget(widget)
        progress_bar.setValue(1)

        # https://pro.geofoncier.fr/index.php?&centre=-196406,5983255&context=metropole
        url = self.permalinkCmb.currentText()

        if not url:
            return self.abort_action(msg="Veuillez renseigner le permalien.")
        self.url = url

        try:
            self.download(self.url)
        except Exception as e:
            return self.abort_action(msg=str(e))

        self.save_permalinks(self.url)

        progress_bar.setValue(2)
        self.iface.messageBar().clearWidgets()

        return

    def on_reset(self):

        # Ensure that the action is intentional
        resp = QMessageBox.question(self, reinit_msg[0], reinit_msg[1],
                                    QMessageBox.Yes, QMessageBox.No)
        if resp == QMessageBox.Yes:
            self.reset()
            self.rfureset.emit()

        return

    def on_uploaded(self):

        self.uploaded.emit()

        # Create message
        self.widget = self.iface.messageBar().createMessage(
            "Géofoncier", "Envoi des modifications.")
        self.progress_bar = QProgressBar()
        self.progress_bar.setMinimum(0)
        self.progress_bar.setMaximum(3)
        self.widget.layout().addWidget(self.progress_bar)
        self.iface.messageBar().pushWidget(self.widget)
        self.progress_bar.setValue(1)

        # Specific dlg to manage the case of several doss with same ref
        self.refdoss_cmt = RefDossCmtEntry()
        self.refdoss_cmt.show()
        # Continue the process after capturing the dic of values
        self.refdoss_cmt.send_refdoss_cmt_vals.connect(
            self.on_uploaded_withref)

    # Continue the process after dlg validation
    def on_uploaded_withref(self, dic_vals):
        if dic_vals["ok"]:
            enr_ref_dossier = dic_vals["refdoss"]
            self.enr_cmt = dic_vals["cmt"]

            if not enr_ref_dossier:
                return self.abort_action(
                    msg="Merci de renseigner une référence de dossier.")

            # Create correct comment
            if not self.enr_cmt:
                self.enr_cmt = cmt_dft % enr_ref_dossier
            else:
                self.enr_cmt += " - " + cmt_dft % enr_ref_dossier

            dossiers = self.conn.dossiersoge_dossiers(self.zone,
                                                      enr_ref_dossier)

            dossiers_read = dossiers.read()
            # DEBUG: Export response as a text file
            # urlresp_to_file(dossiers_read)
            if dossiers.code != 200:
                return self.abort_action(msg=dossiers_read)

            data = json.loads(str(dossiers_read.decode('utf-8')))

            nb_dossiers = data["count"]

            if nb_dossiers == 0:
                return self.abort_action(
                    msg="Le dossier \'%s\' n'existe pas." % enr_ref_dossier)

            # Case of several same ref_dossier
            # In the case, the difference is made by enr_cab_createur
            if nb_dossiers >= 1:
                doss_infos = []
                for doss in data["results"]:
                    doss_info = []
                    doss_info.append(doss["enr_cab_createur"])
                    doss_info.append(doss["enr_ref_dossier"])
                    # doss_uri = doss.find(r"{http://www.w3.org/2005/Atom}link").attrib[r"href"].split(r"/")[-1][1:]
                    # doss_info.append(doss_uri)

                    # id = enr_api_dossier
                    doss_info.append(doss["id"])
                    doss_info.append(doss["zone"])
                    doss_infos.append(doss_info)
                if len(doss_infos) > 1:
                    self.doss_choice = MultiDossChoice(doss_infos)
                    # Modal window
                    self.doss_choice.setWindowModality(Qt.ApplicationModal)
                    self.doss_choice.show()
                    # Continue the process after capturing the dic of values
                    self.doss_choice.send_refapidoss.connect(
                        self.on_uploaded_proc)
                else:
                    self.on_uploaded_proc(doss_info[2])
        else:
            self.iface.messageBar().clearWidgets()

    # Launch the uploading after receiving the ref_api_doss
    def on_uploaded_proc(self, ref_api_doss):
        if ref_api_doss != "":
            self.progress_bar.setValue(2)
            # Stop editing mode
            for layer in self.layers:
                if layer.isEditable():
                    self.iface.setActiveLayer(layer)
                    layer.commitChanges()

            # Check if dataset changes
            if (self.edges_added or self.vertices_added or self.edges_removed
                    or self.vertices_removed or self.edges_modified
                    or self.vertices_modified):
                pass
            else:
                return self.abort_action(
                    msg="Aucune modification des données n'est détectée.")

            # Upload, reset and re-download datasets
            try:
                log = self.upload(enr_api_dossier=ref_api_doss,
                                  commentaire=self.enr_cmt)
                self.reset()
                self.permalinkCmb.setCurrentText(self.url)
                self.download(self.url)
                self.zoom_bbox()
                self.canvas.refresh()
            except Exception as e:
                self.reset()
                self.permalinkCmb.setCurrentText(self.url)
                self.download(self.url)
                self.zoom_bbox()
                self.canvas.refresh()
                return self.abort_action(msg="\n".join(e.args[0]))

            self.iface.messageBar().clearWidgets()

            return QMessageBox.information(self, r"Information",
                                           "\n".join(log))
        # Case of dlg mutidoss_choice cancelled
        else:
            QMessageBox.information(self, multi_doss_canceled_msg[0],
                                    multi_doss_canceled_msg[1])
            self.iface.messageBar().clearWidgets()

    def download(self, url):

        # Test if permalink is valid
        pattern = r"^(https?:\/\/(\w+[\w\-\.\:\/])+)\?((\&+)?(\w+)\=?([\w\-\.\:\,]+?)?)+(\&+)?$"
        if not re.match(pattern, self.url):
            raise Exception("Le permalien n'est pas valide.")

        # Extract params from url
        params = parse_qs(urlparse(self.url).query)

        # Check mandatory parameters
        try:
            context = str(params[r"context"][0])
            center = params[r"centre"][0]
        except:
            raise Exception(
                "Les paramètres \'Context\' et \'Centre\' sont obligatoires.")

        auth_contexts = [
            r"metropole", r"guadeloupe", r"stmartin", r"stbarthelemy",
            r"guyane", r"reunion", r"mayotte", r"martinique"
        ]

        # Check scale parameter
        try:
            scale = int(params[r"echelle"][0])
        except:
            raise Exception("Le paramètre \'Echelle\' est obligatoire.")
        else:
            if scale > scale_limit:
                raise Exception(wrong_scale_txt.format(str(scale_limit)))

        # Check if context is valid
        if context not in auth_contexts:
            raise Exception(
                "La valeur \'%s\' est incorrecte.\n\n"
                "\'Context\' doit prentre une des %s valeurs suivantes: "
                "%s" % (context, len(auth_contexts), ", ".join(auth_contexts)))

        self.zone = context
        if self.zone in [
                r"guadeloupe", r"stmartin", r"stbarthelemy", r"martinique"
        ]:
            self.zone = r"antilles"

        # Check if XY are valid
        if not re.match(r"^\-?\d+,\-?\d+$", center):
            raise Exception("Les coordonnées XY du centre sont incorrectes.")

        # Extract XY (&centre)
        xcenter = int(center.split(r",")[0])
        ycenter = int(center.split(r",")[1])

        # Compute the bbox
        xmin = xcenter - self.conn.extract_lim / 2
        xmax = xcenter + self.conn.extract_lim / 2
        ymin = ycenter - self.conn.extract_lim / 2
        ymax = ycenter + self.conn.extract_lim / 2

        # Transform coordinates in WGS84
        bbox = tools.reproj(QgsRectangle(xmin, ymin, xmax, ymax), 3857, 4326,
                            self.project)

        # Extract RFU (Send the request)
        resp = self.conn.extraction(bbox.xMinimum(), bbox.yMinimum(),
                                    bbox.xMaximum(), bbox.yMaximum())

        resp_read = resp.read()

        # DEBUG: Export response as a text file
        # urlresp_to_file(resp_read)

        if resp.code != 200:
            raise Exception(resp_read)
        tree = EltTree.fromstring(resp_read)
        # Check if error
        err = tree.find(r"./erreur")
        if err:
            raise Exception(err.text)

        # Create the layer: "Masque d'extraction"
        self.l_bbox = QgsVectorLayer(r"Polygon?crs=epsg:4326&index=yes",
                                     "Zone de travail", r"memory")

        p_bbox = self.l_bbox.dataProvider()

        simple_symbol = QgsFillSymbol.createSimple({
            r"color": r"116,97,87,255",
            r"style": r"b_diagonal",
            r"outline_style": r"no"
        })

        renderer_bbox = QgsInvertedPolygonRenderer(
            QgsSingleSymbolRenderer(simple_symbol))

        self.l_bbox.setRenderer(renderer_bbox)

        self.ft_bbox = QgsFeature()
        self.limit_area = QgsRectangle(bbox.xMinimum(), bbox.yMinimum(),
                                       bbox.xMaximum(), bbox.yMaximum())
        self.ft_bbox.setGeometry(QgsGeometry.fromRect(self.limit_area))
        p_bbox.addFeatures([self.ft_bbox])

        self.l_bbox.updateFields()
        self.l_bbox.updateExtents()

        # Create layers..
        self.layers = self.extract_layers(tree)
        self.l_vertex = self.layers[0]
        self.l_edge = self.layers[1]

        # Add layer to the registry
        self.project.addMapLayers([self.l_vertex, self.l_edge, self.l_bbox])

        # Set extent
        # self.canvas.setExtent(QgsRectangle(bbox.xMinimum(), bbox.yMinimum(),
        # bbox.xMaximum(), bbox.yMaximum()))

        self.features_vertex_backed_up = \
            dict((ft[r"fid"], ft) for ft in self.get_features(self.l_vertex))
        self.features_edge_backed_up = \
            dict((ft[r"fid"], ft) for ft in self.get_features(self.l_edge))

        # Get Capabitilies
        resp = self.conn.get_capabilities(self.zone)
        resp_read = resp.read()

        # DEBUG
        # urlresp_to_file(resp_read)

        if resp.code != 200:
            raise Exception(resp_read)

        tree = EltTree.fromstring(resp_read)

        # Find tolerance to determine if 2 points are equals
        for entry in tree.findall(r"./tolerance"):
            self.tol_same_pt = float(entry.text)

        err = tree.find(r"./erreur")
        if err:
            raise Exception(err.text)

        for entry in tree.findall(r"./classe_rattachement/classe"):
            t = (entry.attrib[r"som_precision_rattachement"], entry.text)
            self.precision_class.append(t)

        for entry in tree.findall(
                r"./representation_plane_sommet_autorise/representation_plane_sommet"
        ):
            t = (entry.attrib[r"som_representation_plane"],
                 entry.attrib[r"epsg_crs_id"], entry.text)
            self.ellips_acronym.append(t)

        # Added v2.1 <<
        for entry in tree.findall(r"./typologie_nature_sommet/nature"):
            self.typo_nature_som.append(entry.text)

        for entry in tree.findall(r"./nature_sommet_conseille/nature"):
            self.nature.append(entry.text)

        for entry in tree.findall(r"./typologie_nature_limite/nature"):
            self.typo_nature_lim.append(entry.text)
        # >>

        for entry in tree.findall(
                r"./som_ge_createur_autorise/som_ge_createur"):
            t = (entry.attrib[r"num_ge"], entry.text)
            self.auth_creator.append(t)

        try:
            ft = next(ft for ft in self.l_vertex.getFeatures())
            ft_attrib = tools.attrib_as_kv(ft.fields(), ft.attributes())
            self.dflt_ellips_acronym = ft_attrib[r"som_representation_plane"]
        except:
            self.dflt_ellips_acronym = None

        for i, e in enumerate(self.ellips_acronym):

            self.projComboBox.addItem(e[2])

            if not self.dflt_ellips_acronym and i == 0:
                self.project_crs = int(e[1])

            if self.dflt_ellips_acronym == e[0]:

                # Check projection in combobox
                self.projComboBox.setCurrentIndex(i)

                # Then change the CRS in canvas
                epsg_str = "EPSG:" + str(int(e[1]))
                crs = QgsCoordinateReferenceSystem(epsg_str)
                self.project.setCrs(crs)
                self.project_crs = int(e[1])

        # Calculate bbox in the project CRS (used for the scale limitation of the canvas)
        self.bbox_crsproject = tools.reproj(
            QgsRectangle(xmin, ymin, xmax, ymax), 3857, self.project_crs,
            self.project)

        # Zoom to bbox extents
        self.zoom_bbox()
        self.canvas.refresh()

        # Modified in v2.1 <<
        # Add the list of possible values to the field som_nature
        map_predefined_vals_to_fld(self.l_vertex, "som_typologie_nature",
                                   self.typo_nature_som)
        # Add the list of possible values to the field som_precision_rattachement
        map_predefined_vals_to_fld(self.l_vertex, "som_precision_rattachement",
                                   self.precision_class, 0, 1)
        # Add the list of possible values to the field som_precision_rattachement
        map_predefined_vals_to_fld(self.l_vertex, "som_representation_plane",
                                   self.ellips_acronym, 0, 2)
        # Add the list of possible values to the field lim_typologie_nature
        map_predefined_vals_to_fld(self.l_edge, "lim_typologie_nature",
                                   self.typo_nature_lim)
        # Add the list of possible values to the field som_delimitation_publique
        false_true_lst = [('False', 'Faux'), ('True', 'Vrai')]
        map_predefined_vals_to_fld(self.l_vertex, "som_delimitation_publique",
                                   false_true_lst, 0, 1)
        # Add the list of possible values to the field lim_delimitation_publique
        map_predefined_vals_to_fld(self.l_edge, "lim_delimitation_publique",
                                   false_true_lst, 0, 1)
        # >>

        # Then, start editing mode..
        for idx, layer in enumerate(self.layers):
            if not layer.isEditable():
                layer.startEditing()
            if idx == 0:
                self.iface.setActiveLayer(layer)

        self.projComboBox.setDisabled(False)

        self.permalinkCmb.setDisabled(True)
        self.downloadPushButton.setDisabled(True)
        self.resetPushButton.setDisabled(False)
        self.uploadPushButton.setDisabled(False)

        self.downloadPushButton.clicked.disconnect(self.on_downloaded)
        # self.permalinkLineEdit.returnPressed.disconnect(self.on_downloaded)
        self.resetPushButton.clicked.connect(self.on_reset)
        self.uploadPushButton.clicked.connect(self.on_uploaded)

        # Activate the scale limitation for the canvas
        self.canvas.scaleChanged.connect(self.limit_cvs_scale)

        self.downloaded.emit()

        return True

    def reset(self):
        """Remove RFU layers."""

        # Save (virtually) the changes in the layers
        # (to avoid alert messages when removing the layers)
        for layer in self.layers:
            if isinstance(layer, QgsVectorLayer):
                if layer.isEditable():
                    self.iface.setActiveLayer(layer)
                    layer.commitChanges()

        # Remove RFU layers
        try:
            self.project.removeMapLayers(
                [self.l_vertex.id(),
                 self.l_edge.id(),
                 self.l_bbox.id()])
        except:
            return

        # Remove eliminated lines layer
        if self.project.mapLayersByName(elimedge_lname):
            el_lyr = self.project.mapLayersByName(elimedge_lname)[0]
            self.iface.setActiveLayer(el_lyr)
            el_lyr.commitChanges()
            self.project.removeMapLayers([el_lyr.id()])

        # Reset variable
        self.precision_class = []
        self.ellips_acronym = []
        self.dflt_ellips_acronym = None
        self.nature = []
        self.typo_nature_lim = []
        self.typo_nature_som = []
        self.auth_creator = []
        self.l_vertex = None
        self.l_edge = None
        self.layers = [self.l_vertex, self.l_edge]
        self.edges_added = {}
        self.vertices_added = {}
        self.edges_removed = {}
        self.vertices_removed = {}
        self.edges_modified = {}
        self.vertices_modified = {}
        self.tol_same_pt = 0.0

        # Reset ComboBox which contains projections authorized
        self.projComboBox.clear()
        self.projComboBox.setDisabled(True)

        # Loads permalinks into the permalink combox
        self.load_permalinks()
        self.permalinkCmb.setDisabled(False)
        # self.permalinkLineEdit.returnPressed.connect(self.on_downloaded)

        self.downloadPushButton.setDisabled(False)
        self.downloadPushButton.clicked.connect(self.on_downloaded)

        self.resetPushButton.setDisabled(True)
        self.resetPushButton.clicked.disconnect(self.on_reset)

        self.uploadPushButton.setDisabled(True)
        self.uploadPushButton.clicked.disconnect(self.on_uploaded)

        return True

    def upload(self, enr_api_dossier=None, commentaire=None):
        """Upload data to Géofoncier REST API.
        On success returns the log messages (Array).

        """

        # Set XML document
        root = EltTree.Element(r"rfu")
        first_vtx_kept = True
        first_edge_kept = True
        # Add to our XML document datasets which have been changed
        if self.vertices_added:
            for fid in self.vertices_added:
                # Check if vertex is out of the bbox
                to_export = check_vtx_outofbbox(self.vertices_added_ft[fid],
                                                self.ft_bbox)
                if to_export:
                    tools.xml_subelt_creator(root,
                                             "sommet",
                                             data=self.vertices_added[fid],
                                             action=r"create")
                # If vertex is out of the bbox
                else:
                    # Create a new layer to store the vertices non exported
                    if first_vtx_kept:
                        if layer_exists(vtx_outofbbox_lname, self.project):
                            vtx_outofbbox_lyr = self.project.mapLayersByName(
                                vtx_outofbbox_lname)[0]
                        else:
                            vtx_outofbbox_lyr = create_vtx_outofbbox_lyr()
                    # Add the vertex to this layer
                    if not vtx_outofbbox_lyr.isEditable():
                        vtx_outofbbox_lyr.startEditing()
                    vtx_outofbbox_lyr.addFeature(self.vertices_added_ft[fid])
                    first_vtx_kept = False
        if self.edges_added:
            for fid in self.edges_added:
                # Check if edge is out of the bbox
                to_export = check_edge_outofbbox(self.edges_added_ft[fid],
                                                 self.ft_bbox)
                if to_export:
                    tools.xml_subelt_creator(root,
                                             "limite",
                                             data=self.edges_added[fid],
                                             action=r"create")
                # If edge is out of the bbox
                else:
                    # Create a new layer to store the edges non exported
                    if first_edge_kept:
                        if layer_exists(edge_outofbbox_lname, self.project):
                            edge_outofbbox_lyr = self.project.mapLayersByName(
                                edge_outofbbox_lname)[0]
                        else:
                            edge_outofbbox_lyr = create_edge_outofbbox_lyr()
                    # Add the edge to this layer
                    if not edge_outofbbox_lyr.isEditable():
                        edge_outofbbox_lyr.startEditing()
                    edge_outofbbox_lyr.addFeature(self.edges_added_ft[fid])
                    first_edge_kept = False
        if self.vertices_removed:
            for fid in self.vertices_removed:
                tools.xml_subelt_creator(root,
                                         "sommet",
                                         data=self.vertices_removed[fid],
                                         action=r"delete")
        if self.edges_removed:
            for fid in self.edges_removed:
                tools.xml_subelt_creator(root,
                                         "limite",
                                         data=self.edges_removed[fid],
                                         action=r"delete")
        if self.vertices_modified:
            for fid in self.vertices_modified:
                tools.xml_subelt_creator(root,
                                         "sommet",
                                         data=self.vertices_modified[fid],
                                         action=r"update")
        if self.edges_modified:
            for fid in self.edges_modified:
                tools.xml_subelt_creator(root,
                                         "limite",
                                         data=self.edges_modified[fid],
                                         action=r"update")
        # Create a new changeset Id
        changeset_id = self.create_changeset(enr_api_dossier=enr_api_dossier,
                                             commentaire=commentaire)
        # Add changeset value in our XML document
        root.attrib[r"changeset"] = changeset_id

        # Send data
        edit = self.conn.edit(self.zone, EltTree.tostring(root))
        if edit.code != 200:
            edit_read = edit.read()
            # DEBUG
            # urlresp_to_file(edit_read)
            err_tree = EltTree.fromstring(edit_read)
            msgs_log = []
            for log in err_tree.iter(r"log"):
                msgs_log.append("%s: %s" % (log.attrib["type"], log.text))
            raise Exception(msgs_log)
        tree = EltTree.fromstring(edit.read())
        err = tree.find(r"./erreur")
        if err:
            debug_msg('DEBUG', "erreur: %s", (str(err)))
            err_tree = EltTree.fromstring(err)
            msgs_log = []
            for log in err_tree.iter(r"log"):
                msgs_log.append("%s: %s" % (log.attrib["type"], log.text))
            raise Exception(msgs_log)

        # Returns log info
        msgs_log = []
        for log in tree.iter(r"log"):
            msgs_log.append("%s: %s" % (log.attrib["type"], log.text))

        # Close the changeset
        self.destroy_changeset(changeset_id)

        # Reset all
        self.edges_added = {}
        self.edges_added_ft = {}
        self.vertices_added = {}
        self.vertices_added_ft = {}
        self.edges_removed = {}
        self.vertices_removed = {}
        self.edges_modified = {}
        self.vertices_modified = {}

        # Alert message if elements out of bbox
        msg_outbbox = ""
        if not first_vtx_kept:
            msg_outbbox = msg_outbbox_vtx.format(vtx_outofbbox_lname)
        if not first_edge_kept:
            if msg_outbbox != "":
                msg_outbbox += "<br>"
            msg_outbbox += msg_outbbox_edge.format(edge_outofbbox_lname)
        if msg_outbbox != "":
            self.canvas.refresh()
            m_box = mbox_w_params(tl_atn, txt_msg_outbbox, msg_outbbox)
            m_box.exec_()
        return msgs_log

    def create_changeset(self, enr_api_dossier=None, commentaire=None):
        """Open a new changeset from Géofoncier API.
        On success, returns the new changeset id.

        """

        opencs = self.conn.open_changeset(self.zone,
                                          enr_api_dossier=enr_api_dossier,
                                          commentaire=commentaire)
        if opencs.code != 200:
            raise Exception(opencs.read())

        tree = EltTree.fromstring(opencs.read())

        err = tree.find(r"./log")
        if err:
            raise Exception(err.text)

        # treeterator = list(tree.getiterator(tag=r"changeset"))
        # Python 3.9 -> getiterator deprecated
        treeterator = list(tree.iter(tag=r"changeset"))

        # We should get only one changeset
        if len(treeterator) != 1:
            raise Exception("Le nombre de \'changeset\' est incohérent.\n"
                            "Merci de contacter l'administrateur Géofoncier.")

        return treeterator[0].attrib[r"id"]

    def destroy_changeset(self, id):
        """Close a changeset."""

        closecs = self.conn.close_changeset(self.zone, id)

        if closecs.code != 200:
            raise Exception(closecs.read())

        tree = EltTree.fromstring(closecs.read())

        err = tree.find(r"./log")
        if err:
            raise Exception(err.text)

        return True

    def abort_action(self, msg=None):

        for layer in self.layers:
            if layer and not layer.isEditable():
                layer.startEditing()

        # Clear message bar
        self.iface.messageBar().clearWidgets()

        if msg:
            return QMessageBox.warning(self, r"Attention", msg)

        return

    def extract_layers(self, tree):
        """Return a list of RFU layers."""

        # Create vector layers..
        l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes",
                                  "Sommet RFU", r"memory")
        l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes",
                                "Limite RFU", r"memory")

        p_vertex = l_vertex.dataProvider()
        p_edge = l_edge.dataProvider()

        # Define default style renderer..
        renderer_vertex = QgsRuleBasedRenderer(QgsMarkerSymbol())
        vertex_root_rule = renderer_vertex.rootRule()

        # Modified in v2.1 (som_nature replaced by som_typologie_nature) >>
        vertex_rules = (
            (("Borne, borne à puce, pierre, piquet, clou ou broche"),
             ("$id >= 0 AND \"som_typologie_nature\" IN ('Borne',"
              "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"),
             r"#EC0000", 2.2),
            (("Axe cours d'eau, axe fossé, haut de talus, pied de talus"),
             ("$id >= 0 AND \"som_typologie_nature\" IN ('Axe cours d\'\'eau',"
              "'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012",
             2.2), (("Angle de bâtiment, axe de mur, angle de mur, "
                     "angle de clôture, pylône et toute autre valeur"),
                    ("$id >= 0 AND \"som_typologie_nature\" NOT IN ('Borne',"
                     "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche',"
                     "'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus',"
                     "'Pied de talus')"), r"#9784EC", 2.2),
            ("Temporaire", r"$id < 0", "cyan",
             2.4), ("Point nouveau à traiter car proche d'un existant",
                    r"point_rfu_proche is not null", "#bcff03", 3))

        # >>

        for label, expression, color, size in vertex_rules:
            rule = vertex_root_rule.children()[0].clone()
            rule.setLabel(label)
            rule.setFilterExpression(expression)
            rule.symbol().setColor(QColor(color))
            rule.symbol().setSize(size)
            vertex_root_rule.appendChild(rule)

        vertex_root_rule.removeChildAt(0)
        l_vertex.setRenderer(renderer_vertex)

        renderer_edge = QgsRuleBasedRenderer(QgsLineSymbol())
        edge_root_rule = renderer_edge.rootRule()

        # Modified in v2.1 (lim_typologie_nature added) <<
        edge_rules = (("Limite privée",
                       "$id >= 0 AND \"lim_typologie_nature\" = '" +
                       lim_typo_nat_vals[0] + "'", "#0A0AFF", 0.5),
                      ("Limite naturelle",
                       "$id >= 0 AND \"lim_typologie_nature\" = '" +
                       lim_typo_nat_vals[1] + "'", "#aa876d", 0.5),
                      ("Temporaire", "$id < 0", "cyan", 1))

        # >>

        for label, expression, color, width in edge_rules:
            rule = edge_root_rule.children()[0].clone()
            rule.setLabel(label)
            rule.setFilterExpression(expression)
            rule.symbol().setColor(QColor(color))
            rule.symbol().setWidth(width)
            edge_root_rule.appendChild(rule)

        edge_root_rule.removeChildAt(0)
        l_edge.setRenderer(renderer_edge)

        # Add fields..
        p_vertex.addAttributes(vtx_atts)

        p_edge.addAttributes(edge_atts)

        # Add features from xml tree..
        # ..to vertex layer..
        fts_vertex = []
        for e in tree.findall(r"sommet"):

            ft_vertex = QgsFeature()
            ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"]))
            _id_noeud = int(e.attrib[r"id_noeud"])
            _version = int(e.attrib[r"version"])
            som_ge_createur = str(e.find(r"./som_ge_createur").text)
            som_nature = str(e.find(r"./som_nature").text)
            som_prec_rattcht = int(
                e.find(r"./som_precision_rattachement").text)
            som_coord_est = float(e.find(r"./som_coord_est").text)
            som_coord_nord = float(e.find(r"./som_coord_nord").text)
            som_repres_plane = str(e.find(r"./som_representation_plane").text)
            som_tolerance = float(e.find(r"./som_tolerance").text)
            # Field used to store the attestation_qualite value
            # when modifying a vertex ("false" or "true")
            attestation_qualite = "false"

            som_delim_pub = str(e.find(r"./som_delimitation_publique").text)
            som_typo_nature = str(e.find(r"./som_typologie_nature").text)

            ft_vertex.setAttributes([
                _id_noeud, _version, som_ge_createur, som_delim_pub,
                som_typo_nature, som_nature, som_prec_rattcht, som_coord_est,
                som_coord_nord, som_repres_plane, som_tolerance,
                attestation_qualite, NULL
            ])

            fts_vertex.append(ft_vertex)

        # ..to edge layer..
        fts_edge = []
        for e in tree.findall(r"limite"):

            ft_edge = QgsFeature()
            ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"]))
            _id_arc = int(e.attrib[r"id_arc"])
            _version = int(e.attrib[r"version"])
            lim_ge_createur = str(e.find(r"./lim_ge_createur").text)

            lim_typo_nature = str(e.find(r"./lim_typologie_nature").text)
            lim_delim_pub = str(e.find(r"./lim_delimitation_publique").text)

            ft_edge.setAttributes([
                _id_arc, _version, lim_ge_createur, lim_delim_pub,
                lim_typo_nature
            ])

            fts_edge.append(ft_edge)

        # Add features to layers..
        p_vertex.addFeatures(fts_vertex)
        p_edge.addFeatures(fts_edge)

        # Update fields..
        l_vertex.updateFields()
        l_edge.updateFields()

        # Update layer's extent..
        l_vertex.updateExtents()
        l_edge.updateExtents()

        # Check if valid..
        if not l_vertex.isValid() or not l_edge.isValid():
            raise Exception(
                "Une erreur est survenue lors du chargement de la couche.")

        # Then return layers..
        return [l_vertex, l_edge]

    def get_features(self, layer):

        features = []
        for ft in layer.getFeatures():
            attributes = tools.attrib_as_kv(ft.fields(), ft.attributes())
            attributes[r"fid"] = ft.id()
            features.append(attributes)

        return features

    def remove_features(self, layer_id, fids):

        for fid in fids:

            if layer_id == self.l_edge.id(
            ) and fid in self.features_edge_backed_up:
                self.edges_removed[fid] = self.features_edge_backed_up[fid]

            if layer_id == self.l_vertex.id(
            ) and fid in self.features_vertex_backed_up:
                self.vertices_removed[fid] = self.features_vertex_backed_up[
                    fid]

    def add_features(self, layer_id, features):

        for ft in features:

            attrib = tools.attrib_as_kv(ft.fields(),
                                        ft.attributes(),
                                        qgsgeom=ft.geometry())

            if layer_id == self.l_vertex.id():
                self.vertices_added[ft.id()] = attrib
                self.vertices_added_ft[ft.id()] = ft

            if layer_id == self.l_edge.id():
                self.edges_added[ft.id()] = attrib
                self.edges_added_ft[ft.id()] = ft

    def modify_feature(self, layer_id, feature, qgsgeom=None):

        if qgsgeom:
            f = tools.attrib_as_kv(feature.fields(),
                                   feature.attributes(),
                                   qgsgeom=qgsgeom)
        else:
            f = tools.attrib_as_kv(feature.fields(), feature.attributes())

        if self.l_edge.id() == layer_id:
            if feature.id() not in self.features_edge_backed_up:
                return
            self.edges_modified[feature.id()] = f

        if self.l_vertex.id() == layer_id:
            if feature.id() not in self.features_vertex_backed_up:
                return
            self.vertices_modified[feature.id()] = f

    def set_destination_crs(self, j):

        epsg = 4326  # by default
        for i, e in enumerate(self.ellips_acronym):
            if i == j:
                self.selected_ellips_acronym = e[0]
                epsg = int(e[1])
                continue

        epsg_str = "EPSG:" + str(epsg)
        crs = QgsCoordinateReferenceSystem(epsg_str)
        self.project.setCrs(crs)

    # Stop zoom when the scale limit is exceeded
    def limit_cvs_scale(self):
        if self.canvas.scale() > cvs_scale_limit:
            self.disconn_scale_limit()
            self.zoom_bbox()
            self.canvas.zoomScale(cvs_scale_limit)
            self.canvas.scaleChanged.connect(self.limit_cvs_scale)

    def zoom_bbox(self):
        self.canvas.setExtent(
            QgsRectangle(self.bbox_crsproject.xMinimum(),
                         self.bbox_crsproject.yMinimum(),
                         self.bbox_crsproject.xMaximum(),
                         self.bbox_crsproject.yMaximum()))

    def disconn_scale_limit(self):
        self.canvas.scaleChanged.disconnect(self.limit_cvs_scale)

    def conn_scale_limit(self):
        self.canvas.scaleChanged.connect(self.limit_cvs_scale)

    # Loads permalinks from the json file into the combobox
    def load_permalinks(self):
        try:
            self.json_path = os.path.join(os.path.dirname(__file__),
                                          r"permalinks.json")
        except IOError as error:
            raise error
        with codecs.open(self.json_path, encoding='utf-8',
                         mode='r') as json_file:
            json_permalinks = json.load(json_file)
            self.permalinks = json_permalinks[r"permalinks"]
            current_permalink_idx = json_permalinks[r"current_permalink_idx"]
        if len(self.permalinks) > 0:
            self.permalinkCmb.clear()
            for idx, permalink in enumerate(self.permalinks):
                self.permalinkCmb.addItem(permalink)
            self.permalinkCmb.setCurrentIndex(current_permalink_idx)
            # self.permalinkCmb.lineEdit().selectAll()

    # Save permalinks in the json file (limited to 5 permalinks)
    def save_permalinks(self, permalink):
        # Update the json file
        json_permalinks = {}
        if permalink not in self.permalinks:
            # Update the permalinks list
            if len(self.permalinks) == 5:
                del self.permalinks[0]
            self.permalinks.append(permalink)
            json_permalinks["current_permalink_idx"] = len(self.permalinks) - 1
        else:
            json_permalinks[
                "current_permalink_idx"] = self.permalinkCmb.currentIndex()
        json_permalinks["permalinks"] = self.permalinks

        with codecs.open(self.json_path, encoding='utf-8',
                         mode='w') as json_file:
            json_file.write(
                json.dumps(json_permalinks,
                           indent=4,
                           separators=(',', ': '),
                           ensure_ascii=False))
Ejemplo n.º 33
0
    def action_grid(self):
        """Perform whatever action the grid tab specified"""

        # Find out if we need to create a new layer, or we're editing
        # an existing one
        if self.rbTemplate.isChecked():
            # Find out if it's a vector layer, ignore type of geometry
            layer_template = QgsVectorLayer(self.leTemplate.text(), 'Template',
                                            'ogr')
            if not layer_template.isValid():
                QMessageBox.critical(self, "Error", "Couldn't load layer!")
                return
            # Read field map
            fields = layer_template.fields()
            # Creat a new memory layer with same crs.
            layerOut = QgsVectorLayer(
                "Point?crs={}".format(layer_template.crs().authid()),
                "Inventory points", "memory")
            pr = layerOut.dataProvider()
            # Set fields
            pr.addAttributes(fields)
            # Tell the vector layer to fetch changes from the provider
            layerOut.updateFields()
        elif self.rbExisting.isChecked():
            # Check if it's a point vector layer
            # Is it already opened in QGIS?
            QMessageBox.information(self, "Info", "Not implemented")
            return
        idName = self.findNameField(fields)
        dateName = self.findDateField(fields)
        # # # Find the feature we're putting a point in
        # First, the layer
        stand_layer_idx = self.cbLayer.currentIndex()
        stand_layer_id = self.cbLayer.itemData(stand_layer_idx)
        stand_layer = QgsMapLayerRegistry.instance().mapLayer(stand_layer_id)
        # Then, the stand and geometry.
        stand_layer_geometries = [
            f.geometry() for f in stand_layer.selectedFeaturesIterator()
        ]
        # Check for projections
        geom_crs = stand_layer.crs()
        if geom_crs.geographicFlag():
            # This is not a projected layer. If layerOut
            # isn't either, we will abort. Need a projected
            # crs for calculating points etc.
            if layerOut.crs().geographicFlag():
                # Oops. Tell the customer
                QMessageBox.critical(
                    self, "Error", "Neither input our output\
                layer are projected. Change either layer crs to a projected\
                crs")
                return
            # OK, stand_layer is geographic, but layerout is projected
            # Transform all the geometries to layerOut
            geom_crs = layerOut.crs()
            xform = QgsCoordinateTransform(stand_layer.crs(), geom_crs)
            # Modify in-place.
            for i, g in enumerate(stand_layer_geometries):
                g.transform(xform)
                stand_layer_geometries[i] = g
        if not len(stand_layer_geometries):
            QMessageBox.critical(self, "Error!", "No stand selected!")
            return
        stand_layer_geom = stand_layer_geometries[0]
        # Find out how many points we want to add
        MIN_AREA = 10000
        MAX_AREA = 50000
        da = QgsDistanceArea()
        da.setSourceCrs(geom_crs)
        sqr_meters = da.measureArea(stand_layer_geom)
        nr_of_points = self.interpolate_points_sqrt(
            sqr_meters, MIN_AREA, int(self.sbMinPoint.value()), MAX_AREA,
            int(self.sbMaxPoint.value()))
        # print "Points:", nr_of_points
        # Add a buffer to avoid the border. Use half of the minimum distance.
        min_distance = 25
        stand_layer_geom = stand_layer_geom.buffer(-min_distance / 2, 12)
        # Distribute points
        bb = stand_layer_geom.boundingBox()
        nr_of_iter = nr_of_points * 200
        points = []
        for i in range(0, nr_of_iter):
            p_x = random.uniform(bb.xMinimum(), bb.xMaximum())
            p_y = random.uniform(bb.yMinimum(), bb.yMaximum())
            p = QgsGeometry.fromPoint(QgsPoint(p_x, p_y))
            if (stand_layer_geom.contains(p)
                    and self.checkDistance(points, p, min_distance)):
                points.append(p)
                nr_of_points = nr_of_points - 1
                if not nr_of_points:
                    break
        # Check if we managed to place enough points
        if nr_of_points:
            QMessageBox.information(
                self, "Warning", "Couldn't add requested number of points. " +
                "Please adjust number of points or minimum spacing, " +
                "if more points are needed")
        # Set feature xform
        xform = QgsCoordinateTransform(geom_crs, layerOut.crs())
        # Add points to layer and display layer
        layerOut.startEditing()
        layerOut.beginEditCommand("Adding points")
        n = 0
        for p in points:
            # Transform to output layer crs
            p.transform(xform)
            fet = QgsFeature(fields)
            fet.setGeometry(p)
            if idName != '':
                fet.setAttribute(idName, 'p{}'.format(n))
            if dateName != '':
                fet.setAttribute(dateName, datetime.date.today().isoformat())
            if not layerOut.addFeatures([fet]):
                QMessageBox.critical(self, "Error", "addFeatures()")
            n = n + 1
        layerOut.endEditCommand()
        QgsMapLayerRegistry.instance().addMapLayer(layerOut)
Ejemplo n.º 34
0
    def get_layer(self):

        # Feature store:
        features = []

        for fichero, fecha in dict(zip(self.ficheros, self.fechas)).items():

            reader = vtk.vtkXMLUnstructuredGridReader()
            reader.SetFileName(fichero)
            reader.Update()
            nvars = reader.GetOutput().GetPointData().GetNumberOfArrays()

            vars = []

            for i in range(nvars):
                var = reader.GetOutput().GetPointData().GetArrayName(i)
                # print(var)
                vars.append(var)

            if len(vars) == 1:
                QgsMessageLog.logMessage("No data in file: %s date: %s " %
                                         (fichero, fecha),
                                         PLUGIN_NAME,
                                         level=Qgis.Info)
                continue
            else:
                QgsMessageLog.logMessage("Processing file: %s date: %s " %
                                         (fichero, fecha),
                                         PLUGIN_NAME,
                                         level=Qgis.Info)

            # Coordinates reading by this way:
            coordenadas = vtk_to_numpy(
                reader.GetOutput().GetPoints().GetData())
            x = coordenadas[:, 0]
            y = coordenadas[:, 1]

            arrays = {}
            for var in vars:
                arrays[var] = vtk_to_numpy(
                    reader.GetOutput().GetPointData().GetArray(var))

            i = 0
            for X, Y in zip(x, y):
                punto = ogr.Geometry(ogr.wkbPoint)
                punto.AddPoint(X, Y)

                geom = QgsGeometry.fromWkt(punto.ExportToWkt())
                feature = QgsFeature()
                feature.setGeometry(geom)

                feature.setAttributes([
                    int(arrays['id'][i]),
                    fecha,
                    int(arrays['source'][i]),
                    # float(arrays['velocity'] [i]),
                    int(arrays['state'][i]),
                    float(arrays['age'][i]),
                ])
                features.append(feature)
                i += 1

        vector_layer = QgsVectorLayer("Point?crs=epsg:4326",
                                      "temporary_points", "memory")
        #  vector_layer = QgsVectorLayer("%s/output.shp&Point?crs=epsg:4326" % self.path, "temporary_points", "ogr")

        pr = vector_layer.dataProvider()
        pr.addAttributes([
            QgsField("id", QVariant.Int),
            QgsField("time", QVariant.String),
            QgsField("source", QVariant.Int),
            # QgsField("velocity", QVariant.Double),
            QgsField("state", QVariant.Int),
            QgsField("age", QVariant.Double),
        ])
        vector_layer.updateFields()
        pr.addFeatures(features)
        proyecto = QgsProject.instance()
        proyecto.addMapLayer(vector_layer)
Ejemplo n.º 35
0
    def createAnalysis(self):

        newTableName = self.dlg.cmbAnalysis.currentText()

        analysisLayerList = self.projectInstance.mapLayersByName(newTableName)
        if len(analysisLayerList) == 0:
            analysisLayer = QgsVectorLayer("Polygon?crs=EPSG:2056",
                                           newTableName, "memory")
            analysisDp = analysisLayer.dataProvider()
            analysisCreateNewLayer = True
        elif len(analysisLayerList) == 1:
            analysisLayer = analysisLayerList[0]
            analysisDp = analysisLayer.dataProvider()
            analysisCreateNewLayer = False

        # Delete all existing features in layer if applicable
        iter = analysisLayer.getFeatures()
        featuresToDelete = []
        for feature in iter:
            featuresToDelete.append(feature.id())
        analysisDp.deleteFeatures(featuresToDelete)

        # Check if one analysis is selected
        selectedIndex = self.dlg.cmbAnalysis.currentIndex()
        if selectedIndex == 0:
            self.messageBar.pushWarning("Erreur ",
                                        str(u"Sélectionnez une analyse!"))
            return

        # Get the analysis parameters
        params = self.getAnalysisFromDb()
        self.qstr = params["querystring"]
        if self.qstr is None or self.qstr == "":
            self.messageBar.pushWarning(
                "Erreur",
                str(u"Requête mal définie") + self.qstr)
            return

        # Validate user inputs
        if (self.dlg.lnYearStart.text() == "" and params["date_filtering"]
                and not self.dlg.chkLastSurvey.isChecked()):

            self.messageBar.pushCritical(
                "Erreur", "Vous devez saisir une date " + newTableName)
            return

        if ((self.dlg.lnYearStart.text() == ""
             or self.dlg.lnYearEnd.text() == "") and params["date_filtering"]
                and params["timerange_filtering"]):

            self.messageBar.pushCritical(
                "Erreur", "Vous devez  saisir 2 dates" + newTableName)
            return

        # Adapt connection string if applicable - method could be cleaner...
        if (params["date_filtering"]
                and not self.dlg.chkLastSurvey.isChecked()
                and not params["timerange_filtering"]):

            self.qstr = self.qstr.replace(
                '--EDITTIMESELECT',
                ' ,' + self.dlg.lnYearStart.text() + ' annee ')
            self.qstr = self.qstr.replace(
                '--EDITTIMESTRING', ' AND ' + params["datefield"] + ' = ' +
                self.dlg.lnYearStart.text())

        if (params["date_filtering"] and self.dlg.chkLastSurvey.isChecked()
                and not params["timerange_filtering"]):

            self.qstr = self.qstr.replace(
                '--EDITTIMESELECT',
                ' , max(' + params["datefield"] + ') annee ')

        if (params["date_filtering"] and params["timerange_filtering"]):
            self.qstr = self.qstr.replace('--STARTYEAR',
                                          self.dlg.lnYearStart.text())
            self.qstr = self.qstr.replace('--ENDYEAR',
                                          self.dlg.lnYearEnd.text())

        coupeFilter = self.dlg.lnCoupeType.text()
        self.editCoupeFilter(coupeFilter, params["coupetype_filtering"])

        admFilter = self.dlg.txtAdmShortName.text()
        self.editAdmFilter(admFilter)

        # Advanced users and developers can see and edit the Query string
        if self.dlg.btAdvancedUserMode.isChecked():
            self.qstr = self.dlg.txtMssqlQuery.toPlainText()
        # Get the geometric layer from PostGIS
        pgLayer = self.pgdb.getLayer(params["join_target_schema"],
                                     params["join_target_table"], "geom", "",
                                     params["join_target_table"], "fake_id")

        if not pgLayer:
            self.messageBar.pushCritical(
                "Erreur au chargement de la couche",
                params["join_target_schema"] + '.' +
                params["join_target_table"])
            return

        # Execute the query and parse the results
        query = QSqlQuery(self.qtmsdb)
        query.exec_(self.qstr)
        # TODO: Check query validity
        query.setForwardOnly(True)

        # Create memory layer and add it to LegendInterface
        joinTableName = "SELVANS"
        selvansTable = QgsVectorLayer("Point?crs=EPSG:2056", joinTableName,
                                      "memory")

        selvansTableProvider = selvansTable.dataProvider()

        # Add fields with type given as defined in table main.analysis
        fieldList = params["field_of_interest"].split(",")
        joinedFieldsNames = []
        if params["field_of_interest_type"] == "number":
            for fieldname in fieldList:
                selvansTableProvider.addAttributes(
                    [QgsField(params["join_source_fkfield"], QVariant.Int)])
                selvansTableProvider.addAttributes(
                    [QgsField(fieldname, QVariant.Double)])
                joinedFieldsNames.append(joinTableName + '_' + fieldname)
        else:
            for fieldname in fieldList:
                selvansTableProvider.addAttributes(
                    [QgsField(params["join_source_fkfield"], QVariant.Int)])
                selvansTableProvider.addAttributes(
                    [QgsField(fieldname, QVariant.String)])
                joinedFieldsNames.append(joinTableName + '_' + fieldname)

        # Some more field are required for tables related to surveys
        if params["date_filtering"]:
            selvansTableProvider.addAttributes(
                [QgsField('ANNEE_VALEUR', QVariant.Int)])

            joinedFieldsNames.append(joinTableName + '_' + 'ANNEE_VALEUR')
            fieldList.append('ANNEE_VALEUR')
            selvansTableProvider.addAttributes(
                [QgsField('DIV_SERIE', QVariant.String)])

            joinedFieldsNames.append(joinTableName + '_DIV_SERIE')
            fieldList.append('DIV_SERIE')

        # Create progress bar
        progress = self.createProgressbar(query.numRowsAffected())

        selvansTable.updateFields()

        # Parse the query result and add the features to memory layer
        self.fillSelvansTable(query, selvansTableProvider, progress, fieldList,
                              params["join_source_fkfield"])

        selvansTable.updateFields()
        self.projectInstance.addMapLayer(selvansTable, False)
        self.projectInstance.addMapLayer(pgLayer, False)
        self.messageBar.clearWidgets()

        # Join the memory layer to a geographic PG layer
        # NOTE: layers MUST be added to the project for join to work in pyQGIS
        targetlayer = self.joinLayer(pgLayer, params["join_target_pkfield"],
                                     selvansTable,
                                     params["join_source_fkfield"])

        # Get the fields names of the PG layer
        fields = targetlayer.fields()
        fieldslist = []
        for field in fields:
            fieldslist.append(field)
        # Copy the features to the result layer
        analysisDp.deleteAttributes(analysisDp.attributeIndexes())
        analysisLayer.updateFields()
        analysisDp.addAttributes(fieldslist)
        analysisLayer.updateFields()

        outFeat = QgsFeature()
        iter = targetlayer.getFeatures()

        for inFeat in iter:
            if inFeat.geometry():
                outFeat.setGeometry(inFeat.geometry())
                outFeat.setAttributes(inFeat.attributes())
                analysisDp.addFeatures([outFeat])

        analysisLayer.updateFields()
        # QgsProject.instance().addMapLayer(analysisLayer)

        if self.dlg.chkSaveAnalysisResult.isChecked():
            self.saveAnalysisToDisk(analysisLayer)

        if analysisCreateNewLayer:
            self.messageBar.pushCritical(
                "Avertissement",
                str(u"La couche est manquante - " +
                    u"mettre à jour l'impression..."))

            root = QgsProject.instance().layerTreeRoot()
            sgeoGroup = root.findGroup('Analyses SELVANS')
            if sgeoGroup:
                sgeoGroup.addLayer(analysisLayer)
            else:
                QgsProject.instance().addMapLayer(analysisLayer)

        self.activateLastAnalysis(analysisLayer)
        if qversion == 3:
            self.expandGroup("Analyses SELVANS", True)
        else:
            print("handle that too")
        # 24.11.2016: deactivated for now
        self.setStyleFromDb(params, pgLayer, analysisLayer)
        analysisLayer.triggerRepaint()

        # Zoom to selected administration(s)
        self.zoomToSelectedAdministration(admFilter)

        # remove temporary map layers from project
        # Backward compatibility QGIS3=>2
        if qversion == 3:
            self.projectInstance.removeMapLayer(selvansTable)
            self.projectInstance.removeMapLayer(pgLayer)
        else:
            print("handle that")
Ejemplo n.º 36
0
    def on_btnSave_released(self):
        layer = QgsVectorLayer(
            "MultiLineString?crs={}".format(
                QgsProject.instance().crs().authid()),
            "Lines",
            "memory",
        )

        #QgsProject.instance().addMapLayer(layer)
        layer.startEditing()
        layer.dataProvider().addAttributes([QgsField("num", QVariant.Int)])
        layer.dataProvider().addAttributes([QgsField("row", QVariant.Int)])
        layer.dataProvider().addAttributes([QgsField("column", QVariant.Int)])
        layer.updateFields()
        feats = []

        columnGap = self.columnGap.value()
        rowGap = self.rowGap.value()
        fid = 0
        lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines)
        feature = QgsFeature(fid)
        feature.setAttributes([str(fid)])
        feature.setGeometry(lin)
        feats.append(feature)
        g = feature.geometry()
        rowBuffer = g.buffer(rowGap / 2, 5)

        fid = 1
        lin = QgsGeometry.fromMultiPolylineXY(self.mt.columnLines)
        feature = QgsFeature(fid)
        feature.setAttributes([str(fid)])
        feature.setGeometry(lin)
        feats.append(feature)
        columnBuffer = lin.buffer(columnGap / 2, 5)

        layer.dataProvider().addFeatures(feats)

        # layer.loadNamedStyle(self.plugin_dir + "/lines.qml")
        layer.commitChanges()

        # Generate index lines

        if self.cbReverseRows.isChecked():
            leftEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pA, self.mt.pD
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())
            rightEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pB, self.mt.pC
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())
        else:
            leftEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pD, self.mt.pA
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())
            rightEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pC, self.mt.pB
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())

        # Plot edges lines
        polyline_rows = list(zip(leftEdge[1::2], rightEdge[1::2]))
        if self.cbReverseColumns.isChecked():
            backSide = (QgsGeometry.fromPolylineXY([
                self.mt.pB, self.mt.pA
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
            frontSide = (QgsGeometry.fromPolylineXY([
                self.mt.pC, self.mt.pD
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
        else:
            backSide = (QgsGeometry.fromPolylineXY([
                self.mt.pA, self.mt.pB
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
            frontSide = (QgsGeometry.fromPolylineXY([
                self.mt.pD, self.mt.pC
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
        polyline_columns = list(zip(backSide[1::2], frontSide[1::2]))

        # Generate Row lines
        iRowLayer = QgsVectorLayer(
            "MultiLineString?crs={}".format(
                QgsProject.instance().crs().authid()),
            "Index Rows",
            "memory",
        )

        #QgsProject.instance().addMapLayer(iRowLayer)
        iRowLayer.startEditing()
        iRowLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)])
        iRowLayer.updateFields()
        feats = []

        row = 1
        lines_rows = QgsGeometry.fromMultiPolylineXY(polyline_rows)
        for p in lines_rows.asGeometryCollection():
            feature = QgsFeature(fid)
            feature.setAttributes([row])
            feature.setGeometry(p)
            feats.append(feature)
            row += 1

        iRowLayer.dataProvider().addFeatures(feats)
        iRowLayer.commitChanges()

        # Generate Column lines
        iColLayer = QgsVectorLayer(
            "MultiLineString?crs={}".format(
                QgsProject.instance().crs().authid()),
            "Index Columns",
            "memory",
        )

        #QgsProject.instance().addMapLayer(iColLayer)
        iColLayer.startEditing()
        iColLayer.dataProvider().addAttributes(
            [QgsField("column", QVariant.Int)])
        iColLayer.updateFields()
        feats = []

        column = 1
        lines_columns = QgsGeometry.fromMultiPolylineXY(polyline_columns)
        for p in lines_columns.asGeometryCollection():
            feature = QgsFeature(fid)
            feature.setAttributes([column])
            feature.setGeometry(p)
            feats.append(feature)
            column += 1
        iColLayer.dataProvider().addFeatures(feats)
        iColLayer.commitChanges()

        pLayer = QgsVectorLayer(
            "Polygon?crs={}".format(QgsProject.instance().crs().authid()),
            "Polygons",
            "memory",
        )
        #QgsProject.instance().addMapLayer(pLayer)
        pLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)])
        pLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)])
        pLayer.dataProvider().addAttributes([QgsField("column", QVariant.Int)])
        pLayer.startEditing()
        pLayer.updateFields()
        feats = []
        feature = QgsFeature(0)
        feature.setAttributes([str(fid), 0, 0])

        line_list = [f.geometry() for f in layer.getFeatures()]
        lines = QgsGeometry.unaryUnion(line_list)
        polygons = QgsGeometry.polygonize([lines])
        fid = 0
        for p in polygons.asGeometryCollection():
            feature = QgsFeature(fid)
            feature.setAttributes([str(fid), 0, 0])
            feature.setGeometry(p)
            feats.append(feature)
            fid += 1

        pLayer.dataProvider().addFeatures(feats)
        pLayer.commitChanges()

        pcLayer = QgsVectorLayer(
            "Polygon?crs={}".format(QgsProject.instance().crs().authid()),
            "Plots",
            "memory",
        )
        QgsProject.instance().addMapLayer(pcLayer)
        pcLayer.dataProvider().addAttributes(pLayer.fields())
        pcLayer.startEditing()
        pcLayer.updateFields()
        pcLayer.dataProvider().addFeatures(
            self.clip_polygons(pLayer, rowBuffer, columnBuffer, iRowLayer,
                               iColLayer))
        pcLayer.commitChanges()

        ptLayer = QgsVectorLayer(
            "Point?crs={}".format(QgsProject.instance().crs().authid()),
            "Points", "memory")
        QgsProject.instance().addMapLayer(ptLayer)
        ptLayer.startEditing()
        ptLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)])
        ptLayer.updateFields()
        feats = []
        fid = 0
        lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines)

        for line in lin.asGeometryCollection():
            poly = line.densifyByCount(self.rowCount.value() * 2).asPolyline()
            for part in poly:
                feature = QgsFeature(fid)
                feature.setAttributes([str(fid)])
                feature.setGeometry(QgsPoint(part))
                feats.append(feature)
                fid += 1
        # ptLayer.dataProvider().addFeatures(sorted(feats, key=lambda f: f['num']))
        ptLayer.dataProvider().addFeatures(feats)
        ptLayer.commitChanges()
Ejemplo n.º 37
0
def my_shortest_path(pointTool):
    try:
        #reading the coordinate of the points clicked
        #and writing in a string format to call shortest path algorithm

        startPoint = str(pointTool.x()) + "," + str(
            pointTool.y()) + " [EPSG:4326-WGS84]"
        endPoint = "144.963403,-37.808179 [EPSG:4326-WGS84]"  #coordinate of RMIT

        #path to the road network data (please change accordingly)
        roads_path = r"/Users/chhanda/Desktop/GIS_Programming/Major_project/Street_network_2018/shp/road.shp"
        #set outputfile directory
        outputfilepath = r"Users/chhanda/Desktop/GIS_Programming/Major_project/"

        #setting up the shortest path parameters
        shortestpathParam = {
            'DEFAULT_DIRECTION': 2,
            'DEFAULT_SPEED': 50,
            'DIRECTION_FIELD': None,
            'END_POINT': endPoint,
            'ENTRY_COST_CALCULATION_METHOD': 0,
            'INPUT': roads_path,
            'OUTPUT': outputfilepath + "shortestpath_output",
            'SPEED_FIELD': None,
            'START_POINT': startPoint,
            'STRATEGY': 0,
            'TOLERANCE': 0,
            'VALUE_BACKWARD': '',
            'VALUE_BOTH': '',
            'VALUE_FORWARD': ''
        }
        processing.run("qneat3:shortestpathpointtopoint", shortestpathParam)

        #loading the shortest path layer from the poutput of the previous processing run
        sp_file_path = outputfilepath + "shortestpath_output.gpkg"
        sp_layer = QgsVectorLayer(sp_file_path, "shortest_path", "ogr")
        if not sp_layer.isValid():
            print("Shortest Path Layer failed to load!")

        #loading road network layer
        road_layer = QgsVectorLayer(roads_path, "roads", "ogr")
        if not road_layer.isValid():
            print("road Layer failed to load!")

        #setting the url of the base layer from ESRI
        base_layer = QgsRasterLayer(
            "http://server.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer?f=json&pretty=true",
            "raster")

        #styling the shortest path layer (color and line width)
        sp_layer.renderer().symbol().setWidth(0.6)
        sp_layer.renderer().symbol().setColor(QColor("red"))

        #creating a point layer to show the start point and the end point
        point_layer = QgsVectorLayer("Point", "temporary_points", "memory")
        pr = point_layer.dataProvider()
        #enter editing mode
        point_layer.startEditing()
        #add a field to display the labels
        pr.addAttributes([QgsField("name", QVariant.String)])
        point_layer.updateFields()
        #add features
        fet = QgsFeature()
        fet.setGeometry(
            QgsGeometry.fromPointXY(QgsPointXY(pointTool.x(), pointTool.y())))
        pr.addFeatures([fet])
        point_layer.changeAttributeValue(1, 0, "Your Home")
        fet.setGeometry(
            QgsGeometry.fromPointXY(QgsPointXY(144.963403, -37.808179)))
        pr.addFeatures([fet])
        point_layer.changeAttributeValue(2, 0, "RMIT UNIVERSITY")
        # Commit changes
        point_layer.commitChanges()

        #styling the point layer (size and color)
        point_layer.renderer().symbol().setSize(6)
        point_layer.renderer().symbol().setColor(QColor("red"))

        #styling the labels to make them appear with white background
        layer_settings = QgsPalLayerSettings()
        text_format = QgsTextFormat()

        background_color = QgsTextBackgroundSettings()
        background_color.setFillColor(QColor('white'))
        background_color.setEnabled(True)

        text_format.setFont(QFont("Arial", 12))
        text_format.setSize(12)
        text_format.setBackground(background_color)

        buffer_settings = QgsTextBufferSettings()
        buffer_settings.setEnabled(True)
        buffer_settings.setSize(0.10)
        buffer_settings.setColor(QColor("black"))

        text_format.setBuffer(buffer_settings)
        layer_settings.setFormat(text_format)

        layer_settings.fieldName = "name"
        layer_settings.placement = 4

        layer_settings.enabled = True

        layer_settings = QgsVectorLayerSimpleLabeling(layer_settings)
        point_layer.setLabelsEnabled(True)
        point_layer.setLabeling(layer_settings)

        #initialising an output fgrame
        output_canvas = QgsMapCanvas()
        #chosing the layers to display
        output_canvas.setLayers([sp_layer, point_layer, base_layer])
        #getting the extent of the shortest path layer to zoom into the path
        ext = sp_layer.extent()
        xmin = ext.xMinimum()
        xmax = ext.xMaximum()
        ymin = ext.yMinimum()
        ymax = ext.yMaximum()
        #setting extent of the output to that of a box slightly larger than the shortest path layer
        #such that the labels don't get chopped
        output_canvas.setExtent(
            QgsRectangle(xmin - 0.01, ymin - 0.01, xmax + 0.01, ymax + 0.01))
        output_canvas.show()

        #the function raises an error because eiting without error causes the output window to disappear
        raise

    except AttributeError:
        pass
Ejemplo n.º 38
0
road_layer = QgsVectorLayer(roads_path, "roads", "ogr")
if not road_layer.isValid():
    print("Layer failed to load!")
#setting the url of the base layer
base_layer = QgsRasterLayer(
    "http://server.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer?f=json&pretty=true",
    "raster")

#creating a point layer to highlight RMIT
point_layer = QgsVectorLayer("Point", "temporary_points", "memory")
pr = point_layer.dataProvider()
#enter editing mode
point_layer.startEditing()
#add attribute for labels
pr.addAttributes([QgsField("name", QVariant.String)])
point_layer.updateFields()
# add a feature
fet = QgsFeature()
fet.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(144.963403, -37.808179)))
pr.addFeatures([fet])
point_layer.changeAttributeValue(
    1, 0,
    "RMIT UNIVERSITY\n(Click on your house location to\n obtain the shortest path to here)"
)
# Commit changes
point_layer.commitChanges()

#styling the point layer (size and color)
point_layer.renderer().symbol().setSize(6)
point_layer.renderer().symbol().setColor(QColor("red"))
Ejemplo n.º 39
0
class CCTVMapper:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'CCTVMapper_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&CCTV Mapper')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        self.first_start = None

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('CCTVMapper', message)


    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            # Adds plugin icon to Plugins toolbar
            self.iface.addToolBarIcon(action)

        if add_to_menu:
            self.iface.addPluginToVectorMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/cctv_mapper/icon.png'
        self.add_action(
            icon_path,
            text=self.tr(u'CCTV Mapper'),
            callback=self.run,
            parent=self.iface.mainWindow())

        # will be set False in run()
        self.first_start = True


    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginVectorMenu(
                self.tr(u'&CCTV Mapper'),
                action)
            self.iface.removeToolBarIcon(action)
            
    def create_mem_layer (self):
        uri = "Point?crs=epsg:2272"
        self.temp_layer = QgsVectorLayer(uri, 'temp_points','memory')
        self.provider = self.temp_layer.dataProvider()
        # add fields
        self.provider.addAttributes([QgsField('PIPE_ID', QVariant.String),
                                    QgsField('LOCATION',  QVariant.String),
                                    QgsField('START_MH',  QVariant.String),
                                    QgsField('END_MH',  QVariant.String),
                                    QgsField('TOT_LEN',  QVariant.String),
                                    QgsField('SURV_LEN',  QVariant.String),
                                    QgsField('MAIN_DIA',  QVariant.String),
                                    QgsField('MAIN_MATL',  QVariant.String),
                                    QgsField('DIRECTION',  QVariant.String),
                                    QgsField('DISTANCE',  QVariant.String),
                                    QgsField('CODE',  QVariant.String),
                                    QgsField('DESCR',  QVariant.String),
                                    QgsField('CLOCK',  QVariant.String),
                                    QgsField('LAT_DIA',  QVariant.String),
                                    QgsField('GRADE',  QVariant.String),
                                    QgsField('COMMENT',  QVariant.String),
                                    QgsField('ERROR',  QVariant.String),
                                    
                                    ]) #if attributes are added then you will need to populate them when creating points
        self.temp_layer.updateFields() # tell the vector layer to fetch changes from the provider
        # QgsMapLayerRegistry.instance().addMapLayer(self.temp_layer)
        QgsProject.instance().addMapLayer(self.temp_layer)
        
    def create_point (self, data):
        #create point feature
        ft =  QgsFeature()
        # print (point)
        ft.setGeometry(data[-1])
        # Every attribute has to be filled in when creating new features for temporary layers
        # print (data[0:16])                  
        ft.setAttributes(data[0:17])
        self.provider.addFeature(ft)
        self.temp_layer.updateExtents()
        print ('created point')
            
    def select_csv_file(self):
        csv_folder = os.path.join(os.getenv('APPDATA') + '/QGIS/QGIS3/profiles/default/python/plugins/cctv_mapper/data/')
        print (csv_folder)
        filename, _filter = QFileDialog.getOpenFileName(self.dlg, 'Select output file', csv_folder, '*.csv')
        self.dlg.lineEdit.setText(filename)
        
        
    def get_point_geometry(self, pid, dist, direction):
        # print (pid)
        exp = QgsExpression('FACILITYID = \'' + pid + '\'')
        request = QgsFeatureRequest(exp)
        selection = self.layer.getFeatures(request)        
        for feature in selection:
            feature_length = feature.geometry().length()
            print (feature_length)
            if (direction != 'Downstream'):
                dist = feature_length - dist
            if (dist > feature_length):
                length_error = 'distance longer than feature length point placed at end'
            else:
                length_error = 'none'
                
    
            pt_geom = feature.geometry().interpolate(dist)
        return pt_geom, length_error


    def run(self):
        """Run method that performs all the real work"""

        # Create the dialog with elements (after translation) and keep reference
        # Only create GUI ONCE in callback, so that it will only load when the plugin is started
        if self.first_start == True:
            self.first_start = False
            self.dlg = CCTVMapperDialog()
            self.dlg.pushButton.clicked.connect(self.select_csv_file)
            
        # Fetch the currently loaded layers
        layers = QgsProject.instance().layerTreeRoot().children()
        # Clear the contents of the comboBox from previous runs
        self.dlg.comboBox.clear()
        # Populate the comboBox with names of all the loaded layers
        self.dlg.comboBox.addItems([layer.name() for layer in layers])

        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            # Do something useful here - delete the line containing pass and
            # substitute with your code.
            # pass
            
            filename = self.dlg.lineEdit.text()
            selectedLayerIndex = self.dlg.comboBox.currentIndex()
            self.layer = layers[selectedLayerIndex].layer()
            self.create_mem_layer ()
            # points = []
            new_points = []
            # pt = ''
            with open(filename, 'r') as csv_file:
                csv_reader = csv.reader(csv_file, delimiter=',')
                next(csv_reader)
                for row in csv_reader:
                    # print (row)
                    # if lin
                    point,error = self.get_point_geometry (row[0], float(row[9]), row[8])
                    # print (point)
                    row.append(error)                   
                    row.append(point)
                    new_points.append(row)
                    # points.append(point)
                    # pipeid = row[0]
                    # print (row)
                # print csv_reader
                
            # for point in points:
                # print (point)
                # self.create_point (point)
            
            # print (new_points)
            
            for item in new_points:
                self.create_point (item)
Ejemplo n.º 40
0
    def newFrontageLayer(self):

        # always create a memory layer first

        if self.frontagedlg.createNewFileCheckBox.isChecked():
            building_layer = self.getSelectedLayer()
            crs = building_layer.crs()
            vl = QgsVectorLayer("LineString?crs=" + crs.authid(), "memory:frontages", "memory")

        else:
            vl = QgsVectorLayer("LineString?crs=", "memory:frontages", "memory")
        if vl.crs().toWkt() == "":
            vl.setCrs(QgsProject.instance().crs())
        provider = vl.dataProvider()
        provider.addAttributes([QgsField(FrontageTool.id_attribute, QVariant.Int),
                                QgsField(FrontageTool.group_attribute, QVariant.String),
                                QgsField(FrontageTool.type_attribute, QVariant.String),
                                QgsField(FrontageTool.length_attribute, QVariant.Double)])
        vl.updateFields()

        # use building layer - explode
        if self.frontagedlg.createNewFileCheckBox.isChecked():
            print('building layer')
            exploded_features = []
            i = 1
            for f in building_layer.getFeatures():
                points = f.geometry().asPolygon()[0]  # get list of points
                for (p1, p2) in zip(points[:-1], points[1:]):
                    i += 1
                    feat = QgsFeature()
                    line_geom = QgsGeometry.fromPolyline([p1, p2])
                    feat.setAttributes([i, NULL, NULL, line_geom.geometry().length()])
                    feat.setId(i)
                    feat.setGeometry(line_geom)
                    exploded_features.append(feat)
            print('building layer2')
            vl.updateFields()
            vl.startEditing()
            provider.addFeatures(exploded_features)
            vl.commitChanges()
            print('building layer3')

        if self.frontagedlg.f_shp_radioButton.isChecked():  # layer_type == 'shapefile':

            path = self.frontagedlg.lineEditFrontages.text()

            if path and path != '':
                filename = os.path.basename(path)
                location = os.path.abspath(path)

                shph.createShapeFile(vl, path, vl.crs())
                vl = self.iface.addVectorLayer(location, filename[:-4], "ogr")
            else:
                vl = 'invalid data source'

        elif self.frontagedlg.f_postgis_radioButton.isChecked():

            db_path = self.frontagedlg.lineEditFrontages.text()
            if db_path and db_path != '':

                (database, schema, table_name) = (self.frontagedlg.lineEditFrontages.text()).split(':')
                db_con_info = self.frontagedlg.dbsettings_dlg.available_dbs[database]
                uri = QgsDataSourceUri()
                # passwords, usernames need to be empty if not provided or else connection will fail
                if 'service' in list(db_con_info.keys()):
                    uri.setConnection(db_con_info['service'], '', '', '')  # db_con_info['dbname']
                elif 'password' in list(db_con_info.keys()):
                    uri.setConnection(db_con_info['host'], db_con_info['port'], db_con_info['dbname'],
                                      db_con_info['user'], db_con_info['password'])
                else:
                    print(db_con_info)  # db_con_info['host']
                    uri.setConnection('', db_con_info['port'], db_con_info['dbname'], '',
                                      '')  # , db_con_info['user'], '')
                uri.setDataSource(schema, table_name, "geom")
                error = QgsVectorLayerExporter.exportLayer(vl, uri.uri(), "postgres", QgsProject.instance().crs())
                if error[0] != QgsVectorLayerExporter.NoError:
                    print("Error when creating postgis layer: ", error[1])
                    vl = 'duplicate'
                else:
                    vl = QgsVectorLayer(uri.uri(), table_name, "postgres")

            else:
                vl = 'invalid data source'

        if vl == 'invalid data source':
            msgBar = self.iface.messageBar()
            msg = msgBar.createMessage(u'Specify  output path!')
            msgBar.pushWidget(msg, Qgis.Info, 10)
        elif vl == 'duplicate':
            msgBar = self.iface.messageBar()
            msg = msgBar.createMessage(u'Fronatges layer already exists!')
            msgBar.pushWidget(msg, Qgis.Info, 10)
        elif not vl:
            msgBar = self.iface.messageBar()
            msg = msgBar.createMessage(u'Frontages layer failed to load!')
            msgBar.pushWidget(msg, Qgis.Info, 10)
        else:
            QgsProject.instance().addMapLayer(vl)
            msgBar = self.iface.messageBar()
            msg = msgBar.createMessage(u'Frontages layer created!')
            msgBar.pushWidget(msg, Qgis.Info, 10)
            vl.startEditing()
            if self.isRequiredLayer(vl, type):
                self.dockwidget.useExistingcomboBox.addItem(vl.name(), vl)

        # self.updateFrontageLayer() This is creating problems with signals - REMOVE

        # TODO: updateLength function should receive a layer as input. It would be used earlier
        self.frontagedlg.closePopUp()
Ejemplo n.º 41
0
class Vector2ShapeWidget(QDialog, FORM_CLASS):
    def __init__(self, iface, parent):
        super(Vector2ShapeWidget, self).__init__(parent)
        self.setupUi(self)
        self.mMapLayerComboBox.setFilters(QgsMapLayerProxyModel.PointLayer)
        self.mMapLayerComboBox.layerChanged.connect(self.findFields)
        self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(
            self.apply)
        self.iface = iface
        self.unitOfAxisComboBox.addItems(DISTANCE_MEASURE)
        self.unitOfDistanceComboBox.addItems(DISTANCE_MEASURE)
        self.distUnitsPolyComboBox.addItems(DISTANCE_MEASURE)
        self.unitsStarComboBox.addItems(DISTANCE_MEASURE)
        self.unitsRoseComboBox.addItems(DISTANCE_MEASURE)
        self.unitsCyclodeComboBox.addItems(DISTANCE_MEASURE)
        self.unitsFoilComboBox.addItems(DISTANCE_MEASURE)
        self.unitsHeartComboBox.addItems(DISTANCE_MEASURE)
        self.unitsEpicyclodeComboBox.addItems(DISTANCE_MEASURE)
        self.pieUnitOfDistanceComboBox.addItems(DISTANCE_MEASURE)
        self.polygonLayer = None
        self.geod = Geodesic.WGS84
        icon = QIcon(os.path.dirname(__file__) + '/images/ellipse.png')
        self.tabWidget.setTabIcon(0, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/line.png')
        self.tabWidget.setTabIcon(1, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/pie.png')
        self.tabWidget.setTabIcon(2, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/polygon.png')
        self.tabWidget.setTabIcon(3, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/star.png')
        self.tabWidget.setTabIcon(4, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/rose.png')
        self.tabWidget.setTabIcon(5, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/hypocycloid.png')
        self.tabWidget.setTabIcon(6, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/polyfoil.png')
        self.tabWidget.setTabIcon(7, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/epicycloid.png')
        self.tabWidget.setTabIcon(8, icon)
        icon = QIcon(os.path.dirname(__file__) + '/images/heart.png')
        self.tabWidget.setTabIcon(9, icon)

    def apply(self):
        '''process the data'''
        tab = self.tabWidget.currentIndex()
        layer = self.mMapLayerComboBox.currentLayer()
        outname = self.layerNameLineEdit.text()
        if not layer:
            self.showErrorMessage("No valid layer to process")
            return

        # We need to make sure all the points in the layer are transformed to EPSG:4326
        layerCRS = layer.crs()
        self.transform = QgsCoordinateTransform(layerCRS, epsg4326,
                                                QgsProject.instance())

        if tab == 0:  # Ellipse
            self.processEllipse(layer, outname,
                                self.semiMajorComboBox.currentIndex() - 1,
                                self.semiMinorComboBox.currentIndex() - 1,
                                self.orientationComboBox.currentIndex() - 1,
                                self.unitOfAxisComboBox.currentIndex(),
                                self.defSemiMajorSpinBox.value(),
                                self.defSemiMinorSpinBox.value(),
                                self.defOrientationSpinBox.value())
        elif tab == 1:  # LOB
            self.processLOB(layer, outname,
                            self.bearingComboBox.currentIndex() - 1,
                            self.distanceComboBox.currentIndex() - 1,
                            self.unitOfDistanceComboBox.currentIndex(),
                            self.defaultBearingSpinBox.value(),
                            self.defaultDistanceSpinBox.value())
        elif tab == 2:  # Pie shape
            self.processPie(layer, outname,
                            self.pieBearingStartComboBox.currentIndex() - 1,
                            self.pieBearingEndComboBox.currentIndex() - 1,
                            self.pieDistanceComboBox.currentIndex() - 1,
                            self.pieUnitOfDistanceComboBox.currentIndex(),
                            self.pieBearingStartSpinBox.value(),
                            self.pieBearingEndSpinBox.value(),
                            self.pieDefaultDistanceSpinBox.value())
        elif tab == 3:  # Polygon
            try:
                distance = float(self.distPolyLineEdit.text())
            except:
                self.showErrorMessage("Invalid Distance. Fix and try again")
                return
            self.processPoly(
                layer,
                outname,
                self.sidesPolyComboBox.currentIndex() -
                1,  #number of sides column
                self.anglePolyComboBox.currentIndex() -
                1,  #starting angle column
                self.distPolyComboBox.currentIndex() - 1,  # distance column
                self.sidesPolySpinBox.value(),  # default sides
                self.anglePolySpinBox.value(),  # default starting angle
                distance,
                self.distUnitsPolyComboBox.currentIndex())
        elif tab == 4:  # Star
            self.processStar(layer, outname, self.starPointsSpinBox.value(),
                             self.starStartAngleSpinBox.value(),
                             self.innerStarRadiusSpinBox.value(),
                             self.outerStarRadiusSpinBox.value(),
                             self.unitsStarComboBox.currentIndex())
        elif tab == 5:  # Rose
            self.processRose(layer, outname, self.roseAngleSpinBox.value(),
                             self.rosePetalSpinBox.value(),
                             self.roseRadiusSpinBox.value(),
                             self.unitsRoseComboBox.currentIndex())
        elif tab == 6:  # Cyclode
            self.processCyclode(layer, outname,
                                self.cyclodeAngleSpinBox.value(),
                                self.cyclodeCuspsSpinBox.value(),
                                self.cyclodeRadiusSpinBox.value(),
                                self.unitsCyclodeComboBox.currentIndex())
        elif tab == 7:  # Polyfoil
            self.processPolyfoil(layer, outname, self.foilAngleSpinBox.value(),
                                 self.foilLobesSpinBox.value(),
                                 self.foilRadiusSpinBox.value(),
                                 self.unitsFoilComboBox.currentIndex())
        elif tab == 8:  # Epicycloid
            self.processEpicycloid(layer, outname,
                                   self.epicyclodeAngleSpinBox.value(),
                                   self.epicyclodeLobesSpinBox.value(),
                                   self.epicyclodeRadiusSpinBox.value(),
                                   self.unitsEpicyclodeComboBox.currentIndex())
        elif tab == 9:  # Heart
            self.processHeart(layer, outname, self.heartAngleSpinBox.value(),
                              self.heartSizeSpinBox.value(),
                              self.unitsHeartComboBox.currentIndex())

    def showEvent(self, event):
        '''The dialog is being shown. We need to initialize it.'''
        super(Vector2ShapeWidget, self).showEvent(event)
        self.findFields()

    def findFields(self):
        if not self.isVisible():
            return
        layer = self.mMapLayerComboBox.currentLayer()
        self.clearLayerFields()
        if layer:
            header = ["[ Use Default ]"]
            fields = layer.fields()
            for field in fields.toList():
                # force it to be lower case - makes matching easier
                name = field.name()
                header.append(name)
            self.configureLayerFields(header)

    def configureLayerFields(self, header):
        if not settings.guessNames:
            self.clearLayerFields()
        self.semiMajorComboBox.addItems(header)
        self.semiMinorComboBox.addItems(header)
        self.orientationComboBox.addItems(header)

        self.bearingComboBox.addItems(header)
        self.distanceComboBox.addItems(header)

        self.pieBearingStartComboBox.addItems(header)
        self.pieBearingEndComboBox.addItems(header)
        self.pieDistanceComboBox.addItems(header)

        self.sidesPolyComboBox.addItems(header)
        self.anglePolyComboBox.addItems(header)
        self.distPolyComboBox.addItems(header)

        if not settings.guessNames:
            return

        orientcol = semimajorcol = semiminorcol = -1
        bearingcol = distancecol = -1
        for x, item in enumerate(header):
            # Skip the first entry
            if x == 0:
                continue
            lcitem = item.lower()
            if lcitem.startswith('orient'):
                orientcol = x
            elif bool(re.match('semi.*maj', lcitem)):
                semimajorcol = x
            elif bool(re.match('semi.*min', lcitem)):
                semiminorcol = x
            elif bool(re.search('bearing', lcitem)):
                bearingcol = x
            elif bool(re.match('dist', lcitem)):
                distancecol = x

        if orientcol != -1:
            self.orientationComboBox.setCurrentIndex(orientcol)
        if semimajorcol != -1:
            self.semiMajorComboBox.setCurrentIndex(semimajorcol)
        if semiminorcol != -1:
            self.semiMinorComboBox.setCurrentIndex(semiminorcol)
        if bearingcol != -1:
            self.bearingComboBox.setCurrentIndex(bearingcol)
        if distancecol != -1:
            self.distanceComboBox.setCurrentIndex(distancecol)

    def clearLayerFields(self):
        self.semiMajorComboBox.clear()
        self.semiMinorComboBox.clear()
        self.orientationComboBox.clear()
        self.bearingComboBox.clear()
        self.distanceComboBox.clear()
        self.pieBearingStartComboBox.clear()
        self.pieBearingEndComboBox.clear()
        self.pieDistanceComboBox.clear()
        self.sidesPolyComboBox.clear()
        self.anglePolyComboBox.clear()
        self.distPolyComboBox.clear()

    def showErrorMessage(self, message):
        self.iface.messageBar().pushMessage("",
                                            message,
                                            level=Qgis.Warning,
                                            duration=3)

    def processEllipse(self, layer, outname, semimajorcol, semiminorcol,
                       orientcol, unitOfMeasure, defSemiMajor, defSemiMinor,
                       defOrientation):
        measureFactor = 1.0
        # The ellipse calculation is done in Nautical Miles. This converts
        # the semi-major and minor axis to nautical miles
        if unitOfMeasure == 2:  # Nautical Miles
            measureFactor = 1.0
        elif unitOfMeasure == 0:  # Kilometers
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters,
                QgsUnitTypes.DistanceNauticalMiles) * 1000.0
        elif unitOfMeasure == 1:  # Meters
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters,
                QgsUnitTypes.DistanceNauticalMiles)
        elif unitOfMeasure == 3:  # Miles
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceFeet,
                QgsUnitTypes.DistanceNauticalMiles) * 5280.0
        elif unitOfMeasure == 4:  # Feet
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceNauticalMiles)

        fields = layer.fields()

        self.polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                           "memory")
        ppolygon = self.polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        self.polygonLayer.updateFields()

        iter = layer.getFeatures()
        num_features = 0
        num_good = 0
        for feature in iter:
            num_features += 1
            try:
                if semimajorcol != -1:
                    semi_major = float(feature[semimajorcol])
                else:
                    semi_major = defSemiMajor
                if semiminorcol != -1:
                    semi_minor = float(feature[semiminorcol])
                else:
                    semi_minor = defSemiMinor
                if orientcol != -1:
                    orient = float(feature[orientcol])
                else:
                    orient = defOrientation
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                geom = LatLon.getEllipseCoords(pt.y(), pt.x(),
                                               semi_major * measureFactor,
                                               semi_minor * measureFactor,
                                               orient)
                featureout = QgsFeature()
                featureout.setGeometry(QgsGeometry.fromPolygonXY([geom]))
                featureout.setAttributes(feature.attributes())
                ppolygon.addFeatures([featureout])
                num_good += 1
            except:
                # Just skip any lines that are badly formed
                #traceback.print_exc()
                pass
        self.polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(self.polygonLayer)
        self.iface.messageBar().pushMessage(
            "",
            "{} Ellipses created from {} records".format(
                num_good, num_features),
            level=Qgis.Info,
            duration=3)

    def processLOB(self, layer, outname, bearingcol, distcol, unitOfDist,
                   defaultBearing, defaultDist):
        '''Process each layer point and create a new line layer with the associated bearings'''
        measureFactor = self.conversionToMeters(unitOfDist)

        defaultDist *= measureFactor
        maxseglen = settings.maxSegLength * 1000.0  # Needs to be in meters
        maxSegments = settings.maxSegments

        fields = layer.fields()

        self.lineLayer = QgsVectorLayer("LineString?crs=epsg:4326", outname,
                                        "memory")
        pline = self.lineLayer.dataProvider()
        pline.addAttributes(fields)
        self.lineLayer.updateFields()

        iter = layer.getFeatures()
        num_features = 0
        num_good = 0
        for feature in iter:
            num_features += 1
            try:
                if bearingcol != -1:
                    bearing = float(feature[bearingcol])
                else:
                    bearing = defaultBearing
                if distcol != -1:
                    distance = float(feature[distcol]) * measureFactor
                else:
                    distance = defaultDist
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                pts = [pt]
                l = self.geod.Line(pt.y(), pt.x(), bearing)
                n = int(math.ceil(distance / maxseglen))
                if n > maxSegments:
                    n = maxSegments
                seglen = distance / n
                for i in range(1, n + 1):
                    s = seglen * i
                    g = l.Position(
                        s, Geodesic.LATITUDE | Geodesic.LONGITUDE
                        | Geodesic.LONG_UNROLL)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                featureout = QgsFeature()
                featureout.setGeometry(QgsGeometry.fromPolylineXY(pts))
                featureout.setAttributes(feature.attributes())
                pline.addFeatures([featureout])
                num_good += 1
            except:
                # Just skip any lines that are badly formed
                pass
        self.lineLayer.updateExtents()
        QgsProject.instance().addMapLayer(self.lineLayer)
        self.iface.messageBar().pushMessage(
            "",
            "{} lines of bearing created from {} records".format(
                num_good, num_features),
            level=Qgis.Info,
            duration=3)

    def processPie(self, layer, outname, startanglecol, endanglecol, distcol,
                   unitOfDist, startangle, endangle, defaultDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        defaultDist *= measureFactor

        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            try:
                pts = []
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                pts.append(pt)
                if startanglecol == -1:
                    sangle = startangle
                else:
                    sangle = float(feature[startanglecol])
                if endanglecol == -1:
                    eangle = endangle
                else:
                    eangle = float(feature[endanglecol])
                if distcol == -1:
                    dist = defaultDist
                else:
                    dist = float(feature[distcol]) * measureFactor

                sangle = sangle % 360
                eangle = eangle % 360

                if sangle > eangle:
                    # We are crossing the 0 boundry so lets just subtract
                    # 360 from it.
                    sangle -= 360.0
                while sangle < eangle:
                    g = self.geod.Direct(
                        pt.y(), pt.x(), sangle, dist,
                        Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    sangle += 4  # add this number of degrees to the angle

                g = self.geod.Direct(pt.y(), pt.x(), eangle, dist,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                pts.append(pt)

                featureout = QgsFeature()
                featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                featureout.setAttributes(feature.attributes())
                ppolygon.addFeatures([featureout])
            except:
                pass

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def processPoly(self, layer, outname, sidescol, anglecol, distcol, sides,
                    angle, defaultDist, unitOfDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        defaultDist *= measureFactor

        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            try:
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                if sidescol != -1:
                    s = int(feature[sidescol])
                else:
                    s = sides
                if anglecol != -1:
                    startangle = float(feature[anglecol])
                else:
                    startangle = angle
                if distcol != -1:
                    d = float(feature[distcol]) * measureFactor
                else:
                    d = defaultDist
                pts = []
                i = s
                while i >= 0:
                    a = (i * 360.0 / s) + startangle
                    i -= 1
                    g = self.geod.Direct(
                        pt.y(), pt.x(), a, d,
                        Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    #lat2, lon2 = LatLon.destinationPointVincenty(pt.y(), pt.x(), a, d)
                    #pts.append(QgsPointXY(lon2, lat2))

                featureout = QgsFeature()
                featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                featureout.setAttributes(feature.attributes())
                ppolygon.addFeatures([featureout])
            except:
                pass

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def processStar(self, layer, outname, numPoints, startAngle, innerRadius,
                    outerRadius, unitOfDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        innerRadius *= measureFactor
        outerRadius *= measureFactor

        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        half = (360.0 / numPoints) / 2.0
        for feature in iter:
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = self.transform.transform(pt.x(), pt.y())
            i = numPoints - 1
            while i >= 0:
                i -= 1
                angle = (i * 360.0 / numPoints) + startAngle
                g = self.geod.Direct(pt.y(), pt.x(), angle, outerRadius,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                #lat2, lon2 = LatLon.destinationPointVincenty(pt.y(), pt.x(), angle, outerRadius)
                #pts.append(QgsPointXY(lon2, lat2))
                g = self.geod.Direct(pt.y(), pt.x(), angle - half, innerRadius,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                #lat2, lon2 = LatLon.destinationPointVincenty(pt.y(), pt.x(), angle-half, innerRadius)
                #pts.append(QgsPointXY(lon2, lat2))
            featureout = QgsFeature()
            featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            featureout.setAttributes(feature.attributes())
            ppolygon.addFeatures([featureout])

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def processRose(self, layer, outname, startAngle, k, radius, unitOfDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        radius *= measureFactor
        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()
        dist = []
        if k == 1:
            dist.append(0.0)
        step = 1
        angle = -90.0 + step
        while angle < 90.0:
            a = math.radians(angle)
            r = math.cos(a)
            dist.append(r)
            angle += step
        cnt = len(dist)

        for feature in iter:
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = self.transform.transform(pt.x(), pt.y())
            arange = 360.0 / k
            angle = -arange / 2.0
            astep = arange / cnt
            for i in range(k):
                aoffset = arange * (k - 1)
                index = 0
                while index < cnt:
                    r = dist[index] * radius
                    g = self.geod.Direct(
                        pt.y(), pt.x(), angle + aoffset, r,
                        Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    angle += astep
                    index += 1
            # repeat the very first point to close the polygon
            pts.append(pts[0])
            featureout = QgsFeature()
            featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            featureout.setAttributes(feature.attributes())
            ppolygon.addFeatures([featureout])

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def processCyclode(self, layer, outname, startAngle, cusps, radius,
                       unitOfDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        radius *= measureFactor
        r = radius / cusps
        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = self.transform.transform(pt.x(), pt.y())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle)
                x = r * (cusps - 1.0) * math.cos(a) + r * math.cos(
                    (cusps - 1.0) * a)
                y = r * (cusps - 1.0) * math.sin(a) - r * math.sin(
                    (cusps - 1.0) * a)
                a2 = math.degrees(math.atan2(y, x)) + startAngle
                dist = math.sqrt(x * x + y * y)
                g = self.geod.Direct(pt.y(), pt.x(), a2, dist,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += 0.5
            featureout = QgsFeature()
            featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            featureout.setAttributes(feature.attributes())
            ppolygon.addFeatures([featureout])

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def processEpicycloid(self, layer, outname, startAngle, lobes, radius,
                          unitOfDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        radius *= measureFactor
        r = radius / (lobes + 2.0)
        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = self.transform.transform(pt.x(), pt.y())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle)
                x = r * (lobes + 1.0) * math.cos(a) - r * math.cos(
                    (lobes + 1.0) * a)
                y = r * (lobes + 1.0) * math.sin(a) - r * math.sin(
                    (lobes + 1.0) * a)
                a2 = math.degrees(math.atan2(y, x)) + startAngle
                dist = math.sqrt(x * x + y * y)
                g = self.geod.Direct(pt.y(), pt.x(), a2, dist,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += 0.5
            featureout = QgsFeature()
            featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            featureout.setAttributes(feature.attributes())
            ppolygon.addFeatures([featureout])

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def processPolyfoil(self, layer, outname, startAngle, lobes, radius,
                        unitOfDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        radius *= measureFactor
        r = radius / lobes
        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = self.transform.transform(pt.x(), pt.y())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle - startAngle)
                x = r * (lobes - 1.0) * math.cos(a) + r * math.cos(
                    (lobes - 1.0) * a)
                y = r * (lobes - 1.0) * math.sin(a) - r * math.sin(
                    (lobes - 1.0) * a)
                dist = math.sqrt(x * x + y * y)
                g = self.geod.Direct(pt.y(), pt.x(), angle, dist,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += 0.5
            featureout = QgsFeature()
            featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            featureout.setAttributes(feature.attributes())
            ppolygon.addFeatures([featureout])

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def processHeart(self, layer, outname, startAngle, size, unitOfDist):
        measureFactor = self.conversionToMeters(unitOfDist)
        # The algorithm creates the heart on its side so this rotates
        # it so that it is upright.
        startAngle -= 90.0

        size *= measureFactor

        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = self.transform.transform(pt.x(), pt.y())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle)
                sina = math.sin(a)
                x = 16 * sina * sina * sina
                y = 13 * math.cos(a) - 5 * math.cos(2 * a) - 2 * math.cos(
                    3 * a) - math.cos(4 * a)
                dist = math.sqrt(x * x + y * y) * size / 17.0
                a2 = math.degrees(math.atan2(y, x)) + startAngle
                g = self.geod.Direct(pt.y(), pt.x(), a2, dist,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += 0.5
            featureout = QgsFeature()
            featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            featureout.setAttributes(feature.attributes())
            ppolygon.addFeatures([featureout])

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)

    def conversionToMeters(self, units):
        if units == 2:  # Nautical Miles
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceNauticalMiles,
                QgsUnitTypes.DistanceMeters)
        elif units == 0:  # Kilometers
            measureFactor = 1000.0
        elif units == 1:  # Meters
            measureFactor = 1.0
        elif units == 3:  # Miles
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceFeet,
                QgsUnitTypes.DistanceMeters) * 5280.0
        elif units == 4:  # Feet
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMeters)
        return measureFactor

    def accept(self):
        self.apply()
        self.close()
    def processAlgorithm(self, parameters, context, feedback):
        hab_layer = self.parameterAsVectorLayer(parameters, self.HABITAT,
                                                context)
        observ_layer = self.parameterAsVectorLayer(parameters,
                                                   self.OBSERVATIONS, context)
        hab_etat_ecolo = self.parameterAsVectorLayer(
            parameters, self.HABITAT_ETAT_ECOLOGIQUE, context)

        # Vérification de l'unicité de la couche habitat pour le couple nom/faciès
        params = {'INPUT': hab_layer, 'OUTPUT': 'TEMPORARY_OUTPUT'}
        results = processing.run("mercicor:calcul_unicity_habitat",
                                 params,
                                 context=context,
                                 feedback=feedback,
                                 is_child_algorithm=True)

        if results['NUMBER_OF_NON_UNIQUE']:
            feedback.pushDebugInfo(
                '{} couple(s) habitat/faciès non unique !'.format(
                    results['NUMBER_OF_NON_UNIQUE']))
            feedback.reportError(
                'Les couples habitat/faciès ne sont pas uniques !')
            msg = 'Utiliser l\'algorithme Mercicor : '
            msg += 'Calcul unicité habitat/faciès ; '
            msg += 'pour corriger le problème.'
            feedback.pushInfo(msg)
            return {}

        # Calcul de la moyenne des indicateurs mercicor par habitat/faciès
        params = {
            'DISCARD_NONMATCHING':
            True,
            'INPUT':
            hab_layer,
            'JOIN':
            observ_layer,
            'JOIN_FIELDS': [
                'perc_bsd', 'perc_bsm', 'bsd_recouv_cor', 'bsd_p_acrop',
                'bsd_vital_cor', 'bsd_comp_struc', 'bsd_taille_cor',
                'bsd_dens_juv', 'bsd_f_sessile', 'bsd_recouv_ma',
                'bsm_fragm_herb', 'bsm_recouv_her', 'bsm_haut_herb',
                'bsm_dens_herb', 'bsm_div_herb', 'bsm_epibiose', 'man_fragm',
                'man_recouv', 'man_diam_tronc', 'man_dens', 'man_diversit',
                'man_vital', 'pmi_div_poi', 'pmi_predat_poi', 'pmi_scarib_poi',
                'pmi_macro_inv'
            ],
            'OUTPUT':
            'TEMPORARY_OUTPUT',
            'PREDICATE': [0],  # Intersects
            'SUMMARIES': [6]  # Mean
        }

        results = processing.run(
            "qgis:joinbylocationsummary",
            params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        # Mise en forme du résultat pour enregistrement dans la table habitat_etat_ecologique
        hee_fields = hab_etat_ecolo.fields()
        hee_features = {}
        layer = QgsProcessingUtils.mapLayerFromString(results['OUTPUT'],
                                                      context, True)
        for feat in layer.getFeatures():
            hee_feature = QgsFeature(hee_fields)
            hee_feature.setAttribute('id', feat['id'])
            hee_feature.setAttribute('nom', feat['nom'])
            hee_feature.setAttribute('facies', feat['facies'])
            for field in params['JOIN_FIELDS']:
                hee_feature.setAttribute(field, feat[field + '_mean'])
            hee_features[feat['id']] = hee_feature

        # Récupération de l'information de station en Mangrove
        params = {
            'DISCARD_NONMATCHING': True,
            'INPUT': hab_layer,
            'JOIN': observ_layer,
            'JOIN_FIELDS': ['station_man'],
            'OUTPUT': 'TEMPORARY_OUTPUT',
            'PREDICATE': [0],  # Intersects
            'SUMMARIES': [3]  # Max
        }

        results = processing.run(
            "qgis:joinbylocationsummary",
            params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        # Ajout de l'information de station en Mangrove aux objets qui
        # seront enregistrés dans la table habitat_etat_ecologique
        layer = QgsProcessingUtils.mapLayerFromString(results['OUTPUT'],
                                                      context, True)
        for feat in layer.getFeatures():
            hee_feature = hee_features[feat['id']]
            for field in params['JOIN_FIELDS']:
                hee_feature.setAttribute(field, feat[field + '_max'])
            hee_features[feat['id']] = hee_feature

        # Création d'une couche temporaire pour calcul des notes mercicor
        layer = QgsVectorLayer("None", "temporary_hee", "memory")
        pr = layer.dataProvider()
        pr.addAttributes(hee_fields)
        layer.updateFields()
        pr.addFeatures(list(hee_features.values()))

        # Calcul des notes mercicor
        params = {'INPUT': layer, 'OUTPUT': 'TEMPORARY_OUTPUT'}
        results = processing.run(
            "mercicor:calcul_notes",
            params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        # Ajout des notes mercicor aux objets qui seront enregistrés
        # dans la table habitat_etat_ecologique
        layer = QgsProcessingUtils.mapLayerFromString(results['OUTPUT'],
                                                      context, True)
        layer_fields = layer.fields()
        for feat in layer.getFeatures():
            hee_feature = hee_features[feat['id']]
            for field in layer_fields:
                field_name = field.name()
                if hee_fields.indexOf(field_name) < 0:
                    continue
                field_val = feat[field_name]
                # forcer les valeurs booléenne
                if field.type() == QVariant.Bool:
                    if field_val and str(field_val).lower() == 'true':
                        field_val = 1
                    else:
                        field_val = 0
                #  set attribute
                hee_feature.setAttribute(field_name, field_val)
            hee_features[feat['id']] = hee_feature

        # Début de la modification de la table habitat_etat_ecologique
        hab_etat_ecolo.startEditing()

        # Mise à jour des objets de la table habitat_etat_ecologique
        for existing in hab_etat_ecolo.getFeatures():
            if existing['id'] in hee_features:
                feat = hee_features[existing['id']]
                attributes = {}
                for field in hee_fields:
                    field_name = field.name()
                    attributes[hee_fields.indexOf(
                        field_name)] = feat[field_name]
                hab_etat_ecolo.changeAttributeValues(existing.id(), attributes)
                del hee_features[existing['id']]

        # Ajout des objets restant de la table habitat_etat_ecologique
        for feat in hee_features.values():
            hab_etat_ecolo.addFeature(feat)

        # Fin et enregistrement de la modification de la table habitat_etat_ecologique
        hab_etat_ecolo.commitChanges()

        return {}
Ejemplo n.º 43
0
def run(settings, progress_bars):

    for key in list(progress_bars.keys()):
        bar = progress_bars[key]
        bar['bar'].setValue(0)
        bar['label'].setText('')

    CreateTempDir()

    receiver_layer_name = os.path.splitext(
        os.path.basename(settings['receivers_path']))[0]
    receiver_layer = QgsVectorLayer(settings['receivers_path'],
                                    receiver_layer_name, "ogr")

    if settings['sources_pts_path'] is not None:
        source_pts_layer_name = os.path.splitext(
            os.path.basename(settings['sources_pts_path']))[0]
        source_pts_layer = QgsVectorLayer(settings['sources_pts_path'],
                                          source_pts_layer_name, "ogr")
    else:
        source_pts_layer = None

    if settings['sources_roads_path'] is not None:
        source_roads_layer_name = os.path.splitext(
            os.path.basename(settings['sources_roads_path']))[0]
        source_roads_layer = QgsVectorLayer(settings['sources_roads_path'],
                                            source_roads_layer_name, "ogr")

    else:
        source_roads_layer = None

    if settings['buildings_path'] is not None:
        obstacles_layer_name = os.path.splitext(
            os.path.basename(settings['buildings_path']))[0]
        obstacles_layer = QgsVectorLayer(settings['buildings_path'],
                                         obstacles_layer_name, "ogr")
    else:
        obstacles_layer = None

    rays_layer_path = settings['rays_path']
    diff_rays_layer_path = settings['diff_rays_path']

    # defines rays layer
    if rays_layer_path is not None:

        rays_fields = QgsFields()
        rays_fields.append(QgsField("id_ray", QVariant.Int))
        rays_fields.append(QgsField("id_rec", QVariant.Int))
        rays_fields.append(QgsField("id_emi", QVariant.Int))
        rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2))
        rays_fields.append(
            QgsField("d_rTOe_4m", QVariant.Double, len=10, prec=2))

        if settings['period_pts_gen'] == "True" or settings[
                'period_roads_gen'] == "True":
            rays_fields.append(
                QgsField("gen_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1))
        if settings['period_pts_day'] == "True" or settings[
                'period_roads_day'] == "True":
            rays_fields.append(
                QgsField("day_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1))
        if settings['period_pts_eve'] == "True" or settings[
                'period_roads_eve'] == "True":
            rays_fields.append(
                QgsField("eve_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1))
        if settings['period_pts_nig'] == "True" or settings[
                'period_roads_nig'] == "True":
            rays_fields.append(
                QgsField("nig_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1))

        rays_writer = QgsVectorFileWriter(rays_layer_path, "System",
                                          rays_fields, QgsWkbTypes.LineString,
                                          receiver_layer.crs(),
                                          "ESRI Shapefile")

    else:
        rays_writer = None

    # defines diff rays layer
    if diff_rays_layer_path is not None:

        rays_fields = QgsFields()
        rays_fields.append(QgsField("id_ray", QVariant.Int))
        rays_fields.append(QgsField("id_rec", QVariant.Int))
        rays_fields.append(QgsField("id_dif", QVariant.Int))
        rays_fields.append(QgsField("id_emi", QVariant.Int))
        rays_fields.append(QgsField("d_rTOd", QVariant.Double, len=10, prec=2))
        rays_fields.append(QgsField("d_dTOe", QVariant.Double, len=10, prec=2))
        rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2))

        if settings['period_pts_gen'] == "True" or settings[
                'period_roads_gen'] == "True":
            rays_fields.append(
                QgsField("gen_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1))
        if settings['period_pts_day'] == "True" or settings[
                'period_roads_day'] == "True":
            rays_fields.append(
                QgsField("day_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1))
        if settings['period_pts_eve'] == "True" or settings[
                'period_roads_eve'] == "True":
            rays_fields.append(
                QgsField("eve_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1))
        if settings['period_pts_nig'] == "True" or settings[
                'period_roads_nig'] == "True":
            rays_fields.append(
                QgsField("nig_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1))

        diff_rays_writer = QgsVectorFileWriter(diff_rays_layer_path, "System",
                                               rays_fields,
                                               QgsWkbTypes.LineString,
                                               receiver_layer.crs(),
                                               "ESRI Shapefile")

    else:
        diff_rays_writer = None

    # puts the sound level in the receivers points attribute table
    # gets fields from recever point layer and initializes the final receiver_point_field_level to populate the receiver points layer attribute table
    fields_number = int(receiver_layer.fields().count())

    level_field_index = {}

    #modified version in creating fields on existing layer in qgis 3.x
    receiver_layer.startEditing()
    #level_fields = []
    if settings['period_pts_gen'] == "True" or settings[
            'period_roads_gen'] == "True":
        receiver_layer.addAttribute(
            QgsField('gen', QVariant.Double, len=5, prec=1))
        level_field_index['gen'] = fields_number
        fields_number = fields_number + 1
    if settings['period_pts_day'] == "True" or settings[
            'period_roads_day'] == "True":
        receiver_layer.addAttribute((QgsField('day',
                                              QVariant.Double,
                                              len=5,
                                              prec=1)))
        level_field_index['day'] = fields_number
        fields_number = fields_number + 1
    if settings['period_pts_eve'] == "True" or settings[
            'period_roads_eve'] == "True":
        receiver_layer.addAttribute(
            QgsField('eve', QVariant.Double, len=5, prec=1))
        level_field_index['eve'] = fields_number
        fields_number = fields_number + 1
    if settings['period_pts_nig'] == "True" or settings[
            'period_roads_nig'] == "True":
        receiver_layer.addAttribute(
            QgsField('nig', QVariant.Double, len=5, prec=1))
        level_field_index['nig'] = fields_number
        fields_number = fields_number + 1
    if settings['period_den'] == "True":
        receiver_layer.addAttribute(
            QgsField('den', QVariant.Double, len=5, prec=1))
        level_field_index['den'] = fields_number
        fields_number = fields_number + 1

    #receiver_layer.dataProvider().addAttributes( level_fields )
    receiver_layer.updateFields()

    #calculation
    receiver_feat_new_fields = calc(progress_bars, receiver_layer,
                                    source_pts_layer, source_roads_layer,
                                    settings, level_field_index,
                                    obstacles_layer, rays_writer,
                                    diff_rays_writer)

    #old way to insert data in table
    # receiver_layer.dataProvider().changeAttributeValues(receiver_feat_new_fields)

    #new way to insert data in table
    for f in receiver_layer.getFeatures():
        if 'gen' in level_field_index:
            f['gen'] = receiver_feat_new_fields[f.id()][
                level_field_index['gen']]
            #print(receiver_feat_new_fields,f.id(),f['gen'])
        if 'day' in level_field_index:
            f['day'] = receiver_feat_new_fields[f.id()][
                level_field_index['day']]
        if 'eve' in level_field_index:
            f['eve'] = receiver_feat_new_fields[f.id()][
                level_field_index['eve']]
        if 'nig' in level_field_index:
            f['nig'] = receiver_feat_new_fields[f.id()][
                level_field_index['nig']]
        if 'den' in level_field_index:
            f['den'] = receiver_feat_new_fields[f.id()][
                level_field_index['den']]
        receiver_layer.updateFeature(f)

    receiver_layer.updateExtents()

    receiver_layer.commitChanges()

    #reload all layers to see the updates of shapefile of receivers
    QgsProject.instance().reloadAllLayers()

    if rays_layer_path is not None:
        del rays_writer
        rays_layer_name = os.path.splitext(
            os.path.basename(rays_layer_path))[0]
        rays_layer = QgsVectorLayer(rays_layer_path, str(rays_layer_name),
                                    "ogr")

        QgsProject.instance().addMapLayers([rays_layer])

    if diff_rays_layer_path is not None:
        del diff_rays_writer
        diff_rays_layer_name = os.path.splitext(
            os.path.basename(diff_rays_layer_path))[0]
        diff_rays_layer = QgsVectorLayer(diff_rays_layer_path,
                                         str(diff_rays_layer_name), "ogr")

        QgsProject.instance().addMapLayers([diff_rays_layer])

        QgsProject.instance().reloadAllLayers()

    # render receivers with noise colours
    level_fields_new = list(receiver_layer.dataProvider().fields())

    if len(level_fields_new) > 0:
        receiver_layer_name = settings['receivers_name']
        layer = QgsProject.instance().mapLayersByName(receiver_layer_name)[0]
        on_ApplyNoiseSymbology.renderizeXY(
            layer, level_fields_new[len(level_fields_new) - 1].name())

    DeleteTempDir()
Ejemplo n.º 44
0
    def test_expressionFromOgcFilterWithString(self):
        """
        Test expressionFromOgcFilter with String type field
        """
        vl = QgsVectorLayer('Point', 'vl', 'memory')
        vl.dataProvider().addAttributes([QgsField('id', QVariant.String)])
        vl.updateFields()

        # Literals are Integer 1 and 3
        f = '''<?xml version="1.0" encoding="UTF-8"?>
            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
              <ogc:And>
                <ogc:PropertyIsGreaterThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>1</ogc:Literal>
                </ogc:PropertyIsGreaterThan>
                <ogc:PropertyIsLessThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>3</ogc:Literal>
                </ogc:PropertyIsLessThan>
              </ogc:And>
            </ogc:Filter>
        '''
        d = QDomDocument('filter')
        d.setContent(f, True)

        e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl)
        self.assertEqual(e.expression(), 'id > \'1\' AND id < \'3\'')

        # Literals are Double 1.0 and 3.0
        f = '''<?xml version="1.0" encoding="UTF-8"?>
            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
              <ogc:And>
                <ogc:PropertyIsGreaterThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>1.0</ogc:Literal>
                </ogc:PropertyIsGreaterThan>
                <ogc:PropertyIsLessThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>3.0</ogc:Literal>
                </ogc:PropertyIsLessThan>
              </ogc:And>
            </ogc:Filter>
        '''
        d = QDomDocument('filter')
        d.setContent(f, True)

        e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl)
        self.assertEqual(e.expression(), 'id > \'1.0\' AND id < \'3.0\'')

        # Literals are Double 1.5 and 3.5
        f = '''<?xml version="1.0" encoding="UTF-8"?>
            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
              <ogc:And>
                <ogc:PropertyIsGreaterThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>1.5</ogc:Literal>
                </ogc:PropertyIsGreaterThan>
                <ogc:PropertyIsLessThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>3.5</ogc:Literal>
                </ogc:PropertyIsLessThan>
              </ogc:And>
            </ogc:Filter>
        '''
        d = QDomDocument('filter')
        d.setContent(f, True)

        e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl)
        self.assertEqual(e.expression(), 'id > \'1.5\' AND id < \'3.5\'')

        # Literals are Scientific notation 15e-01 and 35e-01
        f = '''<?xml version="1.0" encoding="UTF-8"?>
            <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
              <ogc:And>
                <ogc:PropertyIsGreaterThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>15e-01</ogc:Literal>
                </ogc:PropertyIsGreaterThan>
                <ogc:PropertyIsLessThan>
                  <ogc:PropertyName>id</ogc:PropertyName>
                  <ogc:Literal>35e-01</ogc:Literal>
                </ogc:PropertyIsLessThan>
              </ogc:And>
            </ogc:Filter>
        '''
        d = QDomDocument('filter')
        d.setContent(f, True)

        e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl)
        self.assertEqual(e.expression(), 'id > \'15e-01\' AND id < \'35e-01\'')
Ejemplo n.º 45
0
    def processAlgorithm(self, parameters, context, model_feedback):
        """
        Here is where the processing itself takes place.
        """
        results = {}

        csvfile = self.parameterAsFile(parameters, self.INPUT, context)
        if csvfile is None:
            raise QgsProcessingException(self.tr('csv file error'))

        #df = QgsVirtualLayerDefinition()

        enc = self.parameterAsInt(parameters, 'ENCODING', context)

        meshLayer = self.parameterAsVectorLayer(parameters, "meshlayer",
                                                context)
        if meshLayer is None:
            raise QgsProcessingException(self.tr('mesh layer missed'))

        meshidfields = self.parameterAsFields(parameters, 'meshid', context)

        limit_sample = self.parameterAsInt(parameters, 'limit_sample', context)

        maxdivide = self.parameterAsInt(parameters, 'maxdivide', context)

        uneven_div = self.parameterAsInt(parameters, 'uneven_div', context)

        popmeshLayer = self.parameterAsVectorLayer(parameters, "popmeshlayer",
                                                   context)
        if popmeshLayer is None:
            raise QgsProcessingException(self.tr('popmes  layer missed'))

        popmeshidfields = self.parameterAsFields(parameters, 'popmeshid',
                                                 context)

        popmeshpopfields = self.parameterAsFields(parameters, 'popmeshpop',
                                                  context)

        feedback = QgsProcessingMultiStepFeedback(9 + maxdivide,
                                                  model_feedback)

        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        # 住所別集計
        alg_params = {
            'addresslayer': parameters['addresslayer'],
            'addressfield': parameters['addressfield'],
            'INPUT': csvfile,
            'ENCODING': enc,
            'CRS': None,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }

        #Stat_CSVAddressPolygon

        outputs_statv = processing.run('QGIS_stat:Stat_CSVAddressPolygon',
                                       alg_params,
                                       context=context,
                                       feedback=feedback,
                                       is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        statv = outputs_statv["OUTPUT"]
        meshid = meshidfields[0]

        #   人口メッシュと行政界メッシュのUnion作成する

        new_popfield = 'pv'

        param_uni = {
            'addresslayer': statv,
            'addressfield': parameters['addressfield'][0],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT,
            'popmeshlayer': popmeshLayer,
            'popmeshid': popmeshidfields[0],
            'popmeshpop': popmeshpopfields[0],
            'POPCOLUMN': new_popfield
        }

        feedback.setCurrentStep(2)

        res_uni = processing.run('QGIS_stat:UnionAdmAndPopMeshAlgorithm',
                                 param_uni,
                                 context=context,
                                 feedback=feedback,
                                 is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        feedback.pushConsoleInfo("csvs 1 union ok  ")

        #     union pop polygon   res_unit["OUTPUT"]
        #   population     pv
        #      address   parameters['addressfield'][0]

        #    行政界別人口の算出

        feedback.setCurrentStep(3)

        param_pop = {
            'inputlayer': res_uni['OUTPUT'],
            'agfield': parameters['addressfield'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT,
            # 'OUTPUT':parameters['OUTPUT'],
            'cfield': new_popfield
        }

        res_adpop = processing.run('QGIS_stat:AggreagteValueAlgorithm',
                                   param_pop,
                                   context=context,
                                   feedback=feedback,
                                   is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        feedback.pushConsoleInfo("csvs 1  caliculate pop adm ok  ")

        #   UNION mesh と 行政界別 人口の結合

        feedback.setCurrentStep(4)

        param_join = {
            'DISCARD_NONMATCHING': False,
            'FIELD': parameters['addressfield'],
            'FIELDS_TO_COPY': [],
            'FIELD_2': parameters['addressfield'],
            'INPUT': res_uni['OUTPUT'],
            'INPUT_2': res_adpop['OUTPUT'],
            'METHOD': 1,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT,
            #'OUTPUT':parameters['OUTPUT'],
            'PREFIX': 'op'
        }

        res_join = processing.run('qgis:joinattributestable',
                                  param_join,
                                  context=context,
                                  feedback=feedback,
                                  is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        feedback.pushConsoleInfo("csvs 1  join union mesh and popof adm  ok  ")

        #   UNION MESH  人口 と行政界人口の比率算出

        feedback.setCurrentStep(5)

        param_ratio = {
            'FIELD_LENGTH': 12,
            'FIELD_NAME': 'pvratio',
            'FIELD_PRECISION': 6,
            'FIELD_TYPE': 0,
            'FORMULA': ' \"pv\" / \"oppv\" ',
            'INPUT': res_join["OUTPUT"],
            #'OUTPUT':parameters['OUTPUT']
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT,
        }

        res_ratio = processing.run('qgis:fieldcalculator',
                                   param_ratio,
                                   context=context,
                                   feedback=feedback,
                                   is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        feedback.pushConsoleInfo(
            "csvs 1 calc ratio of adm pop and union polygon population  ok  ")

        #    Union mesh の想定集計値を算出する   住所別集計値 × ( UNION MESH  人口 と行政界人口の比率算出)

        feedback.setCurrentStep(6)

        param_ratio2 = {
            'FIELD_LENGTH': 12,
            'FIELD_NAME': 'pvsum',
            'FIELD_PRECISION': 6,
            'FIELD_TYPE': 0,
            'FORMULA': ' \"snum\" * \"pvratio\" ',
            'INPUT': res_ratio["OUTPUT"],
            #'OUTPUT':parameters['OUTPUT']
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }

        res_ratio2 = processing.run('qgis:fieldcalculator',
                                    param_ratio2,
                                    context=context,
                                    feedback=feedback,
                                    is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        feedback.pushConsoleInfo("csvs 1 calc ratio of research sample  ok  ")

        #results["OUTPUT"] = res_ratio2["OUTPUT"]
        #return results

        #    入力メッシュとUnionメッシュのUnion
        feedback.setCurrentStep(7)

        #results["OUTPUT"] = res_ratio['OUTPUT']
        #return results

        #    入力UNIONメッシュの保存

        # レイヤをGeoPackage化
        cnv_paramsg = {
            'LAYERS': res_ratio2["OUTPUT"],
            'OVERWRITE': True,
            'SAVE_STYLES': False,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
            #'OUTPUT':parameters['OUTPUT']
        }
        input_c = processing.run('native:package',
                                 cnv_paramsg,
                                 context=context,
                                 feedback=feedback,
                                 is_child_algorithm=True)

        feedback.pushConsoleInfo("csvs 1 cahnge to geopackage  ok  ")

        #results["OUTPUT"] = input_c["OUTPUT"]
        #return results

        #   集計用 人口+行政界  UNION
        input_union = input_c["OUTPUT"]

        feedback.setCurrentStep(8)
        #    create union  poplation mesh and input mesh

        param1 = {
            'INPUT': input_union,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT,
            'pareafield': 'div_area',
            'polsmpl': 'pvsum',
            'meshid': meshid,
            'meshlayer': meshLayer
        }

        #parameters['OUTPUT']
        #
        res1 = processing.run('QGIS_stat:AggregatePopMeshbyMeshAlgorithm',
                              param1,
                              context=context,
                              feedback=feedback,
                              is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        feedback.pushConsoleInfo(
            "csvs 1 AggregatePopMeshbyMeshAlgorithm  ok  ")
        numberof_under_limit = 0

        #numberof_under_limit = res1["LIMITPOL"]

        # レイヤをGeoPackage化
        alg_paramsg = {
            'LAYERS': res1["OUTPUT"],
            'OVERWRITE': True,
            'SAVE_STYLES': False,
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        retg1 = processing.run('native:package',
                               alg_paramsg,
                               context=context,
                               feedback=feedback,
                               is_child_algorithm=True)
        last_output = retg1["OUTPUT"]

        new_mesh = retg1["OUTPUT"]

        mesh_layb = retg1["OUTPUT"]

        if type(mesh_layb) is str:
            mesh_layb = QgsVectorLayer(mesh_layb, "mesh", "ogr")

        numberof_under_limit = 0

        #    作業用レイヤの作成
        crs_str = mesh_layb.crs()

        layerURI = "Polygon?crs=" + crs_str.authid()
        #feedback.pushConsoleInfo( "work layer  " + layerURI  )
        resLayer = QgsVectorLayer(layerURI, "mesh_result", "memory")

        appended = {}

        adfields = []
        for field in mesh_layb.fields():
            #print(field.name(), field.typeName())
            adfields.append(field)
            #resLayer.addField(field)

        resLayer.dataProvider().addAttributes(adfields)
        resLayer.updateFields()

        lower_ids = []

        value_column = "snum"

        #    limit 値より小さい値のポリゴン数算出
        for f in mesh_layb.getFeatures():
            # feedback.pushConsoleInfo( "value  " +str( f["value"])  )
            if not f[value_column] is None:
                if f[value_column] > 0 and f[value_column] < limit_sample:
                    numberof_under_limit += 1
                    lower_ids.append(f[meshid])

        next_output = None

        stepi = 9

        #   集計結果が最小サンプルより小さいものがある場合
        if numberof_under_limit > 0:
            #  初回の場合は終了

            feedback.pushConsoleInfo("最初の集計で指定値以下の集計値がありましたので集計を中止しました")
            results["OUTPUT"] = None
            return results

            if uneven_div:

                rmid = []
                for tgid in (lower_ids):
                    feedback.pushConsoleInfo("lower id  " + str(tgid))

                    #  next_output   code   の下3桁 削除   C27210-02    -> C27210   が last_output の code 番号
                    #  next_output  では last_output  が同じ番号の最大4メッシュを削除する

                    # リミットより小さいレコードは旧レコードを退避
                    #  リミットにひっかかるレコードを再処理用リストから削除(同一親メッシュのものも削除)
                    #   不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出   next_output  分割不能削除  next_output -> last_output 代入
                    parent_code = tgid[0:-3]

                    rmid.append(parent_code)

                addfeatures = []

                alg_paramsg_n = {
                    'LAYERS': last_output,
                    'OVERWRITE': False,
                    'SAVE_STYLES': False,
                    'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
                }
                lmesh = processing.run('native:package',
                                       alg_paramsg_n,
                                       context=context,
                                       feedback=feedback,
                                       is_child_algorithm=True)

                last_output = lmesh["OUTPUT"]

                if type(last_output) is str:
                    last_output = QgsVectorLayer(last_output, "mesh", "ogr")

                last_output.selectAll()

                for lf in last_output.getFeatures():

                    for pcode in (rmid):
                        #    feedback.pushConsoleInfo( "pcode  " + pcode+ " meshid =" + lf[meshid]  )
                        if lf[meshid] == pcode:
                            lf["fid"] = None
                            if not lf[value_column]:
                                lf[value_column] = 0.0

                            if lf[meshid] not in appended:

                                addfeatures.append(lf)
                                appended[lf[meshid]] = lf

                    #       feedback.pushConsoleInfo( "add feature   " + pcode  )

                resLayer.dataProvider().addFeatures(addfeatures)

                deleteFeatures = []

                if type(next_output) is str:
                    next_output = QgsVectorLayer(next_output, "mesh", "ogr")

                #   add check   20210310
                if next_output is None:
                    feedback.pushConsoleInfo("no next  array")
                else:
                    for nf in next_output.getFeatures():

                        for pcode in (rmid):
                            if nf[meshid][0:-3] == pcode:
                                deleteFeatures.append(nf.id())
                                feedback.pushConsoleInfo("delete id  " +
                                                         str(pcode))

                    next_output.dataProvider().deleteFeatures(deleteFeatures)

                last_output = next_output

        #  分割回数ループ
        for divide_c in range(1, maxdivide):
            feedback.setCurrentStep(stepi)

            stepi = stepi + 1

            if numberof_under_limit > 0:
                #  均等分割の場合は終了
                if not uneven_div:
                    break

            if last_output is None:
                feedback.pushConsoleInfo("last output  is none")
            else:
                if type(last_output) is str:
                    feedback.pushConsoleInfo("last output " + last_output)
                else:
                    feedback.pushConsoleInfo("last output " +
                                             last_output.name())

            alg_paramsg_m = {
                'LAYERS': last_output,
                'OVERWRITE': True,
                'SAVE_STYLES': False,
                'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
            }
            spmesh = processing.run('native:package',
                                    alg_paramsg_m,
                                    context=context,
                                    feedback=feedback,
                                    is_child_algorithm=True)

            new_mesh = agtools.SplitMeshLayer(spmesh["OUTPUT"], meshid)

            # statv  行政界別集計データ

            #  再度メッシュ集計
            param2 = {
                'INPUT': input_union,
                'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT,
                'pareafield': 'div_area',
                'polsmpl': 'pvsum',
                'meshid': meshid,
                'meshlayer': new_mesh
            }

            res2 = processing.run('QGIS_stat:AggregatePopMeshbyMeshAlgorithm',
                                  param2,
                                  context=context,
                                  feedback=feedback,
                                  is_child_algorithm=True)

            #numberof_under_limit = res2["LIMITPOL"]
            numberof_under_limit = 0
            # レイヤをGeoPackage化
            alg_paramsg2 = {
                'LAYERS': res2["OUTPUT"],
                'OVERWRITE': True,
                'SAVE_STYLES': False,
                'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
            }
            retg2 = processing.run('native:package',
                                   alg_paramsg2,
                                   context=context,
                                   feedback=feedback,
                                   is_child_algorithm=True)

            mesh_layb = retg2["OUTPUT"]

            if type(mesh_layb) is str:
                mesh_layb = QgsVectorLayer(mesh_layb, "mesh", "ogr")

                #features = mesh_layb.selectedFeatures()
                #feedback.pushConsoleInfo( "feature count  " +str( len(features))  )
            lower_ids = []
            for f in mesh_layb.getFeatures():
                #   feedback.pushConsoleInfo( "value  " +str( f["value"])  )
                if not f[value_column] is None:
                    if f[value_column] > 0 and f[value_column] < limit_sample:
                        numberof_under_limit += 1
                        lower_ids.append(f[meshid])

            if numberof_under_limit == 0:
                last_output = res2["OUTPUT"]
                next_output = retg2["OUTPUT"]
            else:
                #   不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出   next_output  分割不能削除  next_output -> last_output 代入
                # last_output = res2["OUTPUT"]
                next_output = retg2["OUTPUT"]

            #   集計結果が最小サンプルより小さいものがある場合
            if numberof_under_limit > 0:
                #  均等分割の場合は終了
                if not uneven_div:

                    break

                #  不均等分割の場合は終了データを保全  それ以外のメッシュの分割
                else:
                    rmid = []
                    for tgid in (lower_ids):
                        feedback.pushConsoleInfo("lower id  " + str(tgid))

                        #  next_output   code   の下3桁 削除   C27210-02    -> C27210   が last_output の code 番号
                        #  next_output  では last_output  が同じ番号の最大4メッシュを削除する

                        # リミットより小さいレコードは旧レコードを退避
                        #  リミットにひっかかるレコードを再処理用リストから削除(同一親メッシュのものも削除)
                        #   不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出   next_output  分割不能削除  next_output -> last_output 代入
                        parent_code = tgid[0:-3]

                        rmid.append(parent_code)

                    addfeatures = []

                    #if type(last_output) is str:
                    #    last_output =  QgsVectorLayer(last_output, "mesh", "ogr")

                    alg_paramsg_n = {
                        'LAYERS': last_output,
                        'OVERWRITE': False,
                        'SAVE_STYLES': False,
                        'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
                    }
                    lmesh = processing.run('native:package',
                                           alg_paramsg_n,
                                           context=context,
                                           feedback=feedback,
                                           is_child_algorithm=True)

                    #last_output.removeSelection()
                    last_output = lmesh["OUTPUT"]

                    if type(last_output) is str:
                        last_output = QgsVectorLayer(last_output, "mesh",
                                                     "ogr")

                    last_output.selectAll()

                    for lf in last_output.getFeatures():

                        for pcode in (rmid):
                            #    feedback.pushConsoleInfo( "pcode  " + pcode+ " meshid =" + lf[meshid]  )
                            if lf[meshid] == pcode:
                                lf["fid"] = None

                                if not lf[value_column]:
                                    lf[value_column] = 0.0

                                if lf[meshid] not in appended:

                                    addfeatures.append(lf)
                                    appended[lf[meshid]] = lf

                                    #addfeatures.append(lf)
                                    feedback.pushConsoleInfo("add feature   " +
                                                             pcode)

                    resLayer.dataProvider().addFeatures(addfeatures)

                    deleteFeatures = []

                    if type(next_output) is str:
                        next_output = QgsVectorLayer(next_output, "mesh",
                                                     "ogr")

                    for nf in next_output.getFeatures():

                        for pcode in (rmid):
                            if nf[meshid][0:-3] == pcode:
                                deleteFeatures.append(nf.id())
                                feedback.pushConsoleInfo("delete id  " +
                                                         str(pcode))

                    next_output.dataProvider().deleteFeatures(deleteFeatures)

                    last_output = next_output

        # 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.

        #  不均等分割の場合   最終作業レイヤの地物がはいってないかも
        if uneven_div:

            alg_paramsg_n = {
                'LAYERS': next_output,
                'OVERWRITE': False,
                'SAVE_STYLES': False,
                'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
            }
            lmesh = processing.run('native:package',
                                   alg_paramsg_n,
                                   context=context,
                                   feedback=feedback,
                                   is_child_algorithm=True)

            #last_output.removeSelection()
            last_output = lmesh["OUTPUT"]

            if type(last_output) is str:
                last_output = QgsVectorLayer(last_output, "mesh", "ogr")

                last_output.selectAll()

            addfeatures = []

            for lf in last_output.getFeatures():

                feedback.pushConsoleInfo("add features  meshid =" + lf[meshid])
                lf["fid"] = None
                if not lf[value_column]:
                    lf[value_column] = 0.0

                if lf[meshid] not in appended:

                    addfeatures.append(lf)
                    appended[lf[meshid]] = lf

                #addfeatures.append(lf)

            resLayer.dataProvider().addFeatures(addfeatures)

            # フォーマット変換(gdal_translate)
            alg_params = {
                'INPUT': resLayer,
                'OPTIONS': '',
                'OUTPUT': parameters['OUTPUT']
            }
            ocv = processing.run('gdal:convertformat',
                                 alg_params,
                                 context=context,
                                 feedback=feedback,
                                 is_child_algorithm=True)

            results["OUTPUT"] = ocv["OUTPUT"]
            return results

    #   均等分割の場合
        else:

            # フォーマット変換(gdal_translate)
            alg_params = {
                'INPUT': last_output,
                'OPTIONS': '',
                'OUTPUT': parameters['OUTPUT']
            }
            ocv = processing.run('gdal:convertformat',
                                 alg_params,
                                 context=context,
                                 feedback=feedback,
                                 is_child_algorithm=True)

            results["OUTPUT"] = ocv["OUTPUT"]
            return results
Ejemplo n.º 46
0
 def likInterSEC(self):
   # Iterate through species and gear
   result = []
   for sp in self.species:
     for g in self.gear[sp]:
       sp_shp = os.path.join(self.habSuitFolder, "{0}.shp".format(sp))
       gear_shp = os.path.join(self.gearFolder, "{0}.shp".format(g))
       fixgear_params = { 'INPUT' : gear_shp,
                          'OUTPUT' : 'memory:' }
       dissgear_params = { 'FIELD' : ['Rating'],
                           'OUTPUT' : 'memory:' }
       fixsp_params = { 'INPUT' : sp_shp,
                        'OUTPUT' : 'memory:' }
       disssp_params = { 'FIELD' : ['Rating'],
                         'OUTPUT' : 'memory:' }
       likinterSEC_shp = os.path.join(self.exposureFolder, "{0}_{1}_likelihood_of_interaction.shp".format(sp, g))
       params = { 'INPUT_FIELDS' : ['Rating'],
                  'OVERLAY_FIELDS' : ['Rating'],
                  'OUTPUT' : likinterSEC_shp }
       # Intersect gear with habitat suitability shapefile
       try:
         fixed_gear = processing.run('qgis:fixgeometries', fixgear_params)
         dissgear_params['INPUT'] = fixed_gear['OUTPUT']
         dissolved_gear = processing.run('qgis:dissolve', dissgear_params)
         params['INPUT'] = dissolved_gear['OUTPUT']
         
         fixed_sp = processing.run('qgis:fixgeometries', fixsp_params)
         disssp_params['INPUT'] = fixed_sp['OUTPUT']
         dissolved_sp = processing.run('qgis:dissolve', disssp_params)
         params['OVERLAY'] = dissolved_sp['OUTPUT']
         
         processing.run('qgis:intersection', params)
         # Load the intersected shapefile and add a new field for the rating
         likinterSEC_lyr = QgsVectorLayer(likinterSEC_shp)
         likinterSEC_lyr.dataProvider().addAttributes([QgsField('TMP', QVariant.Int)])
         likinterSEC_lyr.updateFields()
         # New rating is based on sum of input ratings: 2,3 -> 1, 4 -> 2, 5,6 -> 3
         for f in likinterSEC_lyr.getFeatures():
           rating_sum = f['RATING'] + f['RATING_2']
           if rating_sum <= 3:
             new_rating = 1
           if rating_sum == 4:
             new_rating = 2
           if rating_sum >= 5:
             new_rating = 3
           # 2 is the index of the new TMP field
           likinterSEC_lyr.dataProvider().changeAttributeValues({f.id(): {2: new_rating}})
         # Delete old fields, create a new RATING based on TMP
         likinterSEC_lyr.dataProvider().deleteAttributes([0, 1])
         likinterSEC_lyr.dataProvider().addAttributes([QgsField('RATING', QVariant.Int)])
         likinterSEC_lyr.updateFields()
         for f in likinterSEC_lyr.getFeatures():
           new_rating = f['TMP']
           # 1 is the index of the new RATING field
           likinterSEC_lyr.dataProvider().changeAttributeValues({f.id(): {1: new_rating}})
         likinterSEC_lyr.dataProvider().deleteAttributes([0])
         result.append((sp, g, True))
       except:
         result.append((sp, g, False))
   # Return results
   return result
Ejemplo n.º 47
0
    def testSaveFields(self):
        # Create a new memory layer with no fields
        myMemoryLayer = QgsVectorLayer(('Point?crs=epsg:4326&index=yes'),
                                       'test', 'memory')

        # Add some fields to the layer
        myFields = [
            QgsField('TestInt', QVariant.Int, 'integer', 2, 0),
            QgsField('TestLong', QVariant.LongLong, 'long', -1, 0),
            QgsField('TestDbl', QVariant.Double, 'double', 8, 6),
            QgsField('TestString', QVariant.String, 'string', 50, 0),
            QgsField('TestDate', QVariant.Date, 'date'),
            QgsField('TestTime', QVariant.Time, 'time'),
            QgsField('TestDateTime', QVariant.DateTime, 'datetime'),
            QgsField("vallist", QVariant.List, subType=QVariant.Int),
            QgsField("stringlist",
                     QVariant.StringList,
                     subType=QVariant.String),
            QgsField("stringlist2", QVariant.List, subType=QVariant.String),
            QgsField("reallist", QVariant.List, subType=QVariant.Double),
            QgsField("longlist", QVariant.List, subType=QVariant.LongLong),
            QgsField("dict", QVariant.Map)
        ]
        self.assertTrue(myMemoryLayer.startEditing())
        for f in myFields:
            assert myMemoryLayer.addAttribute(f)
        self.assertTrue(myMemoryLayer.commitChanges())
        myMemoryLayer.updateFields()

        for f in myFields:
            self.assertEqual(f, myMemoryLayer.fields().field(f.name()))

        # Export the layer to a layer-definition-XML
        qlr = QgsLayerDefinition.exportLayerDefinitionLayers(
            [myMemoryLayer], QgsReadWriteContext())
        self.assertIsNotNone(qlr)

        # Import the layer from the layer-definition-XML
        layers = QgsLayerDefinition.loadLayerDefinitionLayers(
            qlr, QgsReadWriteContext())
        self.assertTrue(layers)
        myImportedLayer = layers[0]
        self.assertIsNotNone(myImportedLayer)

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        for f in myFields:
            self.assertEqual(f.name(), importedFields.field(f.name()).name())
            if f.name() != 'stringlist2':
                self.assertEqual(f.type(),
                                 importedFields.field(f.name()).type())
            else:
                # we automatically convert List with String subtype to StringList, to match other data providers
                self.assertEqual(
                    importedFields.field(f.name()).type(), QVariant.StringList)

            self.assertEqual(f.subType(),
                             importedFields.field(f.name()).subType())
            self.assertEqual(f.precision(),
                             importedFields.field(f.name()).precision())
            self.assertEqual(f.length(),
                             importedFields.field(f.name()).length())
Ejemplo n.º 48
0
class BulkNominatimDialog(QDialog, FORM_CLASS):
    def __init__(self, iface, parent, settings):
        '''Initialize the bulk nominatim dialog box'''
        super(BulkNominatimDialog, self).__init__(parent)
        self.setupUi(self)
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.settings = settings
        self.addressMapLayerComboBox.setFilters(
            QgsMapLayerProxyModel.VectorLayer)
        self.addressMapLayerComboBox.layerChanged.connect(self.findFields)
        self.mMapLayerComboBox.setFilters(QgsMapLayerProxyModel.PointLayer)

    def accept(self):
        '''process and geocode the addresses'''
        selected_tab = self.tabWidget.currentIndex()
        # Clear the Results Dialog box
        self.resultsTextEdit.clear()
        if selected_tab == 0:
            self.processAddressTable()
        elif selected_tab == 1:
            self.processFreeFormData()
        else:
            self.reverseGeocode()

    def showEvent(self, event):
        '''The dialog is being shown. We need to initialize it.'''
        super(BulkNominatimDialog, self).showEvent(event)
        self.findFields()

    def request(self, url):
        fetcher = QgsNetworkContentFetcher()
        fetcher.fetchContent(QUrl(url))
        evloop = QEventLoop()
        fetcher.finished.connect(evloop.quit)
        evloop.exec_(QEventLoop.ExcludeUserInputEvents)
        fetcher.finished.disconnect(evloop.quit)
        return fetcher.contentAsString()

    def reverseGeocode(self):
        layer = self.mMapLayerComboBox.currentLayer()
        if not layer:
            self.iface.messageBar().pushMessage(
                "",
                "No valid point vector layer to reverse geocode",
                level=QgsMessageBar.WARNING,
                duration=2)
            return

        showDetails = int(self.detailedAddressCheckBox.isChecked())
        self.numAddress = layer.featureCount()
        self.numErrors = 0
        if self.numAddress > self.settings.maxAddress:
            self.iface.messageBar().pushMessage(
                "",
                "Maximum geocodes to process were exceeded. Please reduce the number and try again.",
                level=QgsMessageBar.WARNING,
                duration=4)
            return

        layername = self.layerLineEdit.text()
        self.createPointLayerReverse()

        layerCRS = layer.crs()
        epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326")
        transform = QgsCoordinateTransform(layerCRS, epsg4326,
                                           QgsProject.instance())

        iter = layer.getFeatures()

        for feature in iter:
            # already know that this is a point vector layer
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            pt = transform.transform(pt.x(), pt.y())
            newfeature = QgsFeature()
            newfeature.setGeometry(QgsGeometry.fromPointXY(pt))
            lat = str(pt.y())
            lon = str(pt.x())
            url = '{}?format=json&lat={}&lon={}&zoom=18&addressdetails={}'.format(
                self.settings.reverseURL(), lat, lon, showDetails)
            jsondata = self.request(url)
            # print(jsondata)
            address = ''
            try:
                jd = json.loads(jsondata)
                if len(jd) == 0:
                    raise ValueError('')
                display_name = self.fieldValidate(jd, 'display_name')
                if showDetails:
                    osm_type = self.fieldValidate(jd, 'osm_type')
                    osm_id = self.fieldValidate(jd, 'osm_id')
                    house_number = ''
                    road = ''
                    neighbourhood = ''
                    locality = ''
                    town = ''
                    city = ''
                    county = ''
                    state = ''
                    postcode = ''
                    country = ''
                    country_code = ''
                    if 'address' in jd:
                        house_number = self.fieldValidate(
                            jd['address'], 'house_number')
                        road = self.fieldValidate(jd['address'], 'road')
                        neighbourhood = self.fieldValidate(
                            jd['address'], 'neighbourhood')
                        locality = self.fieldValidate(jd['address'],
                                                      'locality')
                        town = self.fieldValidate(jd['address'], 'town')
                        city = self.fieldValidate(jd['address'], 'city')
                        county = self.fieldValidate(jd['address'], 'county')
                        state = self.fieldValidate(jd['address'], 'state')
                        postcode = self.fieldValidate(jd['address'],
                                                      'postcode')
                        country = self.fieldValidate(jd['address'], 'country')
                        country_code = self.fieldValidate(
                            jd['address'], 'country_code')
                    feature.setAttributes([
                        osm_type, osm_id, display_name, house_number, road,
                        neighbourhood, locality, town, city, county, state,
                        postcode, country, country_code
                    ])
                    self.provider.addFeatures([feature])
                else:
                    feature.setAttributes([display_name])
                    self.provider.addFeatures([feature])
            except Exception:
                self.numErrors += 1

        self.pointLayer.updateExtents()
        QgsProject.instance().addMapLayer(self.pointLayer)
        if self.numAddress > 0:
            self.resultsTextEdit.appendPlainText('Total Points Processed: ' +
                                                 str(self.numAddress))
            self.resultsTextEdit.appendPlainText('Processing Complete!')

    def findFields(self):
        if not self.isVisible():
            return
        layer = self.addressMapLayerComboBox.currentLayer()
        if not layer:
            self.clearLayerFields()
        else:
            header = [u"--- Select Column ---"]
            fields = layer.fields()
            for field in fields.toList():
                # force it to be lower case - makes matching easier
                name = field.name()
                header.append(name)
            self.configureLayerFields(header)

    def processAddressTable(self):
        layer = self.addressMapLayerComboBox.currentLayer()
        if not layer:
            self.iface.messageBar().pushMessage(
                "",
                "No valid table or vector layer to reverse geocode",
                level=QgsMessageBar.WARNING,
                duration=4)
            return
        self.numAddress = layer.featureCount()
        if not self.numAddress:
            self.iface.messageBar().pushMessage("",
                                                "No addresses to geocode",
                                                level=QgsMessageBar.WARNING,
                                                duration=4)
            return

        self.numErrors = 0
        if self.numAddress > self.settings.maxAddress:
            self.iface.messageBar().pushMessage(
                "",
                "Maximum geocodes to process were exceeded. Please reduce the number and try again.",
                level=QgsMessageBar.WARNING,
                duration=4)
            return

        maxResults = self.maxResultsSpinBox.value()
        showDetails = int(self.detailedAddressCheckBox.isChecked())
        self.pointLayer = None
        self.createPointLayer()

        iter = layer.getFeatures(QgsFeatureRequest().setFlags(
            QgsFeatureRequest.NoGeometry))
        full_address_idx = self.fullAddressComboBox.currentIndex() - 1
        street_num_idx = self.numberComboBox.currentIndex() - 1
        street_name_idx = self.streetNameComboBox.currentIndex() - 1
        city_idx = self.cityComboBox.currentIndex() - 1
        county_idx = self.countyComboBox.currentIndex() - 1
        state_idx = self.stateComboBox.currentIndex() - 1
        country_idx = self.countryComboBox.currentIndex() - 1
        postal_idx = self.postalCodeComboBox.currentIndex() - 1

        for feature in iter:
            self.isfirst = True
            if full_address_idx >= 0:
                address = feature[full_address_idx].strip()
                address2 = re.sub('\s+', '+', address)
                url = self.settings.searchURL() + '?q=' + address2
            else:
                address = ','.join(
                    [str(x) if x else '' for x in feature.attributes()])
                url = self.settings.searchURL() + '?'
                if street_name_idx >= 0:
                    num = ''
                    name = ''
                    if street_num_idx >= 0 and feature[street_num_idx]:
                        num = ('{}'.format(feature[street_num_idx])).strip()
                    if feature[street_name_idx]:
                        name = ('{}'.format(feature[street_name_idx])).strip()
                    street = num + ' ' + name
                    street = street.strip()
                    if street:
                        url += self.formatParam('street', street)
                if city_idx >= 0:
                    url += self.formatParam('city', feature[city_idx])
                if county_idx >= 0:
                    url += self.formatParam('county', feature[county_idx])
                if state_idx >= 0:
                    url += self.formatParam('state', feature[state_idx])
                if country_idx >= 0:
                    url += self.formatParam('country', feature[country_idx])
                if postal_idx >= 0:
                    url += self.formatParam('postalcode', feature[postal_idx])

            url += '&format=json&limit={}&polygon=0&addressdetails={}'.format(
                maxResults, showDetails)
            jsondata = self.request(url)

            try:
                jd = json.loads(jsondata)
                if len(jd) == 0:
                    raise ValueError(address)
                for addr in jd:
                    try:
                        lat = addr['lat']
                        lon = addr['lon']
                    except:
                        raise ValueError(address)

                    newfeature = QgsFeature()
                    newfeature.setGeometry(
                        QgsGeometry.fromPointXY(
                            QgsPointXY(float(lon), float(lat))))
                    display_name = self.fieldValidate(addr, 'display_name')

                    if self.detailedAddressCheckBox.checkState():
                        osm_type = self.fieldValidate(addr, 'osm_type')
                        osm_id = self.fieldValidate(addr, 'osm_id')
                        osm_class = self.fieldValidate(addr, 'class')
                        type = self.fieldValidate(addr, 'type')
                        house_number = ''
                        road = ''
                        neighbourhood = ''
                        locality = ''
                        town = ''
                        city = ''
                        county = ''
                        state = ''
                        postcode = ''
                        country = ''
                        country_code = ''
                        if 'address' in addr:
                            house_number = self.fieldValidate(
                                addr['address'], 'house_number')
                            road = self.fieldValidate(addr['address'], 'road')
                            neighbourhood = self.fieldValidate(
                                addr['address'], 'neighbourhood')
                            locality = self.fieldValidate(
                                addr['address'], 'locality')
                            town = self.fieldValidate(addr['address'], 'town')
                            city = self.fieldValidate(addr['address'], 'city')
                            county = self.fieldValidate(
                                addr['address'], 'county')
                            state = self.fieldValidate(addr['address'],
                                                       'state')
                            postcode = self.fieldValidate(
                                addr['address'], 'postcode')
                            country = self.fieldValidate(
                                addr['address'], 'country')
                            country_code = self.fieldValidate(
                                addr['address'], 'country_code')
                        newfeature.setAttributes([
                            osm_type, osm_id, osm_class, type, address,
                            display_name, house_number, road, neighbourhood,
                            locality, town, city, county, state, postcode,
                            country, country_code
                        ])
                        self.provider.addFeatures([newfeature])
                    else:
                        # Display only the resulting output address
                        newfeature.setAttributes([display_name])
                        self.provider.addFeatures([newfeature])
            except Exception as e:
                if self.numErrors == 0:
                    self.resultsTextEdit.appendPlainText('Address Errors')
                self.numErrors += 1
                self.resultsTextEdit.appendPlainText(str(e))

        if self.numAddress > 0:
            self.pointLayer.updateExtents()
            QgsProject.instance().addMapLayer(self.pointLayer)
            self.resultsTextEdit.appendPlainText(
                'Number of Addresses Processed: ' + str(self.numAddress))
            self.resultsTextEdit.appendPlainText('Number of Successes: ' +
                                                 str(self.numAddress -
                                                     self.numErrors))
            self.resultsTextEdit.appendPlainText('Number of Errors: ' +
                                                 str(self.numErrors))
            self.resultsTextEdit.appendPlainText('Processing Complete!')

    def formatParam(self, tag, value):
        if value:
            value = ('{}'.format(value)).strip()
            value = re.sub('\s+', '%20', value)
        else:
            value = ''
        if self.isfirst:
            url = '{}={}'.format(tag, value)
            self.isfirst = False
        else:
            url = '&{}={}'.format(tag, value)
        return url

    def processFreeFormData(self):
        addresses = []

        # Get the text for the Address Query Box an dgo through line by line to geocode it
        inputtext = str(self.addressTextEdit.toPlainText())
        lines = inputtext.splitlines()
        self.pointLayer = None
        self.numAddress = 0
        self.numErrors = 0

        # Create a list of all the Addresses. We want to get an accurate count
        for address in lines:
            # Get rid of beginning and end space
            address = address.strip()
            # Skip any blank lines
            if not address:
                continue
            self.numAddress += 1
            addresses.append(address)

        if self.numAddress > self.settings.maxAddress:
            self.iface.messageBar().pushMessage(
                "",
                "Maximum addresses to process were exceeded. Please reduce the number and try again.",
                level=QgsMessageBar.WARNING,
                duration=4)
            return

        if self.numAddress:
            self.createPointLayer()
        maxResults = self.maxResultsSpinBox.value()
        showDetails = int(self.detailedAddressCheckBox.isChecked())

        for address in addresses:
            # Replace internal spaces with + signs
            address2 = re.sub('\s+', '+', address)
            url = '{}?q={}&format=json&limit={}&polygon=0&addressdetails={}'.format(
                self.settings.searchURL(), address2, maxResults, showDetails)
            jsondata = self.request(url)
            # print(jsondata)
            try:
                jd = json.loads(jsondata)
                if len(jd) == 0:
                    raise ValueError(address)
                for addr in jd:
                    try:
                        lat = addr['lat']
                        lon = addr['lon']
                    except:
                        raise ValueError(address)

                    feature = QgsFeature()
                    feature.setGeometry(
                        QgsGeometry.fromPointXY(
                            QgsPointXY(float(lon), float(lat))))
                    display_name = self.fieldValidate(addr, 'display_name')

                    if self.detailedAddressCheckBox.checkState():
                        osm_type = self.fieldValidate(addr, 'osm_type')
                        osm_id = self.fieldValidate(addr, 'osm_id')
                        osm_class = self.fieldValidate(addr, 'class')
                        type = self.fieldValidate(addr, 'type')
                        house_number = ''
                        road = ''
                        neighbourhood = ''
                        locality = ''
                        town = ''
                        city = ''
                        county = ''
                        state = ''
                        postcode = ''
                        country = ''
                        country_code = ''
                        if 'address' in addr:
                            house_number = self.fieldValidate(
                                addr['address'], 'house_number')
                            road = self.fieldValidate(addr['address'], 'road')
                            neighbourhood = self.fieldValidate(
                                addr['address'], 'neighbourhood')
                            locality = self.fieldValidate(
                                addr['address'], 'locality')
                            town = self.fieldValidate(addr['address'], 'town')
                            city = self.fieldValidate(addr['address'], 'city')
                            county = self.fieldValidate(
                                addr['address'], 'county')
                            state = self.fieldValidate(addr['address'],
                                                       'state')
                            postcode = self.fieldValidate(
                                addr['address'], 'postcode')
                            country = self.fieldValidate(
                                addr['address'], 'country')
                            country_code = self.fieldValidate(
                                addr['address'], 'country_code')
                        feature.setAttributes([
                            osm_type, osm_id, osm_class, type, address,
                            display_name, house_number, road, neighbourhood,
                            locality, town, city, county, state, postcode,
                            country, country_code
                        ])
                        self.provider.addFeatures([feature])
                    else:
                        # Display only the resulting output address
                        feature.setAttributes([display_name])
                        self.provider.addFeatures([feature])
            except Exception as e:
                if self.numErrors == 0:
                    self.resultsTextEdit.appendPlainText('Address Errors')
                self.numErrors += 1
                self.resultsTextEdit.appendPlainText(str(e))

        if self.numAddress > 0:
            self.pointLayer.updateExtents()
            QgsProject.instance().addMapLayer(self.pointLayer)
            self.resultsTextEdit.appendPlainText(
                'Number of Addresses Processed: ' + str(self.numAddress))
            self.resultsTextEdit.appendPlainText('Number of Successes: ' +
                                                 str(self.numAddress -
                                                     self.numErrors))
            self.resultsTextEdit.appendPlainText('Number of Errors: ' +
                                                 str(self.numErrors))
            self.resultsTextEdit.appendPlainText('Processing Complete!')

    def fieldValidate(self, data, name):
        if name in data:
            return str(data[name])
        return ''

    def createPointLayerReverse(self):
        layername = self.layerLineEdit.text()
        self.pointLayer = QgsVectorLayer("point?crs=epsg:4326", layername,
                                         "memory")
        self.provider = self.pointLayer.dataProvider()
        if self.detailedAddressCheckBox.checkState():
            self.provider.addAttributes([
                QgsField("osm_type", QVariant.String),
                QgsField("osm_id", QVariant.String),
                QgsField("display_name", QVariant.String),
                QgsField("house_number", QVariant.String),
                QgsField("road", QVariant.String),
                QgsField("neighbourhood", QVariant.String),
                QgsField("locality", QVariant.String),
                QgsField("town", QVariant.String),
                QgsField("city", QVariant.String),
                QgsField("county", QVariant.String),
                QgsField("state", QVariant.String),
                QgsField("postcode", QVariant.String),
                QgsField("country", QVariant.String),
                QgsField("country_code", QVariant.String)
            ])
        else:
            self.provider.addAttributes(
                [QgsField("display_name", QVariant.String)])
        self.pointLayer.updateFields()
        if self.showLabelCheckBox.checkState():
            # Display labels
            label = QgsPalLayerSettings()
            label.fieldName = 'display_name'
            label.placement = QgsPalLayerSettings.AroundPoint
            labeling = QgsVectorLayerSimpleLabeling(label)
            self.pointLayer.setLabeling(labeling)
            self.pointLayer.setLabelsEnabled(True)

    def createPointLayer(self):
        layername = self.layerLineEdit.text()
        self.pointLayer = QgsVectorLayer("point?crs=epsg:4326", layername,
                                         "memory")
        self.provider = self.pointLayer.dataProvider()
        if self.detailedAddressCheckBox.checkState():
            self.provider.addAttributes([
                QgsField("osm_type", QVariant.String),
                QgsField("osm_id", QVariant.String),
                QgsField("class", QVariant.String),
                QgsField("type", QVariant.String),
                QgsField("source_addr", QVariant.String),
                QgsField("display_name", QVariant.String),
                QgsField("house_number", QVariant.String),
                QgsField("road", QVariant.String),
                QgsField("neighbourhood", QVariant.String),
                QgsField("locality", QVariant.String),
                QgsField("town", QVariant.String),
                QgsField("city", QVariant.String),
                QgsField("county", QVariant.String),
                QgsField("state", QVariant.String),
                QgsField("postcode", QVariant.String),
                QgsField("country", QVariant.String),
                QgsField("country_code", QVariant.String)
            ])
        else:
            self.provider.addAttributes(
                [QgsField("display_name", QVariant.String)])
        self.pointLayer.updateFields()
        if self.showLabelCheckBox.checkState():
            # Display labels
            label = QgsPalLayerSettings()
            label.fieldName = 'display_name'
            label.placement = QgsPalLayerSettings.AroundPoint
            labeling = QgsVectorLayerSimpleLabeling(label)
            self.pointLayer.setLabeling(labeling)
            self.pointLayer.setLabelsEnabled(True)

    def configureLayerFields(self, header):
        self.clearLayerFields()
        self.fullAddressComboBox.addItems(header)
        self.numberComboBox.addItems(header)
        self.streetNameComboBox.addItems(header)
        self.cityComboBox.addItems(header)
        self.countyComboBox.addItems(header)
        self.stateComboBox.addItems(header)
        self.countryComboBox.addItems(header)
        self.postalCodeComboBox.addItems(header)

        street_num_col = street_name_col = city_col = county_col = state_col = country_col = postal_col = -1
        for x, item in enumerate(header):
            # Skip the header line
            if x == 0:
                continue
            # force it to be lower case - makes matching easier
            item = item.lower()
            if bool(re.search('num', item)):
                street_num_col = x
            elif bool(re.search('name', item)) or item.startswith('road'):
                street_name_col = x
            elif item.startswith('city'):
                city_col = x
            elif item.startswith('county'):
                county_col = x
            elif item.startswith('state'):
                state_col = x
            elif item.startswith('country'):
                country_col = x
            elif item.startswith('postal'):
                postal_col = x
        if street_num_col != -1:
            self.numberComboBox.setCurrentIndex(street_num_col)
        if street_name_col != -1:
            self.streetNameComboBox.setCurrentIndex(street_name_col)
        if city_col != -1:
            self.cityComboBox.setCurrentIndex(city_col)
        if county_col != -1:
            self.countyComboBox.setCurrentIndex(county_col)
        if state_col != -1:
            self.stateComboBox.setCurrentIndex(state_col)
        if country_col != -1:
            self.countryComboBox.setCurrentIndex(country_col)
        if postal_col != -1:
            self.postalCodeComboBox.setCurrentIndex(postal_col)
        self.fullAddressComboBox.setCurrentIndex(0)

    def clearLayerFields(self):
        self.fullAddressComboBox.clear()
        self.numberComboBox.clear()
        self.streetNameComboBox.clear()
        self.cityComboBox.clear()
        self.countyComboBox.clear()
        self.stateComboBox.clear()
        self.countryComboBox.clear()
        self.postalCodeComboBox.clear()
Ejemplo n.º 49
0
    def accept(self):
        layer = self.mMapLayerComboBox.currentLayer()
        if not layer:
            self.iface.messageBar().pushMessage("",
                                                "No Valid Layer to Process",
                                                level=QgsMessageBar.WARNING,
                                                duration=4)
            return
        layer_name = self.nameLineEdit.text()

        selectedField = self.mFieldComboBox.currentField()
        fieldIndex = layer.fields().lookupField(selectedField)
        if fieldIndex == -1:
            self.iface.messageBar().pushMessage("",
                                                "Invalid MGRS Field",
                                                level=QgsMessageBar.WARNING,
                                                duration=4)
            return

        fields = layer.pendingFields()
        # Check to see if the field is of the right type
        f = fields.at(fieldIndex)
        if f.type() != QVariant.String:
            self.iface.messageBar().pushMessage(
                "",
                "Selected MGRS Field is not a valid data type",
                level=QgsMessageBar.WARNING,
                duration=4)
            return

        pointLayer = QgsVectorLayer("Point?crs=epsg:4326", layer_name,
                                    "memory")
        ppoint = pointLayer.dataProvider()
        ppoint.addAttributes(fields)
        pointLayer.updateFields()

        iter = layer.getFeatures()

        num_features = 0
        num_bad = 0
        for feature in iter:
            num_features += 1
            m = feature[fieldIndex]
            try:
                m = re.sub(r'\s+', '', str(m))  # Remove all white space
                lat, lon = mgrs.toWgs(m)
            except:
                #traceback.print_exc()
                num_bad += 1
                continue
            f = QgsFeature()
            f.setGeometry(QgsGeometry.fromPoint(QgsPointXY(lon, lat)))
            f.setAttributes(feature.attributes())
            ppoint.addFeatures([f])

        pointLayer.updateExtents()
        QgsProject.instance().addMapLayer(pointLayer)

        if num_bad != 0:
            self.iface.messageBar().pushMessage(
                "",
                "{} out of {} features failed".format(num_bad, num_features),
                level=QgsMessageBar.WARNING,
                duration=4)

        self.close()
Ejemplo n.º 50
0
rounded = math.ceil(interpolated)

if side == 'Left' and rounded % 2 == 0:
    streetnum = rounded + 1
elif side == 'Left' and rounded % 2 !=0:
    streetnum = rounded
elif side == 'Right' and rounded % 2 == 0:
    streetnum = rounded
elif side == 'Right' and rounded % 2 != 0:
    streetnum = rounded + 1

address = '{:.0f}, {}'.format(streetnum, street_name)
side = '{} side of street'.format(side)
message = '{}, ({})'.format(address, side)
iface.messageBar().pushMessage(message)

# Create a point layer showing the nearest point whose address we determined
vlayer = QgsVectorLayer('Point?crs=EPSG:2274', 'point', 'memory')
provider = vlayer.dataProvider()
provider.addAttributes([QgsField(address_attribute_name, QVariant.String)])
vlayer.updateFields() 

f = QgsFeature()
f.setGeometry(nearest_point)
f.setAttributes([address])
provider = vlayer.dataProvider()
provider.addFeature(f)
vlayer.updateExtents() 
QgsProject.instance().addMapLayer(vlayer)
iface.setActiveLayer(point_layer)
Ejemplo n.º 51
0
class AssessmentDlg(QDialog, DIALOG_CLASS):

    closingPlugin = pyqtSignal()
    dataChange = pyqtSignal(QRiSProject, str)

    def __init__(self, qris_project):
        """Used to construct the new assessment dialog"""
        QDialog.__init__(self, None)
        self.setupUi(self)

        self.qris_project = qris_project
        self.qris_project.assessments_path = os.path.join(
            self.qris_project.project_path, "Assessments.gpkg")
        # create the db if it isn't there?
        if not os.path.exists(self.qris_project.assessments_path):
            self.load_assessment_gpkg()
        # add signals to buttons
        self.pushButton_save_assessment.clicked.connect(self.save_assessment)
        self.pushButton_cancel_assessment.clicked.connect(
            self.cancel_assessment)

    # def text_validate(self):
    #     text = self.txtLayerName.text()
    #     out_text = ''.join(e for e in text.replace(" ", "_") if e.isalnum() or e == "_")
    #     self.txtProjectLayerPath.setText(os.path.join("ProjectLayers.gpkg", out_text))
    #     self.layer_path_name = out_text
    #     self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
    def load_assessment_gpkg(self):
        """Creates it if it doesn't."""
        # layer for creating the geopackage
        memory_create = QgsVectorLayer("NoGeometry", "memory_create", "memory")
        # write to disk
        QgsVectorFileWriter.writeAsVectorFormat(
            memory_create,
            self.qris_project.assessments_path,
            'utf-8',
            driverName='GPKG',
            onlySelected=False)

        # create assessments table and write to geopackage
        memory_assessments = QgsVectorLayer("NoGeometry", "memory_assessments",
                                            "memory")
        # copy the memory layer to the geopackage with a parent
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.layerName = "assessments"
        options.driverName = 'GPKG'
        if os.path.exists(self.qris_project.assessments_path):
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
            QgsVectorFileWriter.writeAsVectorFormat(
                memory_assessments, self.qris_project.assessments_path,
                options)
            self.assessments_layer = QgsVectorLayer(
                self.qris_project.assessments_path + "|layername=assessments",
                "assessments", "ogr")
            # the data model and add fields
            assessment_date_field = QgsField("assessment_date", QVariant.Date)
            assessment_description_field = QgsField("assessment_description",
                                                    QVariant.String)
            pr = self.assessments_layer.dataProvider()
            pr.addAttributes(
                [assessment_date_field, assessment_description_field])
            self.assessments_layer.updateFields()

        # add the dam table
        memory_dams = QgsVectorLayer("Point", "memory_dams", "memory")
        # copy the memory layer to the geopackage with a parent
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.layerName = "dams"
        options.driverName = 'GPKG'
        if os.path.exists(self.qris_project.assessments_path):
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
            QgsVectorFileWriter.writeAsVectorFormat(
                memory_dams, self.qris_project.assessments_path, options)
            self.dams_layer = QgsVectorLayer(
                self.qris_project.assessments_path + "|layername=dams", "dams",
                "ogr")
            # the data model and add fields to the layer
            assessment_id = QgsField("assessment_id", QVariant.Int)
            dam_type_field = QgsField("dam_type", QVariant.String)
            dam_description_field = QgsField("dam_description",
                                             QVariant.String)
            pr = self.dams_layer.dataProvider()
            pr.addAttributes(
                [assessment_id, dam_type_field, dam_description_field])
            self.dams_layer.updateFields()

    def save_assessment(self):
        """Creates and saves a new assessment record to the db from the assessment dialog"""
        # set an index for the new deployment_idThird o
        # TODO get rid of this reference to assessments_layer here? It should be created above
        self.assessments_layer = QgsVectorLayer(
            self.qris_project.assessments_path + "|layername=assessments",
            "assessments", "ogr")
        index_assessment_fid = self.assessments_layer.fields().indexOf("fid")
        # use try because does not like a max value of 0
        try:
            new_assessment_fid = self.assessments_layer.maximumValue(
                index_assessment_fid) + 1
        except TypeError:
            new_assessment_fid = 1
        # # grab the form values
        new_assessment_date = self.dateEdit_assessment_date.date()
        new_assessment_description = self.plainTextEdit_assessment_description.toPlainText(
        )
        # # create a blank QgsFeature that copies the deployemnt table
        new_assessment_feature = QgsFeature(self.assessments_layer.fields())
        # # set the form values to the feature
        new_assessment_feature.setAttribute("fid", new_assessment_fid)
        new_assessment_feature.setAttribute("assessment_date",
                                            new_assessment_date)
        new_assessment_feature.setAttribute("assessment_description",
                                            new_assessment_description)
        # # TODO add ability to manually enter lat long?
        pr = self.assessments_layer.dataProvider()
        pr.addFeatures([new_assessment_feature])

        # get an assessment name
        new_assessment_name = new_assessment_date.toString('yyyy-MM-dd')
        # create a qris_project.Layer constructor
        # TODO double check what the path looks like for other layers?
        self.qris_project.project_assessments = True
        # TODO call export file to write that shit to the xml
        self.qris_project.write_project_xml()
        # Send information used in the tree so it can be added to the map.
        self.dataChange.emit(self.qris_project, new_assessment_name)
        self.close()

    def cancel_assessment(self):
        self.close()
def main(iface):
    ### Let's go!
    print(datetime.now())

    purp_name = ['Leisure', 'Shopping', 'Services', 'Touring']
    # purp_name = ['Leisure']

    # Dictionnaries for parameters

    origins = '/tmp/origins.shp'

    for name in purp_name:
        gravity = poi_gravity_values[name]
        mode_b = mode_params_bike[name]
        mode_eb = mode_params_ebike[name]

        # 1. Join origin sizes to shortest path

        paths = '/tmp/Paths_' + name + '.shp'
        processing.run(
            "native:joinattributestable",
            {
                'INPUT': paths,
                'FIELD': 'FromFID',
                'INPUT_2': origins,
                'FIELD_2': 'ID',
                'FIELDS_TO_COPY': ['Totalt'],
                'METHOD': 0,
                'DISCARD_NONMATCHING': False,
                'PREFIX': '',
                'OUTPUT': '/tmp/WeightedPaths_' + name + '.shp',
            },
        )
        weighted_paths = '/tmp/WeightedPaths_' + name + '.shp'

        # 2. Apply distance-decay functions

        work_layer = QgsVectorLayer(weighted_paths, '', 'ogr')
        work_layer.dataProvider().addAttributes(
            [QgsField("exp", QVariant.Double, "float", 8, 3)])
        work_layer.dataProvider().addAttributes(
            [QgsField("fbike", QVariant.Double, "float", 8, 3)])
        work_layer.dataProvider().addAttributes(
            [QgsField("febike", QVariant.Double, "float", 8, 3)])
        work_layer.updateFields()

        features = work_layer.getFeatures()
        with edit(work_layer):
            for f in features:
                X = f['Distance']

                # Destination choice: exponential
                f['exp'] = math.exp(gravity * float(X) / 1000)

                # Mode choice probabilities
                f['fbike'] = sigmoid(mode_b[0], mode_b[1], mode_b[2],
                                     mode_b[3], X)
                f['febike'] = sigmoid(mode_eb[0], mode_eb[1], mode_eb[2],
                                      mode_eb[3], X)

                work_layer.updateFeature(f)

        X = processing.run(
            "native:fieldcalculator",
            {
                'INPUT': '/tmp/WeightedPaths_' + name + '.shp',
                'FIELD_NAME': 'Weight_bike',
                'FIELD_TYPE': 0,
                'FIELD_LENGTH': 0,
                'FIELD_PRECISION': 0,
                'FORMULA': 'Totalt*fbike*exp/sum(exp,FromFID)',
                'OUTPUT': 'TEMPORARY_OUTPUT',
            },
        )

        processing.run(
            "native:fieldcalculator",
            {
                'INPUT': X['OUTPUT'],
                'FIELD_NAME': 'Weight_ebike',
                'FIELD_TYPE': 0,
                'FIELD_LENGTH': 0,
                'FIELD_PRECISION': 0,
                'FORMULA': 'Totalt*febike*exp/sum(exp,FromFID)',
                'OUTPUT': '/tmp/WeightedPathsFinal_' + name + '.shp',
            },
        )
        weighted_paths_final = '/tmp/WeightedPathsFinal_' + name + '.shp'
        iface.addVectorLayer(weighted_paths_final, '', 'ogr')

    print(datetime.now())
Ejemplo n.º 53
0
    def get_inner_rings_layer(self,
                              plot_layer,
                              id_field=ID_FIELD,
                              use_selection=False):
        id_field_idx = plot_layer.fields().indexFromName(id_field)
        request = QgsFeatureRequest().setSubsetOfAttributes([id_field_idx])
        polygons = plot_layer.getSelectedFeatures(
            request) if use_selection else plot_layer.getFeatures(request)

        layer = QgsVectorLayer("LineString?crs=EPSG:{}".format(DEFAULT_EPSG),
                               "rings", "memory")
        data_provider = layer.dataProvider()
        data_provider.addAttributes([QgsField(ID_FIELD, QVariant.Int)])
        layer.updateFields()

        features = []

        for polygon in polygons:
            polygon_geom = polygon.geometry()
            is_multipart = polygon_geom.isMultipart()

            # Does the current multipolygon have inner rings?
            has_inner_rings = False
            multi_polygon = None
            single_polygon = None

            if is_multipart:

                multi_polygon = polygon_geom.constGet()

                # TODO: remove when the error is resolved
                if type(multi_polygon) != QgsMultiPolygon:
                    geom = QgsMultiPolygon()
                    geom.fromWkt(polygon_geom.asWkt())
                    multi_polygon = geom

                for part in range(multi_polygon.numGeometries()):
                    if multi_polygon.ringCount(part) > 1:
                        has_inner_rings = True
                        break
            else:
                single_polygon = polygon_geom.constGet()

                # TODO: remove when the error is resolved
                if type(single_polygon) != QgsPolygon:
                    geom = QgsPolygon()
                    geom.fromWkt(polygon_geom.asWkt())
                    single_polygon = geom

                if single_polygon.numInteriorRings() > 0:
                    has_inner_rings = True

            if has_inner_rings:

                if is_multipart and multi_polygon:
                    for i in range(multi_polygon.numGeometries()):
                        temp_polygon = multi_polygon.geometryN(i)

                        # TODO: remove when the error is resolved
                        if type(temp_polygon) != QgsPolygon:
                            geom = QgsPolygon()
                            geom.fromWkt(temp_polygon.asWkt())
                            temp_polygon = geom

                        for j in range(temp_polygon.numInteriorRings()):
                            new_feature = QgsVectorLayerUtils().createFeature(
                                layer,
                                QgsGeometry(
                                    temp_polygon.interiorRing(j).clone()),
                                {0: polygon[id_field]})
                            features.append(new_feature)

                elif not is_multipart and single_polygon:
                    for j in range(single_polygon.numInteriorRings()):
                        new_feature = QgsVectorLayerUtils().createFeature(
                            layer,
                            QgsGeometry(
                                single_polygon.interiorRing(j).clone()),
                            {0: polygon[id_field]})
                        features.append(new_feature)

        layer.dataProvider().addFeatures(features)
        layer.updateExtents()
        layer.reload()
        return layer
Ejemplo n.º 54
0
    def run(self):
        ret = None
        try:
            # Reset current progress
            self.progress.emit(0)

            # Initialize output vector layer for invalid point locations
            # NOTE: Must set CRS in vector layer path URI, rather than using setCrs() method;
            #       see: https://gis.stackexchange.com/a/77500
            layerCrsWkt = self.layer.crs().toWkt()
            errorLayerName = 'validation_errors'
            errorLayer = QgsVectorLayer("Point?crs=%s" % layerCrsWkt,
                                        errorLayerName, 'memory')

            # Add attribute fields to output layer
            dataProvider = errorLayer.dataProvider()
            dataProvider.addAttributes([QgsField('Reason', QVariant.String)])
            errorLayer.updateFields()

            # Iterate over each feature in the input layer
            numErrors = 0
            total = 100.0 / self.layer.featureCount(
            ) if self.layer.featureCount() > 0 else 1
            features = self.layer.getFeatures()
            for current, feature in enumerate(features, 1):
                # Check whether kill request received
                if self.killed is True:
                    break

                # Get geometry from current feature and check whether it is valid
                geom = feature.geometry()
                if not geom.isEmpty() and not geom.isGeosValid():
                    # Use shapely to get validation error reason
                    # NOTE: Cannot use the geom.validateGeometry() method here as it does not seem to work correctly
                    # NOTE: Shapely method uses the GEOSisValidReason_r method internally, see:
                    #       https://trac.osgeo.org/geos/browser/trunk/capi/geos_ts_c.cpp#L954
                    geomWkt = geom.exportToWkt()
                    shape = wkt.loads(geomWkt)
                    validationStr = validation.explain_validity(shape)

                    # Parse validation error reason to get location co-ordinates
                    matches = re.search('\[([\w\d.\-+]+)\s+([\w\d.\-+]+)\]',
                                        validationStr)
                    coordX = matches.group(1)
                    coordY = matches.group(2)

                    # Convert co-ordinates to point geometry
                    errorPoint = QgsPoint(float(coordX), float(coordY))
                    errorGeom = QgsGeometry.fromPoint(errorPoint)

                    # Create new feature from point geometry and attribute with validation error reason
                    errorFeat = QgsFeature()
                    errorFeat.setGeometry(errorGeom)
                    errorFeat.setAttributes([validationStr])
                    dataProvider.addFeatures([errorFeat])

                    # Update error count
                    numErrors += 1

                # Update current progress
                self.progress.emit(int(current * total))

            # Set return value
            if self.killed is False:
                ret = numErrors, errorLayer, errorLayerName
        except Exception, ex:
            # Propagate exception upstream
            self.error.emit(ex, traceback.format_exc())
Ejemplo n.º 55
0
    def extract_layers(self, tree):
        """Return a list of RFU layers."""

        # Create vector layers..
        l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes",
                                  "Sommet RFU", r"memory")
        l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes",
                                "Limite RFU", r"memory")

        p_vertex = l_vertex.dataProvider()
        p_edge = l_edge.dataProvider()

        # Define default style renderer..
        renderer_vertex = QgsRuleBasedRenderer(QgsMarkerSymbol())
        vertex_root_rule = renderer_vertex.rootRule()

        # Modified in v2.1 (som_nature replaced by som_typologie_nature) >>
        vertex_rules = (
            (("Borne, borne à puce, pierre, piquet, clou ou broche"),
             ("$id >= 0 AND \"som_typologie_nature\" IN ('Borne',"
              "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"),
             r"#EC0000", 2.2),
            (("Axe cours d'eau, axe fossé, haut de talus, pied de talus"),
             ("$id >= 0 AND \"som_typologie_nature\" IN ('Axe cours d\'\'eau',"
              "'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012",
             2.2), (("Angle de bâtiment, axe de mur, angle de mur, "
                     "angle de clôture, pylône et toute autre valeur"),
                    ("$id >= 0 AND \"som_typologie_nature\" NOT IN ('Borne',"
                     "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche',"
                     "'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus',"
                     "'Pied de talus')"), r"#9784EC", 2.2),
            ("Temporaire", r"$id < 0", "cyan",
             2.4), ("Point nouveau à traiter car proche d'un existant",
                    r"point_rfu_proche is not null", "#bcff03", 3))

        # >>

        for label, expression, color, size in vertex_rules:
            rule = vertex_root_rule.children()[0].clone()
            rule.setLabel(label)
            rule.setFilterExpression(expression)
            rule.symbol().setColor(QColor(color))
            rule.symbol().setSize(size)
            vertex_root_rule.appendChild(rule)

        vertex_root_rule.removeChildAt(0)
        l_vertex.setRenderer(renderer_vertex)

        renderer_edge = QgsRuleBasedRenderer(QgsLineSymbol())
        edge_root_rule = renderer_edge.rootRule()

        # Modified in v2.1 (lim_typologie_nature added) <<
        edge_rules = (("Limite privée",
                       "$id >= 0 AND \"lim_typologie_nature\" = '" +
                       lim_typo_nat_vals[0] + "'", "#0A0AFF", 0.5),
                      ("Limite naturelle",
                       "$id >= 0 AND \"lim_typologie_nature\" = '" +
                       lim_typo_nat_vals[1] + "'", "#aa876d", 0.5),
                      ("Temporaire", "$id < 0", "cyan", 1))

        # >>

        for label, expression, color, width in edge_rules:
            rule = edge_root_rule.children()[0].clone()
            rule.setLabel(label)
            rule.setFilterExpression(expression)
            rule.symbol().setColor(QColor(color))
            rule.symbol().setWidth(width)
            edge_root_rule.appendChild(rule)

        edge_root_rule.removeChildAt(0)
        l_edge.setRenderer(renderer_edge)

        # Add fields..
        p_vertex.addAttributes(vtx_atts)

        p_edge.addAttributes(edge_atts)

        # Add features from xml tree..
        # ..to vertex layer..
        fts_vertex = []
        for e in tree.findall(r"sommet"):

            ft_vertex = QgsFeature()
            ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"]))
            _id_noeud = int(e.attrib[r"id_noeud"])
            _version = int(e.attrib[r"version"])
            som_ge_createur = str(e.find(r"./som_ge_createur").text)
            som_nature = str(e.find(r"./som_nature").text)
            som_prec_rattcht = int(
                e.find(r"./som_precision_rattachement").text)
            som_coord_est = float(e.find(r"./som_coord_est").text)
            som_coord_nord = float(e.find(r"./som_coord_nord").text)
            som_repres_plane = str(e.find(r"./som_representation_plane").text)
            som_tolerance = float(e.find(r"./som_tolerance").text)
            # Field used to store the attestation_qualite value
            # when modifying a vertex ("false" or "true")
            attestation_qualite = "false"

            som_delim_pub = str(e.find(r"./som_delimitation_publique").text)
            som_typo_nature = str(e.find(r"./som_typologie_nature").text)

            ft_vertex.setAttributes([
                _id_noeud, _version, som_ge_createur, som_delim_pub,
                som_typo_nature, som_nature, som_prec_rattcht, som_coord_est,
                som_coord_nord, som_repres_plane, som_tolerance,
                attestation_qualite, NULL
            ])

            fts_vertex.append(ft_vertex)

        # ..to edge layer..
        fts_edge = []
        for e in tree.findall(r"limite"):

            ft_edge = QgsFeature()
            ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"]))
            _id_arc = int(e.attrib[r"id_arc"])
            _version = int(e.attrib[r"version"])
            lim_ge_createur = str(e.find(r"./lim_ge_createur").text)

            lim_typo_nature = str(e.find(r"./lim_typologie_nature").text)
            lim_delim_pub = str(e.find(r"./lim_delimitation_publique").text)

            ft_edge.setAttributes([
                _id_arc, _version, lim_ge_createur, lim_delim_pub,
                lim_typo_nature
            ])

            fts_edge.append(ft_edge)

        # Add features to layers..
        p_vertex.addFeatures(fts_vertex)
        p_edge.addFeatures(fts_edge)

        # Update fields..
        l_vertex.updateFields()
        l_edge.updateFields()

        # Update layer's extent..
        l_vertex.updateExtents()
        l_edge.updateExtents()

        # Check if valid..
        if not l_vertex.isValid() or not l_edge.isValid():
            raise Exception(
                "Une erreur est survenue lors du chargement de la couche.")

        # Then return layers..
        return [l_vertex, l_edge]
Ejemplo n.º 56
0
 def mgmtSEC(self):
   # Iterate through species and gear
   result = []
   for sp in self.species:
     for g in self.gear[sp]:
       gear_shp = os.path.join(self.gearFolder, "{0}.shp".format(g))
       mgmt_shp = self.mgmtShp
       mgmtSEC_shp = os.path.join(self.exposureFolder, "{0}_{1}_current_status_of_management.shp".format(sp, g))
       fixgear_params = { 'INPUT' : gear_shp,
                          'OUTPUT' : 'memory:' }
       dissgear_params = { 'FIELD' : ['Rating'],
                           'OUTPUT' : 'memory:' }
       fixmgmt_params = { 'INPUT' : mgmt_shp,
                          'OUTPUT' : 'memory:' }  
       dissmgmt_params = { 'FIELD' : ['Rating'],
                           'OUTPUT' : 'memory:' }      
       union_params = { 'OUTPUT' : 'memory:' }
       clip_params = { 'OUTPUT' : mgmtSEC_shp }
       # Union gear with management shapefile, calculate rating, then clip to gear
       try:
         fixed_gear = processing.run('qgis:fixgeometries', fixgear_params)
         dissgear_params['INPUT'] = fixed_gear['OUTPUT']
         dissolved_gear = processing.run('qgis:dissolve', dissgear_params)
         union_params['INPUT'] = dissolved_gear['OUTPUT']
         clip_params['OVERLAY'] = dissolved_gear['OUTPUT']
         
         fixed_mgmt = processing.run('qgis:fixgeometries', fixmgmt_params)
         dissmgmt_params['INPUT'] = fixed_mgmt['OUTPUT']
         dissolved_mgmt = processing.run('qgis:dissolve', dissmgmt_params)
         union_params['OVERLAY'] = dissolved_mgmt['OUTPUT']
         
         mgmt_gear_union = processing.run('qgis:union', union_params)
         clip_params['INPUT'] = mgmt_gear_union['OUTPUT']
         processing.run('qgis:clip', clip_params)
         
         # Load the unioned shapefile and add a new field for the rating
         mgmtSEC_lyr = QgsVectorLayer(mgmtSEC_shp)
         mgmtSEC_lyr.dataProvider().addAttributes([QgsField('TMP', QVariant.Int)])
         mgmtSEC_lyr.updateFields()
         # Get index of "TMP" field
         tmp_fld = mgmtSEC_lyr.fields().indexFromName('TMP')
         # New rating is based on mgmt ratings. Anything outside ('Rating_2' is null) gets a 3.
         for f in mgmtSEC_lyr.getFeatures():
           new_rating = f['RATING_2']
           if not type(new_rating) is int:
             new_rating = 3
           mgmtSEC_lyr.dataProvider().changeAttributeValues({f.id(): {tmp_fld: new_rating}})
         # Delete old fields, create a new RATING based on TMP
         # Get index of "Rating", "Rating_2" fields
         delete_flds = [mgmtSEC_lyr.fields().indexFromName(f) for f in ['Rating', 'Rating_2']]
         mgmtSEC_lyr.dataProvider().deleteAttributes(delete_flds)
         mgmtSEC_lyr.dataProvider().addAttributes([QgsField('RATING', QVariant.Int)])
         mgmtSEC_lyr.updateFields()
         # Get index of new "RATING" field
         rating_fld = mgmtSEC_lyr.fields().indexFromName('RATING')
         for f in mgmtSEC_lyr.getFeatures():
           new_rating = f['TMP']
           mgmtSEC_lyr.dataProvider().changeAttributeValues({f.id(): {rating_fld: new_rating}})
         # Delete TMP field
         tmp_fld = mgmtSEC_lyr.fields().indexFromName('TMP')
         mgmtSEC_lyr.dataProvider().deleteAttributes([tmp_fld])
         result.append((sp, g, True))
       except:
         result.append((sp, g, False))
   # Return results
   return result
   
Ejemplo n.º 57
0
class StartDuplic:
    def __init__(self, iface, layer):

        self.iface = iface

        self.layer = layer
        self.tableSchema = 'edgv'
        self.geometryColumn = 'geom'
        self.keyColumn = 'id'

    def run(self, fid=0):

        ##################################
        ###### PEGA A LAYER ATIVA ########
        ##################################

        parametros = self.layer.source().split(
            " "
        )  # recebe todos os parametros em uma lista ( senha, porta, password etc..)

        ####################################
        ###### INICIANDO CONEXÃO DB ########
        ####################################

        # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for.
        dbname = ""
        host = ""
        port = 0
        user = ""
        password = ""

        for i in parametros:
            part = i.split("=")

            # Recebe os parametros guardados na própria Layer

            if "dbname" in part[0]:
                dbname = part[1].replace("'", "")

            elif "host" in part[0]:
                host = part[1].replace("'", "")

            elif "port" in part[0]:
                port = int(part[1].replace("'", ""))

            elif "user" in part[0]:
                user = part[1].replace("'", "")

            elif "password" in part[0]:
                password = part[1].split("|")[0].replace("'", "")

        print dbname, host, port, user, password

        # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando..
        if len(dbname) == 0 or len(host) == 0 or port == 0 or len(
                user) == 0 or len(password) == 0:
            self.iface.messageBar().pushMessage(
                "Erro",
                u'Um dos parametros não foram devidamente recebidos!',
                level=QgsMessageBar.CRITICAL,
                duration=4)
            return

    ####################################
    #### SETA VALORES DE CONEXÃO DB ####
    ####################################

        connection = QSqlDatabase.addDatabase('QPSQL')
        connection.setHostName(host)
        connection.setPort(port)
        connection.setUserName(user)
        connection.setPassword(password)
        connection.setDatabaseName(dbname)

        if not connection.isOpen(
        ):  # Testa se a conexão esta recebendo os parametros adequadamente.
            if not connection.open():
                print 'Error connecting to database!'
                self.iface.messageBar().pushMessage(
                    "Erro",
                    u'Error connecting to database!',
                    level=QgsMessageBar.CRITICAL,
                    duration=4)
                print connection.lastError().text()
                return

    ####################################
    ###### CRIAÇÃO DE MEMORY LAYER #####
    ####################################

        layerCrs = self.layer.crs().authid()  # Passa o formato (epsg: numeros)

        flagsLayerName = self.layer.name() + "_flags"
        flagsLayerExists = False

        for l in QgsMapLayerRegistry.instance().mapLayers().values(
        ):  # Recebe todas as camadas que estão abertas
            if l.name() == flagsLayerName:  # ao encontrar o nome pretendido..
                self.flagsLayer = l  # flagslayer vai receber o nome..
                self.flagsLayerProvider = l.dataProvider()
                flagsLayerExists = True  # se encontrado os parametros buscados, recebe True.
                break

        if flagsLayerExists == False:  # se não encontrado os parametros buscados, recebe False.
            tempString = "Point?crs="
            tempString += str(layerCrs)

            self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName,
                                             "memory")
            self.flagsLayerProvider = self.flagsLayer.dataProvider()
            self.flagsLayerProvider.addAttributes([
                QgsField("flagId", QVariant.String),
                QgsField("geomId", QVariant.String),
                QgsField("motivo", QVariant.String)
            ])
            self.flagsLayer.updateFields()

        if fid == 0:  # Se tiver iniciando limpa, caso não, mantém.
            self.flagsLayer.startEditing()
            ids = [feat.id() for feat in self.flagsLayer.getFeatures()]
            self.flagsLayer.deleteFeatures(ids)
            self.flagsLayer.commitChanges()

        lista_fid = []  # Iniciando lista.
        for f in self.layer.getFeatures():
            lista_fid.append(
                str(f.id())
            )  # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str".

        source = self.layer.source().split(" ")
        self.tableName = ""  # Inicia vazio.
        layerExistsInDB = False

        for i in source:

            if "table=" in i or "layername=" in i:  # Se encontrar os atributos pretendidos dentre todos do for
                self.tableName = source[source.index(i)].split(".")[
                    1]  # Faz split em ponto e pega a segunda parte.
                self.tableName = self.tableName.replace('"', '')
                layerExistsInDB = True
                break

        if layerExistsInDB == False:
            self.iface.messageBar().pushMessage(
                "Erro",
                u"Provedor da camada corrente não provem do banco de dados!",
                level=QgsMessageBar.CRITICAL,
                duration=4)
            return

        # Busca através do SQL
        sql = '''select * from (
        SELECT "{3}",
        ROW_NUMBER() OVER(PARTITION BY "{2}" ORDER BY "{3}" asc) AS Row,
        ST_AsText(geom) FROM ONLY "{0}"."{1}" 
        where {3} in ({4})
        ) dups 
        where dups.Row > 1'''.format(self.tableSchema, self.tableName,
                                     self.geometryColumn, self.keyColumn,
                                     ",".join(lista_fid))

        query = QSqlQuery(sql)

        self.flagsLayer.startEditing()
        flagCount = fid  # iniciando contador que será referência para os IDs da camada de memória.

        listaFeatures = []
        while query.next():

            id = query.value(0)
            ord = query.value(1)
            local = query.value(2)

            flagId = str(flagCount)

            flagFeat = QgsFeature()
            flagFeat.setFields(self.flagsLayer.fields()
                               )  # passa quais atributos serão usados.
            flagGeom = QgsGeometry.fromWkt(
                local)  # passa o local onde foi localizado o erro.
            flagFeat.setGeometry(flagGeom)
            flagFeat.setAttribute(
                0, flagId
            )  # insere o id definido para a coluna 0 da layer de memória.
            flagFeat.setAttribute(
                1, id
            )  # insere o id da geometria para a coluna 1 da layer de memória.
            flagFeat.setAttribute(2, u'Duplic-Geom')
            listaFeatures.append(flagFeat)

            flagCount += 1  # incrementando o contador a cada iteração.

        self.flagsLayerProvider.addFeatures(listaFeatures)
        self.flagsLayer.commitChanges()  # Aplica as alterações à camada.

        QgsMapLayerRegistry.instance().addMapLayer(
            self.flagsLayer)  # Adicione a camada no mapa.

        return flagCount
Ejemplo n.º 58
0
    def accept_dialog(self):
        input_layer = self.mMapLayerComboBox.currentLayer()
        tolerance = self.dsb_tolerance.value()

        if input_layer is None:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate("ControlledMeasurementDialog",
                                           "First select a point layer!"),
                Qgis.Warning)
            return

        if tolerance <= 0:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ControlledMeasurementDialog",
                    "Set a tolerance greater than zero!"), Qgis.Warning)
            return

        # Run model
        model = QgsApplication.processingRegistry().algorithmById(
            "model:Group_Points")
        if model:
            params = {
                'inputpoints': input_layer.name(),
                'bufferdistance': tolerance,
                'native:multiparttosingleparts_2:output': 'memory:'
            }
            res = processing.run("model:Group_Points", params)
        else:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ControlledMeasurementDialog",
                    "Model Group_Points was not found and cannot be opened!"),
                Qgis.Warning)

        # Create memory layer with average points
        groups = res['native:multiparttosingleparts_2:output']
        if not (type(groups) == QgsVectorLayer and groups.isValid()):
            return

        idx = groups.fields().indexOf(GROUP_ID)
        group_ids = groups.uniqueValues(idx)

        layer = QgsVectorLayer("Point?crs=EPSG:3116", "Average Points",
                               "memory")
        layer.dataProvider().addAttributes([
            QgsField("group_id", QVariant.Int),
            QgsField("count", QVariant.Int),
            QgsField("x_mean", QVariant.Double),
            QgsField("y_mean", QVariant.Double),
            QgsField("x_stdev", QVariant.Double),
            QgsField("y_stdev", QVariant.Double)
        ])
        layer.updateFields()
        new_features = []

        for group_id in group_ids:
            x_mean = 0
            y_mean = 0
            count = 0
            x_list = []
            y_list = []
            for feature in groups.getFeatures('"{}" = {}'.format(
                    GROUP_ID, group_id)):
                current_point = feature.geometry().asPoint()
                x_list.append(current_point.x())
                y_list.append(current_point.y())

            x_mean = statistics.mean(x_list)
            y_mean = statistics.mean(y_list)
            x_stdev = statistics.pstdev(x_list)
            y_stdev = statistics.pstdev(y_list)
            geom = QgsGeometry.fromPointXY(QgsPointXY(x_mean, y_mean))

            new_feature = QgsVectorLayerUtils.createFeature(
                layer, geom, {
                    0: group_id,
                    1: len(x_list),
                    2: x_mean,
                    3: y_mean,
                    4: x_stdev,
                    5: y_stdev
                })
            new_features.append(new_feature)

        layer.dataProvider().addFeatures(new_features)
        QgsProject.instance().addMapLayer(layer)

        self.qgis_utils.message_emitted.emit(
            QCoreApplication.translate(
                "ControlledMeasurementDialog",
                "A new average point layer has been added to the map!"),
            Qgis.Info)
Ejemplo n.º 59
0
    def processPie(self, layer, outname, startanglecol, endanglecol, distcol,
                   unitOfDist, startangle, endangle, defaultDist):
        measureFactor = self.conversionToMeters(unitOfDist)

        defaultDist *= measureFactor

        fields = layer.fields()

        polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname,
                                      "memory")
        ppolygon = polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        polygonLayer.updateFields()

        iter = layer.getFeatures()

        for feature in iter:
            try:
                pts = []
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                pts.append(pt)
                if startanglecol == -1:
                    sangle = startangle
                else:
                    sangle = float(feature[startanglecol])
                if endanglecol == -1:
                    eangle = endangle
                else:
                    eangle = float(feature[endanglecol])
                if distcol == -1:
                    dist = defaultDist
                else:
                    dist = float(feature[distcol]) * measureFactor

                sangle = sangle % 360
                eangle = eangle % 360

                if sangle > eangle:
                    # We are crossing the 0 boundry so lets just subtract
                    # 360 from it.
                    sangle -= 360.0
                while sangle < eangle:
                    g = self.geod.Direct(
                        pt.y(), pt.x(), sangle, dist,
                        Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))
                    sangle += 4  # add this number of degrees to the angle

                g = self.geod.Direct(pt.y(), pt.x(), eangle, dist,
                                     Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                pts.append(pt)

                featureout = QgsFeature()
                featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                featureout.setAttributes(feature.attributes())
                ppolygon.addFeatures([featureout])
            except:
                pass

        polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(polygonLayer)
Ejemplo n.º 60
0
class parcelHelper(object):
    def __init__(self, iface, parent=None, startFolder=""):
        self.iface = iface
        self.parent = parent
        self.canvas = iface.mapCanvas()
        self.parcellayer = None
        self.parcellayerid = ''
        self.parcelProvider = None
        self.startFolder = startFolder

    def save_parcel_polygon(self,
                            polygon,
                            parcelInfo,
                            layername="perceel",
                            saveToFile=False,
                            sender=None,
                            startFolder=None):
        attributes = [
            QgsField("niscode", QVariant.String),
            QgsField("afdeling", QVariant.String),
            QgsField("afdcode", QVariant.String),
            QgsField("sectie", QVariant.String),
            QgsField("bisnummer", QVariant.Int),
            QgsField("exponent", QVariant.String),
            QgsField("macht", QVariant.Int),
            QgsField("grondnr", QVariant.Int),
            QgsField("capakey", QVariant.String),
            QgsField("perceelnr", QVariant.String),
            QgsField("adres", QVariant.String)
        ]

        if not QgsProject.instance().mapLayer(self.parcellayerid):
            self.parcellayer = QgsVectorLayer("MultiPolygon", layername,
                                              "memory")
            self.parcelProvider = self.parcellayer.dataProvider()
            self.parcelProvider.addAttributes(attributes)
            self.parcellayer.updateFields()

        # add a feature
        fields = self.parcellayer.fields()
        fet = QgsFeature(fields)

        #set geometry and project from mapCRS
        fet.setGeometry(polygon)

        #populate fields
        fet['adres'] = ", ".join(parcelInfo['adres'])
        fet['sectie'] = parcelInfo['sectionCode']
        fet['bisnummer'] = parcelInfo['bisnummer']
        fet['exponent'] = parcelInfo['exponent']
        fet['adres'] = ", ".join(parcelInfo['adres'])
        fet['capakey'] = parcelInfo['capakey']
        fet['grondnr'] = parcelInfo['grondnummer']
        fet['NISCode'] = parcelInfo['municipalityCode']
        fet['afdeling'] = parcelInfo['departmentName']
        fet['perceelnr'] = parcelInfo['perceelnummer']
        fet['afdcode'] = parcelInfo['departmentCode']

        self.parcelProvider.addFeatures([fet])
        ""
        # update layer's extent when new features have been added
        # because change of extent in provider is not propagated to the layer
        self.parcellayer.updateExtents()

        # save memoryLAYER to file and replace all references
        if saveToFile and not QgsProject.instance().mapLayer(
                self.parcellayerid):
            save = self._saveToFile(sender, startFolder)
            if save:
                fpath, flType = save
                error, msg = QgsVectorFileWriter.writeAsVectorFormat(
                    self.parcellayer,
                    fileName=fpath,
                    fileEncoding="utf-8",
                    driverName=flType)
                if error == QgsVectorFileWriter.NoError:
                    self.parcellayer = QgsVectorLayer(fpath, layername, "ogr")
                    self.parcelProvider = self.parcellayer.dataProvider()
                else:
                    del self.parcellayer, self.parcelProvider
                    raise Exception(msg)
            else:
                del self.parcellayer, self.parcelProvider
                return

        #  add to map
        QgsProject.instance().addMapLayer(self.parcellayer)

        # store layer id and refresh
        self.parcellayerid = self.parcellayer.id()
        self.canvas.refresh()

    def _saveToFile(self, sender, startFolder=None):
        filter = "OGC GeoPackage (*.gpkg);;ESRI Shape Files (*.shp);;SpatiaLite (*.sqlite);;Geojson File (*.geojson);;GML ( *.gml);;Comma separated value File (excel) (*.csv);;MapInfo TAB (*.TAB);;Any File (*.*)"
        Fdlg = QFileDialog()
        Fdlg.setFileMode(QFileDialog.AnyFile)
        fName, __ = QFileDialog.getSaveFileName(sender,
                                                "open file",
                                                filter=filter,
                                                directory=startFolder)
        if fName:
            ext = os.path.splitext(fName)[1]
            if "GPKG" in ext.upper():
                flType = "GPKG"
            elif "SHP" in ext.upper():
                flType = "ESRI Shapefile"
            elif "SQLITE" in ext.upper():
                flType = "SQLite"
            elif "GEOJSON" in ext.upper():  #no update possible -> hidden
                flType = "GeoJSON"
            elif "GML" in ext.upper():
                flType = "GML"
            elif 'TAB' in ext.upper():
                flType = 'MapInfo File'
            elif 'CSV' in ext.upper():
                flType = 'CSV'
            else:
                fName = fName + ".shp"
                flType = "ESRI Shapefile"
            return (fName, flType)
        else:
            return None