Example #1
0
File: cow.py Project: brunky37/cow
    def drawLimits (self):
        self.dlg.listWidget.clear()
        #comprobate if the layer already exists and delete it
        for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
            if lyr.name() == "Limites":
                QgsMapLayerRegistry.instance().removeMapLayer( lyr.id() )
                break

        #crete a vector layer with a expecific name and color
        v_layer = QgsVectorLayer("LineString", "Limites", "memory")
        symbols =v_layer.rendererV2().symbols()
        symbol=symbols[0]
        symbol.setColor(QColor('magenta'))
        #create the provider and add the layer
        pr = v_layer.dataProvider()
        QgsMapLayerRegistry.instance().addMapLayers([v_layer])
        seg = QgsFeature()
        iterations=len(self.tool.polygon)
        #draw the lines between the buttons in order
        for i in range (iterations):
            if i== iterations-1:
                seg.setGeometry(QgsGeometry.fromPolyline([self.tool.polygon[i], self.tool.polygon[0]]))
            else:
                seg.setGeometry(QgsGeometry.fromPolyline([self.tool.polygon[i], self.tool.polygon[i+1]]))
            #add the lines to the provider and update the layer
            pr.addFeatures( [ seg ] )
            v_layer.updateExtents()
            v_layer.triggerRepaint()

        #add the points to the QlistWidget
        for i in range (len(self.tool.polygon)):
            self.addItem(i)
Example #2
0
File: cow.py Project: brunky37/cow
    def drawLimits2 (self):
        self.dlg.listWidget.clear()
        #comprobate if the layer already exists and delete it
        for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
            if lyr.name() == "Limites":
                QgsMapLayerRegistry.instance().removeMapLayer( lyr.id() )
                break

        #crete a vector layer with a expecific name and color
        v_layer = QgsVectorLayer("Polygon", "Limites", "memory")
        v_layer.setLayerTransparency(70)
        symbols =v_layer.rendererV2().symbols()
        symbol=symbols[0]
        symbol.setColor(QColor('green'))
        #create the provider and add the layer
        pr = v_layer.dataProvider()
        poly = QgsFeature()
        #draw the lines between the buttons in order
        points = self.tool.polygon
        #print points[0].x()
        poly.setGeometry(QgsGeometry.fromPolygon([self.tool.polygon]))
        #add the lines to the provider and update the layer
        pr.addFeatures([poly])
        v_layer.updateExtents()
        QgsMapLayerRegistry.instance().addMapLayers([v_layer])

        #add the points to the QlistWidget
        for i in range (len(self.tool.polygon)):
            self.addItem(i)
    def create_layer(self, data):
        display_name = 'some-layer'
        uri = 'Point?crs=epsg:4326&index=yes&uuid=%s' % uuid.uuid4()
        vlayer = QgsVectorLayer(uri, display_name, 'memory')
        QgsMapLayerRegistry.instance().addMapLayer(vlayer)

        provider = vlayer.dataProvider()
        vlayer.startEditing()
        provider.addAttributes([
            QgsField('population_density', QtCore.QVariant.Double),
        ])
        features = []
        for x, y, density in data:
            feat = QgsFeature()
            geom = QgsGeometry.fromPoint(QgsPoint(x, y))
            feat.setGeometry(geom)
            feat.setAttributes([density])
            features.append(feat)
        provider.addFeatures(features)
        vlayer.commitChanges()

        vlayer.updateExtents()
        self.canvas.setExtent(vlayer.extent())
        cl = QgsMapCanvasLayer(vlayer)
        self.canvas.setLayerSet([cl])
        vlayer.triggerRepaint()
    def adjlayer_make(self, name, layertype):
        if layertype == LayerType.Parliament:
            ig = self.colouring_par.id_graph
        elif layertype == LayerType.State:
            ig = self.colouring_state.id_graph
        else:
            raise Exception("Not implemented")

        vl = QgsVectorLayer("LineString?crs={}&index=yes&field=label:string&field=from:string&field=to:string"
                            .format(self.layer.dataProvider().crs().authid()),
                            "{}-{}-adj".format(name, layertype.name),
                            "memory")
        pr = vl.dataProvider()
        info = self.__box_info(layertype)
        fet = QgsFeature()
        for (f, tlist) in ig.nodeEdge.iteritems():
            for t in tlist:
                # make a feature from id=f to id=t
                centref, labelf = info[f]
                ptf = QgsPoint(centref[0], centref[1])
                centret, labelt = info[t]
                ptt = QgsPoint(centret[0], centret[1])
                lines = [ptf, ptt]
                fet.setGeometry(QgsGeometry().fromPolyline(lines))
                attributes = ["{}-{}".format(labelf, labelt), labelf, labelt]
                fet.setAttributes(attributes)
                pr.addFeatures([fet])
        vl.updateExtents()
        return vl
Example #5
0
    def test_split_by_polygon(self):
        """Test split_by_polygon work"""
        line_before = QgsVectorLayer(
            self.line_before + '.shp', 'test', 'ogr')
        expected_lines = QgsVectorLayer(
            self.line_after + '.shp', 'test', 'ogr')
        polygon_layer = QgsVectorLayer(
            self.polygon_base + '.shp', 'test', 'ogr')

        # Only one polygon is stored in the layer
        for feature in polygon_layer.getFeatures():
            polygon = feature.geometry()

        split_lines = split_by_polygon(
            line_before,
            polygon,
            mark_value=('flooded', 1))

        # Test the lines is not multipart
        for feature in split_lines.getFeatures():
            self.assertFalse(feature.geometry().isMultipart())

        self.assertEqual(expected_lines.featureCount(),
                         split_lines.featureCount())
        # Assert for every line from split_lines
        # we can find the same line
        for feature in split_lines.getFeatures():
            found = False
            for expected in expected_lines.getFeatures():
                if (feature.attributes() == expected.attributes()) and \
                   (feature.geometry().isGeosEqual(expected.geometry())):
                    found = True
                    break
            self.assertTrue(found)

        # Split by the extent (The result is the copy of the layer)
        line_before.updateExtents()
        # Expand extent to cover the lines (add epsilon to bounds)
        epsilon = 0.0001    # A small number
        extent = line_before.extent()
        new_extent = QgsRectangle(
            extent.xMinimum() - epsilon,
            extent.yMinimum() - epsilon,
            extent.xMaximum() + epsilon,
            extent.yMaximum() + epsilon
        )
        new_extent = QgsGeometry().fromRect(new_extent)
        split_lines = split_by_polygon(
            line_before,
            new_extent)
        for feature in split_lines.getFeatures():
            found = False
            for expected in line_before.getFeatures():
                if (feature.attributes() == expected.attributes()) and \
                   (feature.geometry().isGeosEqual(expected.geometry())):
                    found = True
                    break
            self.assertTrue(found)
    def get_poi(self):
        try:
            client_id = self.dlg.lineEdit_clientID.text()
            client_secret = self.dlg.lineEdit_clientSecret.text()
            radius = self.dlg.lineEdit_radius.text()
            category_name = self.dlg.comboBox_category.currentText()
            category_id = foursquare_categories[category_name]
            current_date = str(datetime.datetime.now().date()).replace("-", "")
            url = "https://api.foursquare.com/v2/venues/search?ll=%s,%s&radius=%s&intent=browse&categoryId=%s&limit=50&client_id=%s&client_secret=%s&v=%s" % (lat, lon, radius, category_id, client_id, client_secret, current_date)

            req = urllib2.Request(url)
            opener = urllib2.build_opener()
            f = opener.open(req)
            data = json.loads(f.read())

            json_object_count = len(data['response']['venues'])

            if json_object_count == 0:
                iface.messageBar().pushMessage(u"Info:", "Unfortunately, there is no POI at the specified location...",
                                               level=QgsMessageBar.INFO, duration=5)
            else:
                iface.messageBar().pushMessage(u"Info:", str(json_object_count) + " POI(s) fetched for " +
                                               category_name + " category", level=QgsMessageBar.SUCCESS, duration=5)

                poi_id = []
                poi_name = []
                poi_lon = []
                poi_lat = []

                for i in range(0, json_object_count):
                    poi_id.append(data['response']['venues'][i]['id'])
                    poi_name.append(data['response']['venues'][i]['name'])
                    poi_lon.append(data['response']['venues'][i]['location']['lng'])
                    poi_lat.append(data['response']['venues'][i]['location']['lat'])

                coord_pairs = []

                layer_name = "POI - %s" % category_name
                memory_layer = QgsVectorLayer("Point?crs=epsg:4326", layer_name, "memory")
                memory_layer.startEditing()
                provider = memory_layer.dataProvider()
                provider.addAttributes([QgsField("FoursqID", QVariant.String), QgsField("Name",  QVariant.String), QgsField("Category", QVariant.String), QgsField("Date", QVariant.String)])

                for fsid, name, x, y in zip(poi_id, poi_name, poi_lon, poi_lat):
                    geometry = QgsGeometry.fromPoint(QgsPoint(x, y))
                    feature = QgsFeature()
                    feature.setGeometry(geometry)
                    feature.setAttributes([fsid, name, category_name, current_date])
                    coord_pairs.append(feature)

                memory_layer.dataProvider().addFeatures(coord_pairs)
                memory_layer.updateExtents()
                memory_layer.commitChanges()
                QgsMapLayerRegistry.instance().addMapLayer(memory_layer)
        except:
            iface.messageBar().pushMessage(u"Error:", "Please make sure to drop a pin on Google Map or fill in all \
                                            the fields!", level=QgsMessageBar.CRITICAL, duration=5)
    def addParcelleMap(self):
        '''
        Add content in the first page
        with a map and basic information
        '''
        # First add headers
        for key, item in list(self.composerTemplates.items()):
            if 'sticky' in item:
                self.buildComposerLabel(key, item, 0)

        # Get feature extent
        exp = QgsExpression('"geo_parcelle" = \'%s\'' % self.geo_parcelle)
        request = QgsFeatureRequest(exp)
        extent = None
        features = self.layer.getFeatures(request)
        for feature in features:
            geom = feature.geometry()
            peri = geom.length()
            buf = peri / 20
            extent = geom.buffer(buf,5).boundingBox()

        # Add memory layer to highlight parcelle
        if extent:
            if self.redlineLayer:
                self.mProject.removeMapLayer(self.redlineLayer.id())
            crs = self.layer.crs().authid()
            vl = QgsVectorLayer("Polygon?crs=" + crs, "temporary", "memory")
            pr = vl.dataProvider()
            vl.startEditing()
            pr.addFeatures([f for f in self.layer.getFeatures(request)])
            vl.commitChanges()
            vl.updateExtents()
            props = vl.renderer().symbol().symbolLayer(0).properties()
            props['outline_width'] = u'1'
            props['outline_color'] = u'0,85,255,255'
            props['outline_style'] = u'solid'
            props['style'] = u'no'
            vl.renderer().setSymbol(QgsFillSymbol.createSimple(props))
            self.mProject.addMapLayer(vl)
            self.redlineLayer = vl

        # Add composer map & to parcelle
        miLayers = self.mInstance.layers()
        miLayers.insert( 0, vl )
        cm = QgsLayoutItemMap(self.currentComposition)
        cm.updateBoundingRect()
        cm.setRect(QRectF(0, 0, 286, 190))
        cm.setPos(6,15)
        cm.setLayers(self.mProject.mapThemeCollection().masterVisibleLayers())

        if extent:
            cm.zoomToExtent(extent)

        cm.setFrameEnabled(True)
        cm.setBackgroundEnabled(True)
        self.currentComposition.addItem(cm)
Example #8
0
 def load_countries(self):
     display_name = 'Population density'
     uri = DATA_DIR + 'Countries.shp'
     vlayer = QgsVectorLayer(uri, display_name, 'ogr')
     QgsMapLayerRegistry.instance().addMapLayers([vlayer])
     vlayer.updateExtents()
     self.canvas.setExtent(vlayer.extent())
     # set the map canvas layer set
     cl = QgsMapCanvasLayer(vlayer)
     self.layers.insert(0, cl)
     self.canvas.setLayerSet(self.layers)
     vlayer.triggerRepaint()
Example #9
0
    def saveSelected(self):
        gridLayer = getLayerFromId(self.GRID_LAYER)

        # create memory layer
        outputLayer = QgsVectorLayer("Polygon", "taxon", "memory")
        outProvider = outputLayer.dataProvider()

        # add features
        outGrids = gridLayer.selectedFeatures()
        for grid in outGrids:
            outProvider.addFeatures([grid])
        outputLayer.updateExtents()
        self.TAXON_GRID_LAYER = outputLayer
def pointsAlongLine(distance):
    # Create a new memory layer and add a distance attribute
    vl = QgsVectorLayer("Point", "distance nodes", "memory")
    pr = vl.dataProvider()
    pr.addAttributes( [ QgsField("distance", QVariant.Int) ] )
    layer = iface.mapCanvas().currentLayer()
    # Loop though all the selected features
    for feature in layer.selectedFeatures():
        geom = feature.geometry()
        features = createPointsAt(distance, geom)
        pr.addFeatures(features)
        vl.updateExtents()
 
    QgsMapLayerRegistry.instance().addMapLayer(vl)
Example #11
0
  def saveInMemory(self, polygons, progress):
    '''
    save output polygon as memory layer
    polygons: list of polygons created by Polygonize function
    progress: progress bar value
    '''
    global polyCount
    outFeat = QgsFeature()

    setGeometry = outFeat.setGeometry
    setAttributeMap = outFeat.setAttributeMap

    if self.ui.cbTable.isChecked():
      fields = self.parent.layer.dataProvider().fields()
    else:
      fields = {}
    polyCount = len(polygons)
    step = 50. / polyCount

    mLayer = QgsVectorLayer("Polygon", '%s_polygons' % self.ui.cmbLayer.currentText(), "memory")
    provider = mLayer.dataProvider()
    if self.ui.cbGeometry.isChecked():
      fields[len(fields)] = QgsField("area",QVariant.Double,"double",16,2)
      fields[len(fields)] = QgsField("perimeter",QVariant.Double,"double",16,2)
      nrArea = len(fields)-2
      nrPerimeter = len(fields)-1

      provider.addAttributes([fields[i] for i in range(len(fields))])
      for polygon in polygons:
        setGeometry(QgsGeometry.fromWkt(polygon.wkt))
        setAttributeMap({ nrArea:polygon.area, nrPerimeter:polygon.length })
        provider.addFeatures([outFeat])

        progress += step
        self.emit(SIGNAL('progress'), progress)
    else:
      provider.addAttributes([fields[i] for i in range(len(fields))])
      for polygon in polygons:
        setGeometry(QgsGeometry.fromWkt(polygon.wkt))
        provider.addFeatures([outFeat])

        progress += step
        self.emit(SIGNAL('progress'), progress)

    mLayer.updateExtents()
    mLayer.updateFieldMap()
    self.parent.mLayer = mLayer
    self.emit(SIGNAL('progress'), 100)
def createMemoryLayer(values):
    ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory")
    # Data as list of x, y, id, value
    assert ml.isValid()
    pr = ml.dataProvider()
    fields = pr.fields()
    for id, value in enumerate(values):
        x = id * 10.0
        feat = QgsFeature(fields)
        feat["id"] = id
        feat["value"] = value
        g = QgsGeometry.fromPoint(QgsPoint(x, x))
        feat.setGeometry(g)
        pr.addFeatures([feat])
    ml.updateExtents()
    return ml
Example #13
0
def show_clicked_point(point, name, iface, vl=None):
    """ Displays the extent from the listeOfPoints

        Keyword arguments:
            listPoints        --    list of point to draw the extent
            name              --    name of the layer to display the extent name_extent
            indexGroupProduct --    index of the product group in qgis where to move the layers
    """
    # set True to set a define color to the extent and the world
    setColor = False

    # create layer
    # if vl == None :
    vl = QgsVectorLayer("Point?crs=epsg:4326", name, "memory")
    pr = vl.data_provider()

    # add fields
    pr.addAttributes([QgsField("spectral_angle", QVariant.String)])

    # add a feature
    fet = QgsFeature()

    geometry = QgsGeometry.fromPoint(point)

    # fet.setGeometry( qgis.core.QgsGeometry.fromPolygon( qgis.core.QgsGeometry.\
    # QgsPolygon(4.45 43.95, 4.45 44.400433068, 5.000403625 44.400433068,5.000403625 43.95) ) )
    fet.setGeometry(geometry)

    # ( 4.45, 43.95 ) to (5.000403625, 44.400433068 )
    pr.addFeatures([fet])

    # set color to the extent
    if setColor:
        if vl.isUsingRendererV2():
            # new symbology - subclass of qgis.core.QgsFeatureRendererV2 class
            rendererV2 = vl.rendererV2()
            symbol = rendererV2.symbol()
            for i in xrange(symbol.symbolLayerCount()):
                symbol.symbolLayer(i).setColor(QColor(168, 255, 0))

    # update layer's extent when new features have been added
    # because change of extent in provider is not propagated to the layer
    vl.updateExtents()

    QgsMapLayerRegistry.instance().addMapLayers([vl])
    return vl
Example #14
0
 def splitSelected(self,targetArea,granulFactor,method="h",splitEven=True):
     global recurs
     recurs=0;
     layer = iface.mapCanvas().currentLayer()
     if layer:
         #Gets layer CRS for new layer
         crs=layer.crs().description()
         if self.debug: print "Starting, Layer crs: " + crs
         # Create a new memory layer and add an area attribute
         polyLayer = QgsVectorLayer("MultiPolygon?crs="+crs, "split_poly", "memory")
         polyLayer.dataProvider().addAttributes( [ QgsField("area", QVariant.Double) ] )
         #QgsMapLayerRegistry.instance().addMapLayer(polyLayer)
         allFeatures=False
         if not layer.selectedFeatures():
             layer.invertSelection();
             allFeatures=True
         #save original target area
         origTargetArea=targetArea
         # Loop though all the selected features
         for feature in layer.selectedFeatures():
             geom = feature.geometry()
             if self.debug: print "Starting Number of original geoms: ",str(len(geom.asGeometryCollection()))
             if self.debug: print "Starting Number of part to split into: ",str(geom.area()/targetArea)
             div=round(geom.area()/origTargetArea)
             if div<1:
                 div=1
             if splitEven:
                 targetArea=geom.area()/div
                 if self.debug: print "Spliteven selected. modifying target area to:", targetArea
             if div>1:
                 granularity=round(granulFactor*geom.area()/targetArea)
                 if self.debug: print "Granularity: ",granularity
                 #Figure out direction to start with from cutting method
                 #If alternating, start horizontally
                 if method=="a":
                     firstDirection="h"
                 else:
                     firstDirection=method
                 self.alternatingSlice(geom,polyLayer,targetArea,granularity,firstDirection,method)
             else:
                 self.addGeomToLayer(geom,polyLayer)
         polyLayer.updateExtents()
         #if self.debug: print recurs
         QgsMapLayerRegistry.instance().addMapLayer(polyLayer)
         if allFeatures:
             layer.invertSelection();
Example #15
0
def add_resource_as_geojson(resource, return_extent=False):
    if not isinstance(resource, NGWVectorLayer):
        raise NGWError('Resource type is not VectorLayer!')

    qgs_geojson_layer = QgsVectorLayer(resource.get_geojson_url(), resource.common.display_name, 'ogr')

    if not qgs_geojson_layer.isValid():
        raise NGWError('Layer %s can\'t be added to the map!' % resource.alias)

    qgs_geojson_layer.dataProvider().setEncoding('UTF-8')

    QgsMapLayerRegistry.instance().addMapLayer(qgs_geojson_layer)

    if return_extent:
        if qgs_geojson_layer.extent().isEmpty() and qgs_geojson_layer.type() == QgsMapLayer.VectorLayer:
            qgs_geojson_layer.updateExtents()
            return qgs_geojson_layer.extent()
Example #16
0
def spQgsVectorLayer(name):
    spatial = robjects.r.get(name)
    type = spType(spatial)
    layer = QgsVectorLayer(type, unicode(name), "memory")
    crs = QgsCoordinateReferenceSystem()
    proj = spatial.do_slot('proj4string').do_slot('projargs')[0]
    if crs.createFromProj4(proj):
        layer.setCrs(crs)
    else:
        print "Error: unable to parse proj4string: using QGIS default"
    provider = layer.dataProvider()
    fields = spFields(spatial)
    provider.addAttributes(fields)
    feats = spData(spatial)
    features = [spFeature(*feat) for feat in feats]
    provider.addFeatures(features)
    layer.updateExtents()
    return layer
    def buildLine(self, pointSelectFlag):
        print 'buildLine'
        pointLayer = processing.getObject(str(self.uPointLayer.currentText()))
        orderField = self.uOrderField.currentText()
        sortOrder = self.uOrder.currentText()
        crs = pointLayer.crs().toWkt()

        pointList = []
        if pointSelectFlag:
            pointFeatureList = pointLayer.selectedFeatures()
        else:
            pointFeatureList = pointLayer.getFeatures()        
        for pointFeature in pointFeatureList:
            pointGeom = pointFeature.geometry()
            coords = pointGeom.asPoint()
            sortField = pointFeature[orderField]
            ##store data
            pointList.append([coords, sortField])
        
        if not pointFeatureList:
            QMessageBox.warning(self,'Error',
                                        'Selected point list is empty')
            return 'Error'
        ###sort data by field
        if sortOrder=='Ascending':
            pointList = sorted(pointList, key=itemgetter(1))  
        else:
            pointList = sorted(pointList, key=itemgetter(1), reverse=True)  
        
        ## drop sort field
        pointList = list(zip(*pointList)[0])
        
        ###build line
        # create a new memory layer
        newLineLayer = QgsVectorLayer("LineString?crs="+crs, "profileFromPointsLine", "memory")
        pr = newLineLayer.dataProvider()
        feat = QgsFeature()
        geom = QgsGeometry.fromPolyline(pointList)
        feat.setGeometry(geom)
        pr.addFeatures( [ feat ] )
        
        newLineLayer.updateExtents()
        QgsMapLayerRegistry.instance().addMapLayers([newLineLayer])
        return newLineLayer
Example #18
0
    def testReadExtentOnView(self):
        # vector layer based on view
        vl0 = QgsVectorLayer(self.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POLYGON table="qgis_test"."some_poly_data_view" (geom) sql=', 'test', 'postgres')
        self.assertTrue(vl0.isValid())
        self.assertFalse(vl0.dataProvider().hasMetadata())

        # set a custom extent
        originalExtent = vl0.extent()

        customExtent = QgsRectangle(-80, 80, -70, 90)
        vl0.setExtent(customExtent)

        # write xml
        doc = QDomDocument("testdoc")
        elem = doc.createElement("maplayer")
        self.assertTrue(vl0.writeLayerXml(elem, doc, QgsReadWriteContext()))

        # read xml with the custom extent. It should not be used by default
        vl1 = QgsVectorLayer()
        vl1.readLayerXml(elem, QgsReadWriteContext())
        self.assertTrue(vl1.isValid())

        self.assertEqual(vl1.extent(), originalExtent)

        # read xml with custom extent with readExtent option. Extent read from
        # xml document should be used because we have a view
        vl2 = QgsVectorLayer()
        vl2.setReadExtentFromXml(True)
        vl2.readLayerXml(elem, QgsReadWriteContext())
        self.assertTrue(vl2.isValid())

        self.assertEqual(vl2.extent(), customExtent)

        # but a force update on extent should allow retrieveing the data
        # provider extent
        vl2.updateExtents()
        vl2.readLayerXml(elem, QgsReadWriteContext())
        self.assertEqual(vl2.extent(), customExtent)

        vl2.updateExtents(force=True)
        vl2.readLayerXml(elem, QgsReadWriteContext())
        self.assertEqual(vl2.extent(), originalExtent)
Example #19
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
    def dict2lyr(self):
        new_feats = []
        for k in self.ndict:
            cs = self.ndict[k]['attrs']
            for points in self.ndict[k]['points']:
                distance = points['distance']
                elem = QgsFeature()
                elem.setGeometry(point_geometry(points['X'], points['Y']))
                elem.setAttributes(cs + [distance])
                new_feats.append(elem)

        crs = self.layer.crs().authid()
        vl = QgsVectorLayer('Point?crs={0}'.format(crs), self.outname, 'memory')
        pr = vl.dataProvider()
        pr.addAttributes(self.flds)
        vl.startEditing()
        vl.addFeatures(new_feats)
        vl.updateExtents()
        vl.commitChanges()
        vl.removeSelection()
        return vl
 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 add_resource_as_geojson(resource, return_extent=False):
    if not isinstance(resource, NGWVectorLayer):
        raise Exception('Resource type is not VectorLayer!')

    qgs_geojson_layer = QgsVectorLayer(resource.get_absolute_geojson_url(),
                                       resource.common.display_name, 'ogr')

    if not qgs_geojson_layer.isValid():
        raise Exception('Layer %s can\'t be added to the map!' %
                        resource.common.display_name)

    qgs_geojson_layer.dataProvider().setEncoding('UTF-8')

    _add_aliases(qgs_geojson_layer, resource)

    CompatQgis.layers_registry().addMapLayer(qgs_geojson_layer)

    if return_extent:
        if qgs_geojson_layer.extent().isEmpty() and qgs_geojson_layer.type(
        ) == QgsMapLayer.VectorLayer:
            qgs_geojson_layer.updateExtents()
            return qgs_geojson_layer.extent()
 def createOutputLayer(self, resp):
     if not QgsProject.instance().mapLayersByName(
             'Identyfikacja LPIS'):
         vl = QgsVectorLayer("MultiPolygon?crs=EPSG:2180",
                             "Identyfikacja LPIS",
                             "memory")
         pr = vl.dataProvider()
         vl.startEditing()
         pr.addAttributes(
             [QgsField("id", QVariant.String),
              QgsField("objectid", QVariant.String),
              QgsField("identyfika", QVariant.String),
              QgsField("powierzchn", QVariant.String),
              QgsField("teryt", QVariant.String),
              QgsField("numer", QVariant.String),
              QgsField("obreb", QVariant.String),
              QgsField("wojewodztw", QVariant.String),
              QgsField("powiat", QVariant.String),
              QgsField("gmina", QVariant.String),
              QgsField("data_od", QVariant.String),
              QgsField("shape_leng", QVariant.String),
              QgsField("shape_area", QVariant.String)])
         vl.commitChanges()
         QgsProject.instance().addMapLayer(vl)
     vl = QgsProject.instance().mapLayersByName(
         'Identyfikacja LPIS')[0]
     pr = vl.dataProvider()
     for wkt in resp['data']:
         feature = QgsFeature()
         feature.setGeometry(QgsGeometry.fromWkt(wkt[0]))
         feature.setAttributes([a for a in wkt[1:]])
         pr.addFeatures([feature])
     vl.updateExtents()
     vl.triggerRepaint()
     self.canvas.refresh()
     self.iface.messageBar().pushMessage(
             'Identyfikacja LPIS',
             u'Znaleziono działkę',
             level=Qgis.Info)
Example #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)
Example #25
0
    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 envelope2layer(self, envelope):
        """Transform metadata envelope into a QGIS layer."""
        # layer
        md_lyr = QgsVectorLayer("Polygon?crs=epsg:4326",
                                "Metadata envelope",
                                "memory")
        md_lyr.setLayerTransparency(75)
        symbols = md_lyr.rendererV2().symbols()
        symbol = symbols[0]
        symbol.setColor(QColor.fromRgb(255,20,147))

        if envelope.get("type") == "Polygon":
            # parse coordinates
            coords = envelope.get("coordinates")[0]
            poly_pts = [QgsPoint(round(i[0], 3),
                                 round(i[1], 3))
                        for i in coords]
            # add geometry to layer
            poly = QgsFeature()
            poly.setGeometry(QgsGeometry.fromPolygon([poly_pts]))
            md_lyr.dataProvider().addFeatures([poly])
            md_lyr.updateExtents()
        elif envelope.get("type") == "MultiPolygon":
            coords = envelope.get("bbox")
            bbox = QgsRectangle(round(coords[0], 3),
                                round(coords[1], 3),
                                round(coords[2], 3),
                                round(coords[3], 3),)
            poly = QgsFeature()
            poly.setGeometry(QgsGeometry.fromWkt(bbox.asWktPolygon()))
            md_lyr.dataProvider().addFeatures([poly])
            md_lyr.updateExtents()
        elif envelope.get("type") == "Point":
            return md_lyr
        else:
            pass
        # method ending
        return md_lyr
Example #27
0
def strekning2kart(lenkeliste, lagnavn):

    egenskaper = [
        'field=vegref:string', 'veglenkesekvensid:int', 'startposisjon:double',
        'sluttposisjon:double', 'kortform:string'
    ]
    egenskapdef = '&field='.join(egenskaper)

    minelag = QgsProject.instance().mapLayersByName(lagnavn)
    if len(minelag) > 0:
        qgislag = minelag[0]
    else:
        qgislag = QgsVectorLayer(
            'Linestringz' + '?crs=epsg:25833&index=yes&' + egenskapdef,
            lagnavn, 'memory')

        QgsProject.instance().addMapLayer(qgislag)

    qgislag.startEditing()

    egenskap_liste = egenskapdef.split('&')
    for lenke in lenkeliste:

        feat = QgsFeature()
        eg = []
        for egenskap in egenskap_liste:
            mykey = egenskap[6:].split(':')[0]
            eg.append(lenke[mykey])

        feat.setAttributes(eg)

        geom = QgsGeometry.fromWkt(lenke['wkt'])
        feat.setGeometry(geom)

        qgislag.addFeature(feat)

    qgislag.updateExtents()
    qgislag.commitChanges()
Example #28
0
 def saveToLayer(self):
     units = self.unitDesignator()
     canvasCrs = self.canvas.mapSettings().destinationCrs()
     fields = QgsFields()
     fields.append(QgsField("label", QVariant.String))
     fields.append(QgsField("value", QVariant.Double))
     fields.append(QgsField("units", QVariant.String))
     fields.append(QgsField("heading_to", QVariant.Double))
     fields.append(QgsField("heading_from", QVariant.Double))
     
     layer = QgsVectorLayer("LineString?crs={}".format(canvasCrs.authid()), "Measurements", "memory")
     dp = layer.dataProvider()
     dp.addAttributes(fields)
     layer.updateFields()
     
     num = len(self.capturedPoints)
     for i in range(1,num):
         (distance, startA, endA) = self.calcParameters(self.capturedPoints[i-1], self.capturedPoints[i])
         pts = self.getLinePts(distance, self.capturedPoints[i-1], self.capturedPoints[i])
         distance = self.unitDistance(distance)
         feat = QgsFeature(layer.fields())
         feat.setAttribute(0, "{:.2f} {}".format(distance, units))
         feat.setAttribute(1, distance)
         feat.setAttribute(2, units)
         feat.setAttribute(3, startA)
         feat.setAttribute(4, endA)
         feat.setGeometry(QgsGeometry.fromPolylineXY(pts))
         dp.addFeatures([feat])
             
     label = QgsPalLayerSettings()
     label.fieldName = 'label'
     label.placement = QgsPalLayerSettings.AboveLine
     labeling = QgsVectorLayerSimpleLabeling(label)
     layer.setLabeling(labeling)
     layer.setLabelsEnabled(True)
     
     layer.updateExtents()
     QgsProject.instance().addMapLayer(layer)
    def createFinalLayer(self) -> QgsVectorLayer:
        assert self.dockWidget

        filename = self.dockWidget.getOutputLayer()
        crs = self.__getCrs(self.simplifiedSegmentsLayer)

        if os.path.isfile(filename):
            finalLayer = QgsVectorLayer(filename, self.finalLayerName, 'ogr')
        else:
            finalLayer = QgsVectorLayer('MultiLineString?crs=%s' % crs.authid(), self.finalLayerName, 'memory')
            finalLayer.dataProvider().addAttributes([QgsField('FID', QVariant.Int)])
            finalLayer.updateFields()
            finalLayer.updateExtents()

            if filename:
                (writeErrorCode, writeErrorMsg) = QgsVectorFileWriter.writeAsVectorFormat(finalLayer, filename, 'utf-8', crs, 'ESRI Shapefile')

                if writeErrorMsg:
                    show_info('[%s] %s' % (writeErrorCode, writeErrorMsg))

                finalLayer = QgsVectorLayer(filename, self.finalLayerName, 'ogr')

        return finalLayer
Example #30
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
Example #31
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
Example #32
0
def point_layer_from_coords_array(waypoints_coords_array, output_folder, crs,
                                  slope_label, points_height_data):
    """ Creating from points coordinates a points shapefile.
    """

    forest_road_points_mem_layer = QgsVectorLayer(
        'Point?crs={}'.format(crs.toWkt()), 'road_points', 'memory')

    provider = forest_road_points_mem_layer.dataProvider()
    for point in waypoints_coords_array:
        point_coord = QgsPoint(point[0], point[1])
        feature = QgsFeature()
        feature.setGeometry(QgsGeometry.fromPoint(point_coord))
        provider.addFeatures([feature])
        forest_road_points_mem_layer.updateExtents()

    road_points_mask = 'forest_road_points_{}_num_{}.shp'
    key_for_glob = os.path.join(output_folder,
                                road_points_mask.format(slope_label, '*'))

    files_list = glob.glob(key_for_glob)
    points_file_name = road_points_mask.format(slope_label,
                                               len(files_list) + 1)

    points_out_path = os.path.join(output_folder, points_file_name)

    forest_road_points_writer = QgsVectorFileWriter.writeAsVectorFormat(
        forest_road_points_mem_layer, points_out_path, "UTF-8", crs,
        "ESRI Shapefile")
    del forest_road_points_writer
    forest_road_points = QgsVectorLayer(points_out_path, points_file_name,
                                        'ogr')

    forest_road_points = layers_attributes.create_fields_for_points(
        forest_road_points, waypoints_coords_array, points_height_data)

    return forest_road_points
 def createCsvVectorLayer(dataSourceHandler, vectorLayerDescriptor, qgsVectorLayer=None):                
     ':type dataSourceHandler:GeoCsvDataSourceHandler'
     ':type vectorLayerDescriptor: CsvVectorLayerDescriptor'                     
     if not qgsVectorLayer:
         # create VectorLayer using memory provider
         _path = vectorLayerDescriptor.geometryType
         _path += '?index=yes'
         if vectorLayerDescriptor.crs:
             _path += "&crs=" + vectorLayerDescriptor.crs.toWkt()            
         qgsVectorLayer = QgsVectorLayer(_path, vectorLayerDescriptor.layerName, "memory")
     else:            
         # reset the memory layer 
         qgsVectorLayer.dataProvider().deleteFeatures(qgsVectorLayer.allFeatureIds())
         qgsVectorLayer.dataProvider().deleteAttributes(qgsVectorLayer.dataProvider().fields().allAttributesList())
                                 
     # : :type dataProvider: QgsVectorDataProvider                
     dataProvider = qgsVectorLayer.dataProvider() 
     dataProvider.addAttributes(vectorLayerDescriptor.getAttributesAsQgsFields())        
     qgsVectorLayer.updateFields()
     dataProvider.addFeatures(dataSourceHandler.createFeaturesFromCsv(vectorLayerDescriptor))                
     qgsVectorLayer.updateExtents()        
     csvVectorLayer = CsvVectorLayer(qgsVectorLayer, vectorLayerDescriptor)
     csvVectorLayer.updateGeoCsvPath(dataSourceHandler.getPathToCsvFile())                 
     return csvVectorLayer 
Example #34
0
    def combine_features(self, parm_store):
        """
        Combines all features under one layer.
        :param parm_store: The parameter store object
        :type parm_store: Class
        :return:
        :rtype:
        """
        final_layer = QgsVectorLayer(
            "{0}?crs=epsg:{1}&field=id:integer&index=yes".format(
                parm_store.geometry_type, parm_store.gpx_projection
            ),
            parm_store.layer_name,
            "memory"
        )

        feature_list = self.gpx_to_feature_list(parm_store)

        if self.layer_fields is None:
            self.progress_dlg.blockSignals(True)
            self.progress_dlg.close()
            self.progress_dlg.blockSignals(False)
            return 0
        if STOP_IMPORT:
            return
        provider = final_layer.dataProvider()

        final_layer.startEditing()
        provider.addAttributes(self.layer_fields)
        final_layer.updateFields()
        provider.addFeatures(feature_list)
        final_layer.commitChanges()

        final_layer.updateExtents()
        QgsProject.instance().addMapLayer(final_layer)
        return len(feature_list)
Example #35
0
    def createRouteFromResponse(self, response):
        """
        Build output layer based on response attributes for directions endpoint.

        :param response: API response object
        :type response: dict


        :returns: Ouput layer with a single geometry containing the route.
        :rtype: QgsVectorLayer
        """
        response_mini = response['trip']
        feat = QgsFeature()
        coordinates, distance, duration = [], 0, 0
        for leg in response_mini['legs']:
            coordinates.extend([
                list(reversed(coord))
                for coord in decodePolyline6(leg['shape'])
            ])
            duration += round(leg['summary']['time'] / 3600, 3)
            distance += round(leg['summary']['length'], 3)

        qgis_coords = [QgsPointXY(x, y) for x, y in coordinates]
        feat.setGeometry(QgsGeometry.fromPolylineXY(qgis_coords))
        feat.setAttributes([distance, duration])

        layer = QgsVectorLayer("LineString?crs=epsg:4326", "route", "memory")
        provider = layer.dataProvider()
        provider.addAttributes([
            QgsField("DIST_KM", QVariant.Double),
            QgsField("DURATION_H", QVariant.Double)
        ])
        layer.updateFields()
        provider.addFeature(feat)
        layer.updateExtents()
        return layer
Example #36
0
    def create_virtual_layer(self, virtual_layer_name):

        sql = (
            "SELECT value FROM " + self.controller.schema_name +
            ".config_param_user"
            " WHERE cur_user = current_user AND parameter = 'virtual_layer_point'"
        )
        row = self.controller.get_row(sql)
        if not row:
            sql = ("INSERT INTO " + self.schema_name +
                   ".config_param_user (parameter, value, cur_user) "
                   " VALUES ('virtual_layer_point', '" + virtual_layer_name +
                   "', current_user)")
            self.controller.execute_sql(sql)
        uri = "Point?crs=epsg:" + str(self.srid)
        virtual_layer = QgsVectorLayer(uri, virtual_layer_name, "memory")
        props = {'color': 'red', 'color_border': 'red', 'size': '1.5'}
        s = QgsMarkerSymbolV2.createSimple(props)
        virtual_layer.setRendererV2(QgsSingleSymbolRendererV2(s))
        virtual_layer.updateExtents()
        QgsProject.instance().setSnapSettingsForLayer(virtual_layer.id(), True,
                                                      0, 0, 1.0, False)
        QgsMapLayerRegistry.instance().addMapLayer(virtual_layer)
        self.iface.mapCanvas().refresh()
Example #37
0
class crea_couche(object):
     
    def __init__(self,nom,type):
        self.nom = nom
        self.type= type
        self.couche =  QgsVectorLayer(self.type, self.nom , "memory") #creation de la couche virtuelle
        self.pr = self.couche.dataProvider()                
        self.couche.startEditing()
        #ajout des attributs
        self.pr.addAttributes( [QgsField("numero", QVariant.String), QgsField("rue", QVariant.String), QgsField("code_postal", QVariant.Double),
                            QgsField("commune", QVariant.String), QgsField("latitude",  QVariant.Double), QgsField("longitude", QVariant.Double)])

    def create_point(self,point,numero,rue,code_postal,commune,latitude,longitude):
        #ajout d'un point
        self.seg = QgsFeature()
        self.seg.setGeometry(QgsGeometry.fromPoint(point)) #renseignement de la geometrie du point (lat,long)
        self.seg.setAttributes([numero,rue,code_postal,commune,latitude, longitude]) #renseignement des attributs
        self.pr.addFeatures([self.seg]) 
        self.couche.commitChanges()
        self.couche.updateExtents()
    @property
    def aff_couche(self):
        #fin de l'edition et affichage de la couche
        QgsMapLayerRegistry.instance().addMapLayers([self.couche])
Example #38
0
    def envelope2layer(self, envelope):
        """Transform metadata envelope into a QGIS layer."""
        # layer
        md_lyr = QgsVectorLayer("Polygon?crs=epsg:4326", "Metadata envelope",
                                "memory")
        md_lyr.setLayerTransparency(75)

        if envelope.get("type") == "Polygon":
            # parse coordinates
            coords = envelope.get("coordinates")[0]
            poly_pts = [
                QgsPoint(round(i[0], 3), round(i[1], 3)) for i in coords
            ]
            # add geometry to layer
            poly = QgsFeature()
            poly.setGeometry(QgsGeometry.fromPolygon([poly_pts]))
            md_lyr.dataProvider().addFeatures([poly])
            md_lyr.updateExtents()
        elif envelope.get("type") == "MultiPolygon":
            coords = envelope.get("bbox")
            bbox = QgsRectangle(
                round(coords[0], 3),
                round(coords[1], 3),
                round(coords[2], 3),
                round(coords[3], 3),
            )
            poly = QgsFeature()
            poly.setGeometry(QgsGeometry.fromWkt(bbox.asWktPolygon()))
            md_lyr.dataProvider().addFeatures([poly])
            md_lyr.updateExtents()
        elif envelope.get("type") == "Point":
            return md_lyr
        else:
            pass
        # method ending
        return md_lyr
Example #39
0
	def run(self, delegate):
		import pstalgo  # Do it here when it is needed instead of on plugin load
		props = self._props
		model = self._model

		table_name = props['in_network']
		new_table_name = table_name + "_lines"

		layer = model._layerFromName(table_name)

		copy_column = model._safeFieldIndex(layer, props['copy_column_in']) if props['copy_column_enabled'] else None

		# Generate URI
		uri = "LineString?crs=%s" % model.coordinateReferenceSystem(table_name)
		if copy_column is not None:
			uri += "&field=%s:%s" % (props['copy_column_out'], model.columnType(table_name, props['copy_column_in']))
		new_layer = QgsVectorLayer(uri, table_name + "_lines", "memory")

		delegate.setStatus("Splitting polylines '%s' -> '%s'" % (table_name, new_table_name))

		BATCH_SIZE = 4096
		features = [None]*BATCH_SIZE
		dp = new_layer.dataProvider()
		n = 0
		for feature in LinesAndValueFeatures(layer, copy_column, delegate):
			features[n] = feature
			n += 1
			if n == BATCH_SIZE:
				dp.addFeatures(features)
				n = 0
		if n > 0:
			dp.addFeatures(features[:n])

		new_layer.updateExtents()

		QgsProject.instance().addMapLayer(new_layer)
    def show_grid(self):
        try:
            point_interval = self.dlg.lineEdit_interval.text()
            if ',' in point_interval:
                iface.messageBar().pushMessage(
                    u"Warning: ",
                    "Please use point (.) as separator",
                    level=QgsMessageBar.WARNING,
                    duration=3)
            else:
                start_time = time.time()

                latlist = list(
                    arange(sw_lat['0'], ne_lat['0'], float(point_interval)))
                lnglist = list(
                    arange(sw_lng['0'], ne_lng['0'], float(point_interval)))

                msgBox = QMessageBox()
                msgBox.setWindowTitle('Info')
                message = "%s points will be generated. Continue?" % str(
                    len(list(itertools.product(latlist, lnglist))))
                msgBox.setText(message)
                msgBox.setInformativeText(
                    "Zomato API daily limit is up to 1000 calls.")
                msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                pop = msgBox.exec_()

                if pop == QMessageBox.Yes:
                    directory = QFileDialog.getExistingDirectory(
                        None, "Select folder to save shapefile...")
                    shp_dir = directory.replace("\\", "/")

                    if len(directory) > 1:
                        current_date = str(
                            datetime.datetime.now().date()).replace("-", "")
                        layer_name = 'grid_' + current_date
                        coord_pairs = []
                        memory_layer = QgsVectorLayer("Point?crs=epsg:4326",
                                                      layer_name, "memory")
                        memory_layer.startEditing()
                        provider = memory_layer.dataProvider()
                        provider.addAttributes(
                            [QgsField("NLINDEX", QVariant.Double)])

                        for i in itertools.product(latlist, lnglist):
                            api_key = self.dlg.lineEdit_apikey.text()
                            url = "https://developers.zomato.com/api/v2.1/geocode?lat=%f&lon=%f" % (
                                i[0], i[1])
                            headers = {
                                "User-agent": "curl/7.43.0",
                                "user_key": api_key,
                                "Accept": "application/json"
                            }
                            req = urllib2.Request(url, None, headers)
                            response = urllib2.urlopen(req)
                            data = json.load(response)
                            nightlife_index = data['popularity'][
                                'nightlife_index']

                            geometry = QgsGeometry.fromPoint(
                                QgsPoint(i[1], i[0]))
                            feature = QgsFeature()
                            feature.setGeometry(geometry)
                            feature.setAttributes([nightlife_index])
                            coord_pairs.append(feature)

                        memory_layer.dataProvider().addFeatures(coord_pairs)
                        memory_layer.updateExtents()
                        memory_layer.commitChanges()
                        QgsMapLayerRegistry.instance().addMapLayer(
                            memory_layer)

                        shp_path = shp_dir + "/" + layer_name
                        QgsVectorFileWriter.writeAsVectorFormat(
                            memory_layer, shp_path, "utf-8", None,
                            "ESRI Shapefile")

                        end_time = time.time()
                        time_difference = end_time - start_time
                        time_difference_rounded = "%.2f" % time_difference

                        iface.messageBar().pushMessage(
                            u"Info: ",
                            str(time_difference_rounded) +
                            " seconds have elapsed for " +
                            str(len(list(itertools.product(
                                latlist, lnglist)))) + " points.",
                            level=QgsMessageBar.SUCCESS,
                            duration=5)
                    else:
                        iface.messageBar().pushMessage(
                            u"Warning: ",
                            u"Folder is not selected...",
                            level=QgsMessageBar.WARNING,
                            duration=5)
                else:
                    pass
        except:
            iface.messageBar().pushMessage(
                u"Error: ",
                u"Check your API key and/or point interval value!",
                level=QgsMessageBar.CRITICAL,
                duration=5)
    def run(self):
        """Run the impact function."""
        # First fo any generic run work defined in the ABC.
        self.prepare()

        target_field = self.parameters['target_field']
        building_type_field = self.parameters['building_type_field']
        affected_value = self.parameters['affected_value']

        crs = self.exposure.crs().toWkt()
        exposure_provider = self.exposure.dataProvider()
        fields = exposure_provider.fields()
        # If target_field does not exist, add it:
        if fields.indexFromName(target_field) == -1:
            exposure_provider.addAttributes(
                [QgsField(target_field, QVariant.Int)])
        target_field_index = exposure_provider.fieldNameIndex(target_field)
        fields = exposure_provider.fields()

        # Create layer for store the lines from exposure and extent
        building_layer = QgsVectorLayer(
            'Polygon?crs=' + crs, 'impact_buildings', 'memory')
        building_provider = building_layer.dataProvider()

        # Set attributes
        building_provider.addAttributes(fields.toList())
        building_layer.startEditing()
        building_layer.commitChanges()

        # Filter geometry and data using the extent
        extent = QgsRectangle(*self.extent)
        request = QgsFeatureRequest()
        request.setFilterRect(extent)

        # Split building_layer by hazard and save as result:
        #   1) Filter from hazard inundated features
        #   2) Mark buildings as inundated (1) or not inundated (0)

        affected_field_type = self.hazard_provider.fields()[
            self.affected_field_index].typeName()
        if affected_field_type in ['Real', 'Integer']:
            affected_value = float(affected_value)

        hazard_data = self.hazard.getFeatures(request)
        hazard_poly = None
        for multi_polygon in hazard_data:
            attributes = multi_polygon.attributes()
            if attributes[self.affected_field_index] != affected_value:
                continue
            if hazard_poly is None:
                hazard_poly = QgsGeometry(multi_polygon.geometry())
            else:
                # Make geometry union of inundated polygons
                # But some multi_polygon.geometry() could be invalid, skip them
                tmp_geometry = hazard_poly.combine(multi_polygon.geometry())
                try:
                    if tmp_geometry.isGeosValid():
                        hazard_poly = tmp_geometry
                except AttributeError:
                    pass

        if hazard_poly is None:
            message = tr(
                '''There are no objects in the hazard layer with "Affected
                value"='%s'. Please check the value or use other extent.''' %
                (affected_value, ))
            raise GetDataError(message)

        exposure_features = self.exposure.getFeatures(request)
        for feature in exposure_features:
            building_geometry = feature.geometry()
            attributes = feature.attributes()
            l_feat = QgsFeature()
            l_feat.setGeometry(building_geometry)
            l_feat.setAttributes(attributes)
            if hazard_poly.intersects(building_geometry):
                l_feat.setAttribute(target_field_index, 1)
            else:

                l_feat.setAttribute(target_field_index, 0)
            # Synctactic sugar to discard return values
            (_, __) = building_layer.dataProvider().addFeatures([l_feat])
        building_layer.updateExtents()

        # Generate simple impact report

        building_count = flooded_count = 0  # Count of buildings
        buildings_by_type = dict()      # Length of flooded roads by types

        buildings_data = building_layer.getFeatures()
        building_type_field_index = building_layer.fieldNameIndex(
            building_type_field)
        for building in buildings_data:
            building_count += 1
            attributes = building.attributes()
            building_type = attributes[building_type_field_index]
            if building_type in [None, 'NULL', 'null', 'Null']:
                building_type = 'Unknown type'
            if not building_type in buildings_by_type:
                buildings_by_type[building_type] = {'flooded': 0, 'total': 0}
            buildings_by_type[building_type]['total'] += 1

            if attributes[target_field_index] == 1:
                flooded_count += 1
                buildings_by_type[building_type]['flooded'] += 1

        self._tabulate(building_count, buildings_by_type, flooded_count)

        self._style(target_field)

        self._impact = building_layer
Example #42
0
class QueryBuilderWidget(QtWidgets.QDockWidget):
    closingWidget = pyqtSignal()

    def __init__(self, parent=None, iface=None):

        super(QueryBuilderWidget, self).__init__(parent)
        self.iface = iface

        self._polygons = QgsVectorLayer(
            "polygon?crs={0}&field=name:string(20)".format(28992),
            "building",
            "memory")

        self._points = QgsVectorLayer(
            "point?crs={0}&field=ahn:double".format(28992),
            "point",
            "memory")

        QgsProject.instance().addMapLayer(
            self._polygons,
            False)

        QgsProject.instance().addMapLayer(
            self._points,
            False)

        root = QgsProject.instance().layerTreeRoot()
        group = root.addGroup('GeoGraphQL')
        group.addLayer(self._points)
        group.addLayer(self._polygons)

        self.setup_ui()

        self.api = PythonAPI(self.on_new_data)
        self.frame = self.web_view.page().mainFrame()
        self.frame.javaScriptWindowObjectCleared.connect(self.load_api)

        QNetworkProxyFactory.setUseSystemConfiguration(True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.DnsPrefetchEnabled, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.JavascriptEnabled, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.JavascriptCanOpenWindows, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.OfflineStorageDatabaseEnabled, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.AutoLoadImages, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.LocalStorageEnabled, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.PrivateBrowsingEnabled, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
        QWebSettings.globalSettings().setAttribute(QWebSettings.LocalContentCanAccessRemoteUrls, True)
        # url = "https://gateway.geographql.com/"
        url = 'http://localhost:4005/console'
        # url = 'http://localhost:3000/'
        url = QUrl(url)

        file_path = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'build', 'index.html')

        url = QUrl.fromLocalFile(file_path)

        self.web_view.load(url)

    def on_unload(self):
        self.frame.javaScriptWindowObjectCleared.disconnect(self.load_api)

    def load_api(self):
        print('load_api')
        self.frame.addToJavaScriptWindowObject('pyapi', self.api)

    def add_point(self, feature):
        self._points.dataProvider().addFeatures([feature])
        self._points.updateExtents()

    def add_polygon(self, feature):
        self._polygons.dataProvider().addFeatures([feature])
        self._polygons.updateExtents()

    def make_feature_recursive(self, key, value):

        if value.get("__typename"):


            if value.get("__typename") == "Point" and value.get('x') is not None and value.get('y') is not None:
                feat = QgsFeature(self._points.fields())
                geom = QgsGeometry.fromPointXY(QgsPointXY(value.get('x'), value.get('y')))
                feat.setGeometry(geom)
                feat.setAttribute('ahn', value.get('ahn'))
                self.add_point(feat)
            elif value.get("__typename") == "Building" and type(value.get('geom') == dict):
                feat = QgsFeature(self._polygons.fields())
                geom = QgsGeometry.fromWkt(value.get('geom'))
                feat.setGeometry(geom)
                feat.setAttribute('name', value.get('name'))
                self.add_polygon(feat)

        for k, v in value.items():

            if type(v) == list:
                for list_v in v:
                    if type(list_v) == dict:
                        self.make_feature_recursive("{}-{}".format(key, k), list_v)
            elif type(v) == dict:
                self.make_feature_recursive("{}-{}".format(key, k), v)

    def on_new_data(self, obj):
        print(obj)
        if 'data' in obj:
            for key, value in obj['data'].items():
                if type(value) == dict:
                    self.make_feature_recursive(key, value)

        extent = self._points.extent()
        extent.combineExtentWith(self._polygons.extent())
        extent.scale(1.1)

        canvas = self.iface.mapCanvas()
        canvas.setExtent(extent)
        canvas.refresh()


    def setup_ui(self):

        self.dock_widget_content = QtWidgets.QWidget(self)
        self.setObjectName("graphqlDockWidget")
        self.dock_widget_content.setObjectName("graphqlMainWidget")

        self.main_vlayout =  QtWidgets.QVBoxLayout(self.dock_widget_content)
        self.dock_widget_content.setLayout(self.main_vlayout)

        #self.web_view = QtWebEngineWidgets.QWebEngineView(self.dock_widget_content)
        self.web_view = QtWebKitWidgets.QWebView(self.dock_widget_content)
        self.main_vlayout.addWidget(self.web_view)

        self.button_bar = QtWidgets.QHBoxLayout(self.dock_widget_content)
        self.load_button = QtWidgets.QPushButton(self.dock_widget_content)
        self.refresh_button = QtWidgets.QPushButton(self.dock_widget_content)
        spacer = QtWidgets.QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.button_bar.addWidget(self.load_button)
        self.button_bar.addSpacerItem(spacer)
        self.button_bar.addWidget(self.refresh_button)

        self.main_vlayout.addLayout(self.button_bar)

        self.setWidget(self.dock_widget_content)

        self.setWindowTitle("GeoGraphQL")
        self.load_button.setText("Laad data")

        self.refresh_button.setText("Refresh")
    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()
def addRowInLayer(row, errTable, table_codif):
    """
    Rows will be converted in a geometry thanks to codification.
    All attributes will be added thanks to QgsExpressionContext.

    Parameters
    ----------
    row: list of list
        A row contains one or many list of points.
    errTable: list of list
        Contains points in error.
        Some points can be added after the end of this function.
    table_codif: dictionnary
        The codification file. See the information about qlsc format.
    """

    #  TODO: assert?
    code = row[CODE_POSITION][0]
    parameters = row[PARAM_POSITION]

    codif = table_codif['Codification'][code]
    layerName = codif['Layer']

    layer = QgsVectorLayer(layerName)

    dim = 4 if QgsWkbTypes.hasZ(layer.dataProvider().wkbType()) else 3
    geom = geomFromType(list(zip(*row[1:dim])), parameters,
                        codif['GeometryType'], layer.geometryType())

    if geom:
        layer.startEditing()

        fields = layer.fields()
        newFeature = QgsFeature(fields)

        newFeature.setGeometry(geom)

        for e in codif['Attributes']:
            # print(e, e[1], e[1].startswith('_att'))
            if e[1].startswith('_att'):
                # len('_att') == 4
                try:
                    nb = int(e[1][4:]) - 1
                    assert(nb >= 0)
                    val = row[ATTRS_POSITION + nb][0]
                    newFeature[e[0]] = val
                except:
                    # print("attributes error")
                    pass
            else:
                context = QgsExpressionContext()
                scope = QgsExpressionContextScope()
                try:
                    exp = QgsExpression(e[1])
                    scope.setFeature(newFeature)
                    context.appendScope(scope)
                    newFeature[e[0]] = exp.evaluate(context)
                except:
                    # print('key error')
                    pass

        ret = layer.addFeature(newFeature)
        # if not ret:
         #   print(ret)

        layer.commitChanges()
        layer.updateExtents()
    else:
        # can it happen?
        errTable.append(row)
Example #45
0
def addDiffLayer(repo, layername, commit):
    
    styles = [diffStylePoints, diffStyleLines, diffStylePolygons]
    geomTypes = ["Point","LineString","Polygon"]
    beforeFilename = tempFilename("gpkg")
    repo.exportdiff(layername, commit.commitid, commit.parent.commitid, beforeFilename)
    beforeLayer = loadLayerNoCrsDialog(beforeFilename, layername, "ogr")
    afterFilename = tempFilename("gpkg")
    repo.exportdiff(layername, commit.parent.commitid, commit.commitid, afterFilename)
    afterLayer = loadLayerNoCrsDialog(afterFilename, layername, "ogr")

    beforeCon = sqlite3.connect(beforeFilename)
    beforeCursor = beforeCon.cursor()
    afterCon = sqlite3.connect(afterFilename)
    afterCursor = afterCon.cursor()

    attributes = [v[1] for v in beforeCursor.execute("PRAGMA table_info('%s');" % layername)]
    attrnames = [f.name() for f in beforeLayer.pendingFields()]

    layerFeatures = []

    beforeCursor.execute("SELECT * FROM %s_changes WHERE audit_op=2;" % layername)
    modified = beforeCursor.fetchall()
    for m in modified:
        geogigfid = m[0]
        beforeGpkgfid = gpkgfidFromGeogigfid(beforeCursor, layername, geogigfid)
        beforeCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, beforeGpkgfid))
        featureRow = beforeCursor.fetchone()
        attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames}
        attrs["changetype"] = MODIFIED_BEFORE
        request = QgsFeatureRequest()
        request.setFilterFid(beforeGpkgfid)
        feature = next(beforeLayer.getFeatures(request))
        layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())})
        afterGpkgfid = gpkgfidFromGeogigfid(afterCursor, layername, geogigfid)
        afterCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername,afterGpkgfid))
        featureRow = afterCursor.fetchone()
        attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames}
        attrs["changetype"] = MODIFIED_AFTER
        request = QgsFeatureRequest()
        request.setFilterFid(beforeGpkgfid)
        feature = next(afterLayer.getFeatures(request))
        layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())})


    afterCursor.execute("SELECT * FROM %s_changes WHERE audit_op=1;" % layername)
    added = afterCursor.fetchall()
    for a in added:
        geogigfid = a[0]
        afterGpkgfid = gpkgfidFromGeogigfid(afterCursor, layername, geogigfid)
        afterCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, afterGpkgfid))
        featureRow = afterCursor.fetchone()
        attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames}
        attrs["changetype"] = ADDED
        request = QgsFeatureRequest()
        request.setFilterFid(afterGpkgfid)
        feature = next(afterLayer.getFeatures(request))
        layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())})

    beforeCursor.execute("SELECT * FROM %s_changes WHERE audit_op=1;" % layername)
    removed = beforeCursor.fetchall()
    for r in removed:
        geogigfid = r[0]
        beforeGpkgfid = gpkgfidFromGeogigfid(beforeCursor, layername, geogigfid)
        beforeCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, beforeGpkgfid))
        featureRow = beforeCursor.fetchone()
        attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames}
        attrs["changetype"] = REMOVED
        request = QgsFeatureRequest()
        request.setFilterFid(beforeGpkgfid)
        feature = next(beforeLayer.getFeatures(request))
        layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())})

    attrnames.append("changetype")
    uriFields = "&".join(["field=%s" % f for f in attrnames])
    uri = "%s?crs=%s&%s" % (geomTypes[beforeLayer.geometryType()], beforeLayer.crs().authid(), uriFields)
    layer = QgsVectorLayer(uri, "diff", "memory")
    featuresList = []
    for feature in layerFeatures:
        qgsfeature = QgsFeature()
        qgsfeature.setGeometry(feature["geom"])
        qgsfeature.setAttributes([feature["attrs"][attr] for attr in attrnames])
        featuresList.append(qgsfeature)

    layer.dataProvider().addFeatures(featuresList)
    layer.updateExtents()
    QgsMapLayerRegistry.instance().addMapLayers([layer])
    layer.loadNamedStyle(styles[layer.geometryType()])
Example #46
0
    def on_btnRun_clicked(self):
                
        if self.inputfile == '':
            QMessageBox.critical(self,'Map Creator',
                                 'Please specify input coordinate file.')
            return
        
        if self.outputfile == '':
            QMessageBox.critical(self,'Map Creator',
                                 'Please specify output shapefile.')
            return
        
        self.setCursor(Qt.WaitCursor)

        #Open coordinate input file
        f = open(self.inputfile, 'r')
        lines = f.readlines()
        f.close()
        header = lines[0].split(',')[0]
        totfeat = len(lines) - 1
        lines.pop(0)
        lines.reverse() 
        
        #Create vector layer
        basename = os.path.basename(self.outputfile)
        vlayer = QgsVectorLayer("Polygon", basename, "memory")
        vprovider = vlayer.dataProvider()
        fld = QgsField(header,QVariant.String)
        flds = QgsFields()
        flds.append(fld)
        vprovider.addAttributes([fld])
        vlayer.startEditing()
                
        hull = []
        for cnt, line in enumerate(lines):
            line = line.rstrip().split(',')
            numcoords = int((len(line) - 1) / 2)
            hull[:] = []
            geom = QgsGeometry()
            feat = QgsFeature()
            feat.setFields(flds)
            for i in range(numcoords):
                hull.append(QgsPoint(float(line[i*2+1]),float(line[i*2+2])))
            geom = geom.fromMultiPoint(hull)
            geom = geom.convexHull()
            feat.setGeometry(geom)
            feat.setAttribute(header,str(line[0]))
            result = vlayer.addFeature(feat)
            if not result:
                self.setCursor(Qt.ArrowCursor)
                QMessageBox.critical(self,'Map Creator', 'Processing error.')
                return
            self.ui.ProgressBar.setValue(float(cnt+1)/float(totfeat) * 100.0)
            QApplication.processEvents()  
        vlayer.commitChanges()
        vlayer.updateExtents()
        
        #Write the output shapefile
        if os.path.exists(self.outputfile):
            QgsVectorFileWriter.deleteShapeFile(self.outputfile)
        result = QgsVectorFileWriter.writeAsVectorFormat(vlayer, 
                                                         self.outputfile, 
                                                         'utf-8', 
                                                         vlayer.crs())
                
        if result != QgsVectorFileWriter.NoError:
            QMessageBox.critical(self,'Map Creator','Error creating shapefile.')
        else: #Ask to add shapfile to map
            name = QFileInfo(self.outputfile).completeBaseName()
            result = QMessageBox.question(self,'Map Creator',
                                          'Add shapefile to map?',
                                          QMessageBox.Yes,
                                          QMessageBox.No)
            if result == QMessageBox.Yes:
                self.iface.addVectorLayer(self.outputfile, name, 'ogr')
                
        self.setCursor(Qt.ArrowCursor)
Example #47
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()
Example #48
0
def generateIsochrones(point,
                       profile,
                       costingOptions,
                       intervals,
                       colors,
                       basename,
                       overwrite=True):
    response = valhalla.isochrones(point, profile, costingOptions, intervals,
                                   colors)
    features = getFeaturesFromResponse(response)
    if costingOptions.get("shortest"):
        suffix = "km"
    else:
        suffix = "min"
    for interval, feature in zip(intervals[::-1], features):
        # FIXME: we should use the 'contour' property in the feature to be sure of the contour line that we are
        # drawing, but due to a bug in qgis json parser, this property appears to be always set to '0'
        layername = "{} {} - {}".format(interval, suffix, basename)
        try:
            # FIXME: we do not consider if there are several layers with the same name here
            existinglayer = QgsProject.instance().mapLayersByName(layername)[0]
            if overwrite:
                QgsProject.instance().removeMapLayer(existinglayer.id())
            else:
                raise OverwriteError(
                    tr("layer {layername} already exists and overwrite is {overwrite}"
                       ).format(layername=layername, overwrite=overwrite))
        except IndexError:
            LOG.debug("this layer was not found: {}".format(layername))

        layer = QgsVectorLayer(
            "Polygon?crs=epsg:4326&field=centerx:double&field=centery:double&field=interval:double",
            layername,
            "memory",
        )
        pr = layer.dataProvider()
        qgsfeature = QgsFeature()
        qgsfeature.setAttributes([point.x(), point.y(), interval])
        qgsfeature.setGeometry(feature.geometry())
        pr.addFeatures([qgsfeature])
        layer.updateExtents()
        QgsProject.instance().addMapLayer(layer)
        outlineColor = QColor(0, 0, 0)
        # Set opacity to 40% or 66 in hex (65% transparency)
        fillColor = QColor("#66" + feature["color"][1:])
        renderer = QgsSingleSymbolRenderer.defaultRenderer(
            QgsWkbTypes.PolygonGeometry)
        symbol = renderer.symbol()
        symbol.setColor(fillColor)
        symbol.symbolLayer(0).setStrokeColor(outlineColor)
        layer.setRenderer(renderer)

    # Add center of reachability
    center_point_layer_name = tr("Center of {basename}").format(
        basename=basename)
    try:
        existinglayer = QgsProject.instance().mapLayersByName(
            center_point_layer_name)[0]
        if overwrite:
            QgsProject.instance().removeMapLayer(existinglayer.id())
        else:
            raise OverwriteError(
                tr("layer {layername} already exists and overwrite is {overwrite}"
                   ).format(layername=center_point_layer_name,
                            overwrite=overwrite))
    except IndexError:
        LOG.debug(
            "this layer was not found: {}".format(center_point_layer_name))

    center_point = QgsVectorLayer(
        "Point?crs=epsg:4326",
        center_point_layer_name,
        "memory",
    )
    pr = center_point.dataProvider()
    qgsfeature = QgsFeature()
    qgsfeature.setGeometry(QgsGeometry.fromPointXY(point))
    pr.addFeatures([qgsfeature])
    # symbology
    path = ":/kadas/icons/pin_red"
    symbol = QgsSvgMarkerSymbolLayer(path)
    symbol.setSize(10)
    symbol.setVerticalAnchorPoint(QgsMarkerSymbolLayer.Bottom)
    center_point.renderer().symbol().changeSymbolLayer(0, symbol)
    QgsProject.instance().addMapLayer(center_point)
Example #49
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))
Example #50
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
class CanvasLayerSaver:
    def __init__(
            self,
            name,
            features=None,
            crs=QgsCoordinateReferenceSystem(4326),
            color=QColor("lightGray"),
            style=None,
    ):
        self.name = name
        self.color = color
        self.transformer = transformToWGS(crs)
        self.features = features
        self.style = style
        self.addPolygonLayer()

    def addPolygonLayer(self):
        try:
            # FIXME: we do not consider if there are several layers with the same name here
            existinglayer = QgsProject.instance().mapLayersByName(self.name)[0]
            QgsProject.instance().removeMapLayer(existinglayer.id())
        except IndexError:
            # if such layer does not exist we can pass over
            pass
        # arbitrary decision taken: WGS84 for these layers
        self.layer = QgsVectorLayer(
            "Polygon?crs=epsg:4326&field=centerx:double&field=centery:double&field=interval:double",
            self.name,
            "memory",
        )
        pr = self.layer.dataProvider()
        if self.features:
            for feature in self.features:
                if isinstance(feature, QgsFeature):
                    geom = feature.geometry()
                    feature.setGeometry(self.reprojectToWGS84(geom))
                    pr.addFeatures([feature])
                elif isinstance(feature, QgsGeometry):
                    qgsFeature = QgsFeature()
                    qgsFeature.setGeometry(self.reprojectToWGS84(feature))
                    pr.addFeatures([qgsFeature])

        self.layer.updateExtents()
        QgsProject.instance().addMapLayer(self.layer)
        if self.style:
            self.layer.loadNamedStyle(self.style)
        else:
            renderer = QgsSingleSymbolRenderer.defaultRenderer(
                QgsWkbTypes.PolygonGeometry)
            symbol = renderer.symbol()
            symbol.setColor(self.color)
            symbol.symbolLayer(0).setStrokeColor(self.color)
            symbol.symbolLayer(0).setFillColor(QColor(0, 0, 0, 0))
            symbol.symbolLayer(0).setStrokeWidth(0.5)
            self.layer.setRenderer(renderer)

    def reprojectToWGS84(self, geom):
        geomType = geom.type()
        if geomType == QgsWkbTypes.LineGeometry:
            geomList = geom.asPolyline()
        elif geomType == QgsWkbTypes.PolygonGeometry:
            geomList = geom.asPolygon()
        newGeom = []
        for j in range(len(geomList)):
            if geomType == QgsWkbTypes.LineGeometry:
                newGeom.append(self.transformer.transform(geomList[j]))
            elif geomType == QgsWkbTypes.PolygonGeometry:
                line = geomList[j]
                for i in range(len(line)):
                    point = line[i]
                    newGeom.append(self.transformer.transform(point))
        if geomType == QgsWkbTypes.LineGeometry:
            return QgsGeometry.fromPolylineXY(newGeom)
        elif geomType == QgsWkbTypes.PolygonGeometry:
            return QgsGeometry.fromPolygonXY([newGeom])
        else:
            # TODO, from qgis 3.18 it will be possible to use the method
            # QgsWkbTypes.translatedDisplayString() to have much nicer error message
            pushWarning(
                "not implemented: cannot save layer type: {}".format(geomType))
Example #52
0
 def onAddLayersClick(self):
     try:
         # On parcourt les champs géographiques recensés
         for geoField in self.connector.getGeoFields():
             index = geoField["index"]
             type = geoField["type"]
             field = geoField["field"]
             geotype = geoField["geotype"]
             # On préparer les tableaux
             features = {
                 "MultiPoint": [],
                 "MultiLineString": [],
                 "MultiPolygon": []
             }
             # On parcourt les résultats
             hits = self.connector.getHits(index, type)
             if len(hits) > 0:
                 # Si on va récupérer des geo_point
                 if geotype == "geo_point":
                     for hit in hits:
                         try:
                             # On construit une feature et on l'ajoute au tableau
                             geoPoint = hit["_source"][field]
                             wkt = ""
                             if isinstance(geoPoint, str) or isinstance(
                                     geoPoint, unicode):
                                 coordinates = geoPoint.split(",")
                                 wkt = "POINT(" + coordinates[
                                     1] + " " + coordinates[0] + ")"
                             elif isinstance(geoPoint, dict):
                                 wkt = "POINT(" + geoPoint[
                                     "lon"] + " " + geoPoint["lat"] + ")"
                             elif isinstance(geoPoint, list):
                                 wkt = "POINT(" + geoPoint[
                                     1] + " " + geoPoint[0] + ")"
                             feature = QgsFeature()
                             feature.setGeometry(QgsGeometry.fromWkt(wkt))
                             features["MultiPoint"].append(feature)
                         except KeyError:
                             pass
                 # Si on va récupérer des geo_shape
                 elif geotype == "geo_shape":
                     for hit in hits:
                         try:
                             # On construit une feature et on l'ajoute au tableau
                             geom = hit["_source"][field]
                             geometry = ogr.CreateGeometryFromJson(
                                 json.dumps(geom))
                             wkt = geometry.ExportToWkt()
                             feature = QgsFeature()
                             feature.setGeometry(QgsGeometry.fromWkt(wkt))
                             geomtype = geom["type"].lower()
                             if "point" in geomtype:
                                 features["MultiPoint"].append(feature)
                             if "line" in geomtype:
                                 features["MultiLineString"].append(feature)
                             if "polygon" in geomtype:
                                 features["MultiPolygon"].append(feature)
                         except KeyError:
                             pass
                 # S'il y a au moins une géométrie exploitable qui a été récupérée dans ce champ
                 if len(features["MultiPoint"]) + len(
                         features["MultiLineString"]) + len(
                             features["MultiPolygon"]) > 0:
                     # On crée un groupe de couches
                     name = "[@ " + self.connector.getUrl(
                     ) + "] /" + index + "/" + type + "/" + field
                     group = QgsProject.instance().layerTreeRoot().addGroup(
                         name)
                     # On crée les couches vectorielles et on les ajoute à la carte
                     for geomtype in features:
                         if len(features[geomtype]) > 0:
                             # On crée la couche vectorielle
                             layer = QgsVectorLayer(
                                 geomtype + "?crs=EPSG:4326",
                                 geomtype[5:] + "s", "memory")
                             provider = layer.dataProvider()
                             # On ajoute le tableau de features à la couche
                             provider.addFeatures(features[geomtype])
                             layer.updateExtents()
                             # On ajoute la couche au groupe
                             QgsMapLayerRegistry.instance().addMapLayer(
                                 layer, False)
                             group.addLayer(layer)
         self.connector.clearGeoFields()
         self.iface.messageBar().pushMessage(
             "ElasticSearch Connector",
             u"Les couches ont été ajoutées",
             level=QgsMessageBar.INFO,
             duration=5)
         # On ferme la popup
         self.oncloseDlgClick()
     except ESConnectorException, e:
         self.iface.messageBar().pushMessage("ElasticSearch Connector",
                                             str(e),
                                             level=QgsMessageBar.CRITICAL,
                                             duration=5)
Example #53
0
    def handle_add_layer(self):
        """Create a new layer by name (rev_lyr)"""

        slds = self.get_sld()

        selected_name = self.dlg.mComboBox.currentText()
        selected_id = self.dataset_dictionary[selected_name]

        # Group name equals selected dataset name
        group = self.create_group(selected_name)

        # Get metadata and features from NgisOpenAPI
        try:
            metadata_from_api = self.client.getDatasetMetadata(selected_id)
            epsg = metadata_from_api.crs_epsg
            features_from_api = self.client.getDatasetFeatures(
                metadata_from_api.id, metadata_from_api.bbox, epsg)
        except Exception as e:
            error = ApiError("Nedlasting av data mislyktes",
                             "Kunne ikke laste ned datasett", e)
            self.iface.messageBar().pushMessage(error.title,
                                                error.detail,
                                                error.show_more,
                                                level=2,
                                                duration=10)
            return
        crs_from_api = features_from_api['crs']['properties']['name']
        features_by_type = {}

        # Extract features from GeoJSON into dictionary
        for feature in features_from_api['features']:
            feature_type = feature['properties']['featuretype']
            features_by_type.setdefault(feature_type, []).append(feature)

        features_from_api['features'] = None

        for feature_type, features_list in features_by_type.items():
            # Create a new GeoJSON object containing a single featuretype
            features_dict = features_from_api.copy()
            features_dict['features'] = features_list

            features_json = json.dumps(features_dict, ensure_ascii=False)

            # Identify fields and features from GeoJSON
            codec = QTextCodec.codecForName("UTF-8")
            fields = QgsJsonUtils.stringToFields(features_json, codec)
            newFeatures = QgsJsonUtils.stringToFeatureList(
                features_json, fields, codec)

            # If different geometry types are identified, separate them into individual layers
            geometry_dict = {}
            if newFeatures:
                for feature in newFeatures:

                    featuretype = feature.attribute('featuretype')
                    geom_type = feature.geometry()
                    geom_type = QgsWkbTypes.displayString(
                        int(geom_type.wkbType()))
                    if geom_type not in geometry_dict:
                        geometry_dict[geom_type] = {}
                    if featuretype not in geometry_dict[geom_type]:
                        geometry_dict[geom_type][featuretype] = []

                    geometry_dict[geom_type][featuretype].append(feature)

            for geom_type, feature_types in geometry_dict.items():
                for feature_type, features in feature_types.items():
                    lyr = QgsVectorLayer(f'{geom_type}?crs={crs_from_api}',
                                         f'{feature_type}-{geom_type}',
                                         "memory")
                    #lyr = QgsVectorLayer(f'{geom_type}?crs=EPSG:25832', f'{feature_type}-{geom_type}', "memory") #TODO Remove
                    QgsProject.instance().addMapLayer(lyr, False)

                    lyr.startEditing()

                    add_fields_to_layer(lyr, fields, feature_type)

                    lyr.commitChanges()
                    l_d = lyr.dataProvider()
                    l_d.addFeatures(features)
                    # update the extent of rev_lyr
                    lyr.updateExtents()
                    # save changes made in 'rev_lyr'
                    lyr.commitChanges()
                    group.addLayer(lyr)

                    #lyr.committedFeaturesAdded.connect(self.handleCommitedAddedFeatures)
                    #lyr.committedFeaturesRemoved.connect(self.handleCommittedFeaturesRemoved)
                    #lyr.featuresDeleted.connect(self.handleDeletedFeatures)
                    #lyr.committedGeometriesChanges(self.ee)

                    lyr.beforeCommitChanges.connect(
                        self.handle_before_commitchanges)

                    if feature_type in slds:
                        lyr.loadSldStyle(slds[feature_type])

                    self.dataset_dictionary[lyr.id()] = selected_id
                    self.feature_type_dictionary[lyr.id()] = feature_type
Example #54
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)
Example #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]
Example #56
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()
Example #57
0
def points_along_line(layerout,
                      startpoint,
                      endpoint,
                      distance,
                      label,
                      layer,
                      selected_only=True,
                      force=False,
                      fo_fila=False,
                      divide=0,
                      decimal=2):
    """Adding Points along the line
    """

    crs = layer.crs().authid()
    # TODO check for virtual or shapelayer and set virt_layer according to it
    shape = False
    if shape:
        # define fields for feature attributes. A list of QgsField objects is needed
        fields = [QgsField("first", QVariant.Int),
                  QgsField("second", QVariant.String)]
        # create an instance of vector file writer, which will create the vector file.
        # Arguments:
        # 1. path to new file (will fail if exists already)
        # 2. encoding of the attributes
        # 3. field map
        # 4. geometry type - from WKBTYPE enum
        # 5. layer's spatial reference (instance of
        #    QgsCoordinateReferenceSystem) - optional
        # 6. driver name for the output file
        writer = QgsVectorFileWriter("my_shapes.shp",
                                     "CP1250",
                                     fields,
                                     QGis.WKBPoint,
                                     crs,
                                     "ESRI Shapefile")
        if writer.hasError() != QgsVectorFileWriter.NoError:
            print "Error when creating shapefile: ", writer.hasError()
        # add a feature
        fet = QgsFeature()
        fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10)))
        fet.setAttributes([1, "text"])
        writer.addFeature(fet)
        # delete the writer to flush features to disk (optional)
        del writer

        layer_type = "Shapefile"  # TODO Add Shapefile functionality here
    else:
        layer_type = "memory"

    virt_layer = QgsVectorLayer("Point?crs=%s" % crs,
                                layerout,
                                layer_type)
    provider = virt_layer.dataProvider()
    virt_layer.startEditing()   # actually writes attributes
    units = layer.crs().mapUnits()
    unit_dic = {
        QGis.Degrees: 'Degrees',
        QGis.Meters: 'Meters',
        QGis.Feet: 'Feet',
        QGis.UnknownUnit: 'Unknown'}
    unit = unit_dic.get(units, 'Unknown')
    provider.addAttributes([QgsField("fid", QVariant.Int),
                            QgsField("cng_("+unit+")", QVariant.Double)])

    def get_features():
        """Getting the features
        """
        if selected_only:
            return layer.selectedFeatures()
        else:
            return layer.getFeatures()

    # Loop through all (selected) features
    for feature in get_features():
        geom = feature.geometry()
        # Add feature ID of selected feature
        fid = feature.id()
        if not geom:
            QgsMessageLog.logMessage("No geometry", "QChainage")
            continue

        features = create_points_at(startpoint,
                                    endpoint,
                                    distance,
                                    geom,
                                    fid,
                                    force,
                                    fo_fila,
                                    divide)
        provider.addFeatures(features)
        virt_layer.updateExtents()

    QgsMapLayerRegistry.instance().addMapLayers([virt_layer])
    virt_layer.commitChanges()
    virt_layer.reload()

    # from here Add labeling
    # generic labeling properties
    if label:
        virt_layer.setCustomProperty("labeling", "pal")
        virt_layer.setCustomProperty("labeling/enabled", "true")
        virt_layer.setCustomProperty("labeling/fieldName", "cng_("+unit+")")
        virt_layer.setCustomProperty("labeling/fontSize", "10")
        virt_layer.setCustomProperty("labeling/multiLineLabels", "true")
        virt_layer.setCustomProperty("labeling/formatNumbers", "true")
        virt_layer.setCustomProperty("labeling/decimals", decimal)

        # virt_layer.setCustomProperty("labeling/Size", "5")
    # symbol = QgsMarkerSymbolV2.createSimple({"name": "capital"})
    # virt_layer.setRendererV2(QgsSingleSymbolRendererV2(symbol))
    virt_layer.triggerRepaint()
    return
 def drawEllipse(self):
     # self.showInfo('Result: ' + str(self.result))
     meanx = self.result[0]
     meany = self.result[1]
     angle1 = self.result[2]
     angle2 = self.result[3]
     SD1 = self.result[4]
     SD2 = self.result[5]
     if self.method == 2:  # CrimeStat
         SD1 = SD1 * (sqrt(2) *
                      sqrt(self.featureCount) /
                      sqrt(self.featureCount - 2))
         SD2 = SD2 * (sqrt(2) *
                      sqrt(self.featureCount) /
                      sqrt(self.featureCount - 2))
     if self.crimestatCorr and self.method != 2:
         SD1 = SD1 * sqrt(2)
         SD2 = SD2 * sqrt(2)
     if self.degfreedCorr and self.method != 2:
         SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 2)
         SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 2)
         # SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 1)
         # SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 1)
     # Find the major and minor axis
     majoraxisangle = angle1
     minoraxisangle = angle2
     majorSD = SD2
     minorSD = SD1
     if SD2 < SD1:
         majoraxisangle = angle2
         minoraxisangle = angle1
         majorSD = SD1
         minorSD = SD2
     # Calculate the "compass" direction angle (clockwise from north)
     direction = 90.0 - majoraxisangle * 180 / pi
     # Calculte the eccentricity
     eccentricity = sqrt(1 - pow(minorSD, 2) / pow(majorSD, 2))
     # Create the memory layer for the ellipse
     sdefields = []
     sdefields.append(QgsField("meanx", QVariant.Double))
     sdefields.append(QgsField("meany", QVariant.Double))
     sdefields.append(QgsField("majoranglerad", QVariant.Double))
     # sdefields.append(QgsField("minoranglerad", QVariant.Double))
     sdefields.append(QgsField("directiondeg", QVariant.Double))
     sdefields.append(QgsField("majorsd", QVariant.Double))
     sdefields.append(QgsField("minorsd", QVariant.Double))
     sdefields.append(QgsField("eccentricity", QVariant.Double))
     layeruri = 'Polygon?'
     layeruri = (layeruri + 'crs=' +
                 str(self.SDLayer.dataProvider().crs().authid()))
     memSDlayer = QgsVectorLayer(layeruri, self.OutputLayerName.text(),
                                 "memory")
     # Set the CRS to the original CRS object
     memSDlayer.setCrs(self.SDLayer.dataProvider().crs())
     memSDlayer.startEditing()  # ?
     for field in sdefields:
         memSDlayer.dataProvider().addAttributes([field])
     sdfeature = QgsFeature()
     theta1 = majoraxisangle
     points = []
     step = pi / 180    # 360 points to draw the ellipse
     t = 0.0
     while t < 2 * pi:
         p1 = QPointF(meanx + majorSD * cos(t) * cos(majoraxisangle) -
                      minorSD * sin(t) * sin(majoraxisangle),
                      meany + majorSD * cos(t) * sin(majoraxisangle) +
                      minorSD * sin(t) * cos(majoraxisangle))
         points.append(QgsPointXY(p1))
         t = t + step
     # Close the polygon
     p1 = QPointF(meanx + majorSD * cos(majoraxisangle),
                  meany + majorSD * sin(majoraxisangle))
     points.append(QgsPointXY(p1))
     sdfeature.setGeometry(QgsGeometry.fromPolygonXY([points]))
     attrs = [meanx, meany, majoraxisangle, direction,
              majorSD, minorSD, eccentricity]
     sdfeature.setAttributes(attrs)
     memSDlayer.dataProvider().addFeatures([sdfeature])
     memSDlayer.commitChanges()  # ?
     memSDlayer.updateExtents()
     QgsProject.instance().addMapLayers([memSDlayer])
Example #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)
Example #60
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)