Ejemplo n.º 1
1
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context)
        target_crs = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS, context)

        target_geom = QgsGeometry.fromRect(extent)

        fields = QgsFields()
        fields.append(QgsField('auth_id', QVariant.String, '', 20))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())

        # make intersection tests nice and fast
        engine = QgsGeometry.createGeometryEngine(target_geom.constGet())
        engine.prepareGeometry()

        layer_bounds = QgsGeometry.fromRect(source.sourceExtent())

        crses_to_check = QgsCoordinateReferenceSystem.validSrsIds()
        total = 100.0 / len(crses_to_check)

        found_results = 0

        transform_context = QgsCoordinateTransformContext()
        for current, srs_id in enumerate(crses_to_check):
            if feedback.isCanceled():
                break

            candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id)
            if not candidate_crs.isValid():
                continue

            transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs, transform_context)
            transformed_bounds = QgsGeometry(layer_bounds)
            try:
                if not transformed_bounds.transform(transform_candidate) == 0:
                    continue
            except:
                continue

            try:
                if engine.intersects(transformed_bounds.constGet()):
                    feedback.pushInfo(self.tr('Found candidate CRS: {}').format(candidate_crs.authid()))
                    f = QgsFeature(fields)
                    f.setAttributes([candidate_crs.authid()])
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    found_results += 1
            except:
                continue

            feedback.setProgress(int(current * total))

        if found_results == 0:
            feedback.reportError(self.tr('No matching projections found'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 2
0
 def transformGeom(self, item):
     src_crs = QgsCoordinateReferenceSystem()
     src_crs.createFromSrid(item.srid)
     dest_crs = self.mapCanvas.mapRenderer().destinationCrs()
     geom = QgsGeometry(item.geometry)
     geom.transform(QgsCoordinateTransform(src_crs, dest_crs))
     return geom
Ejemplo n.º 3
0
    def set_next_analysis_extent(self, extent, crs):
        """Setter for the next analysis extent.

        This function will redraw the rubberband if needed.

        :param extent: The next analysis extent.
        :type extent: QgsGeometry

        :param crs: The CRS of the extent.
        :type crs: QgsCoordinateReferenceSystem
        """
        extent = QgsGeometry(extent)
        transform = QgsCoordinateTransform(crs, self.crs)
        extent.transform(transform)
        self._next_analysis_extent = extent

        if self._show_rubber_bands:
            self.display_next_analysis()
Ejemplo n.º 4
0
    def set_user_extent(self, extent, crs):
        """Setter for the user requested extent.

        This function will redraw the rubberband if needed.

        :param extent: The user extent.
        :type extent: QgsGeometry

        :param crs: The CRS of the extent.
        :type crs: QgsCoordinateReferenceSystem
        """
        extent = QgsGeometry(extent)
        transform = QgsCoordinateTransform(crs, self.crs)
        extent.transform(transform)
        self._user_extent = extent
        set_setting('user_extent', extent.exportToWkt())
        set_setting('user_extent_crs', crs.authid())
        if self._show_rubber_bands:
            self.display_user_extent()
Ejemplo n.º 5
0
  def _addHighlightGeom(self):
    def highlight():
      rb = QgsRubberBand( self.canvas, QGis.Polygon)
      rb.setBorderColor( QColor( 255,  0, 0 ) )
      rb.setWidth( 2 )
      rb.setToGeometry( geomRB, None )

      return rb

    crsCanvas = self.canvas.mapSettings().destinationCrs()
    crsLayer = self.layerSrc.crs()
    if not crsCanvas == crsLayer:
      geomRB = QgsGeometry( self.geom )
      ct = QgsCoordinateTransform( crsLayer, crsCanvas )
      geomRB.transform( ct )
    else:
      geomRB = self.geom

    return highlight()
Ejemplo n.º 6
0
def dissolvePolygonsOnCanvas(writer, layer):
  """dissolve polygons of the layer and clip the dissolution with base extent"""
  settings = writer.settings
  baseExtent = settings.baseExtent
  baseExtentGeom = baseExtent.geometry()
  rotation = baseExtent.rotation()
  transform = QgsCoordinateTransform(layer.crs(), settings.crs)

  combi = None
  request = QgsFeatureRequest()
  request.setFilterRect(transform.transformBoundingBox(baseExtent.boundingBox(), QgsCoordinateTransform.ReverseTransform))
  for f in layer.getFeatures(request):
    geometry = f.geometry()
    if geometry is None:
      logMessage("null geometry skipped")
      continue

    # coordinate transformation - layer crs to project crs
    geom = QgsGeometry(geometry)
    if geom.transform(transform) != 0:
      logMessage("Failed to transform geometry")
      continue

    # check if geometry intersects with the base extent (rotated rect)
    if rotation and not baseExtentGeom.intersects(geom):
      continue

    if combi:
      combi = combi.combine(geom)
    else:
      combi = geom

  # clip geom with slightly smaller extent than base extent
  # to make sure that the clipped polygon stays within the base extent
  geom = combi.intersection(baseExtent.clone().scale(0.999999).geometry())
  if geom is None:
    return None

  # check if geometry is empty
  if geom.isGeosEmpty():
    logMessage("empty geometry")
    return None

  return geom
Ejemplo n.º 7
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)

        extent = self.getParameterValue(self.TARGET_AREA).split(',')
        if not extent:
            extent = QgsProcessingUtils.combineLayerExtents([layer])
        target_crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.TARGET_AREA_CRS))

        target_geom = QgsGeometry.fromRect(QgsRectangle(float(extent[0]), float(extent[2]),
                                                        float(extent[1]), float(extent[3])))

        output_file = self.getOutputValue(self.OUTPUT_HTML_FILE)

        # make intersection tests nice and fast
        engine = QgsGeometry.createGeometryEngine(target_geom.geometry())
        engine.prepareGeometry()

        layer_bounds = QgsGeometry.fromRect(layer.extent())

        results = []

        for srs_id in QgsCoordinateReferenceSystem.validSrsIds():
            candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id)
            if not candidate_crs.isValid():
                continue

            transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs)
            transformed_bounds = QgsGeometry(layer_bounds)
            try:
                if not transformed_bounds.transform(transform_candidate) == 0:
                    continue
            except:
                continue

            if engine.intersects(transformed_bounds.geometry()):
                results.append(candidate_crs.authid())

        self.createHTML(output_file, results)
Ejemplo n.º 8
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        method = self.getParameterValue(self.METHOD)

        geometryType = layer.geometryType()

        idx1 = -1
        idx2 = -1
        fields = layer.pendingFields()

        if geometryType == QGis.Polygon:
            (idx1, fields) = vector.findOrCreateField(layer, fields, 'area',
                    21, 6)
            (idx2, fields) = vector.findOrCreateField(layer, fields,
                    'perimeter', 21, 6)
        elif geometryType == QGis.Line:
            (idx1, fields) = vector.findOrCreateField(layer, fields, 'length',
                    21, 6)
            idx2 = idx1
        else:
            (idx1, fields) = vector.findOrCreateField(layer, fields, 'xcoord',
                    21, 6)
            (idx2, fields) = vector.findOrCreateField(layer, fields, 'ycoord',
                    21, 6)

        writer = self.getOutputFromName(
            self.OUTPUT).getVectorWriter(fields.toList(),
            layer.dataProvider().geometryType(), layer.crs())

        ellips = None
        crs = None
        coordTransform = None

        # Calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal

        if method == 2:
            ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid',
                    'NONE')[0]
            crs = layer.crs().srsid()
        elif method == 1:
            mapCRS = iface.mapCanvas().mapRenderer().destinationCrs()
            layCRS = layer.crs()
            coordTransform = QgsCoordinateTransform(layCRS, mapCRS)

        outFeat = QgsFeature()
        inGeom = QgsGeometry()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

        current = 0
        features = vector.features(layer)
        total = 100.0 / float(len(features))
        for f in features:
            inGeom = f.geometry()

            if method == 1:
                inGeom.transform(coordTransform)

            (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs)

            outFeat.setGeometry(inGeom)
            attrs = f.attributes()
            attrs.insert(idx1, attr1)
            if attr2 is not None:
                attrs.insert(idx2, attr2)
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            current += 1
            progress.setPercentage(int(current * total))

        del writer
Ejemplo n.º 9
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        method = self.getParameterValue(self.METHOD)

        geometryType = layer.geometryType()
        fields = layer.fields()

        export_z = False
        export_m = False
        if geometryType == QgsWkbTypes.PolygonGeometry:
            areaName = vector.createUniqueFieldName("area", fields)
            fields.append(QgsField(areaName, QVariant.Double))
            perimeterName = vector.createUniqueFieldName("perimeter", fields)
            fields.append(QgsField(perimeterName, QVariant.Double))
        elif geometryType == QgsWkbTypes.LineGeometry:
            lengthName = vector.createUniqueFieldName("length", fields)
            fields.append(QgsField(lengthName, QVariant.Double))
        else:
            xName = vector.createUniqueFieldName("xcoord", fields)
            fields.append(QgsField(xName, QVariant.Double))
            yName = vector.createUniqueFieldName("ycoord", fields)
            fields.append(QgsField(yName, QVariant.Double))
            if QgsWkbTypes.hasZ(layer.wkbType()):
                export_z = True
                zName = vector.createUniqueFieldName("zcoord", fields)
                fields.append(QgsField(zName, QVariant.Double))
            if QgsWkbTypes.hasM(layer.wkbType()):
                export_m = True
                zName = vector.createUniqueFieldName("mvalue", fields)
                fields.append(QgsField(zName, QVariant.Double))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields.toList(), layer.wkbType(), layer.crs())

        ellips = None
        crs = None
        coordTransform = None

        # Calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal

        if method == 2:
            ellips = QgsProject.instance().readEntry("Measure", "/Ellipsoid", "NONE")[0]
            crs = layer.crs().srsid()
        elif method == 1:
            mapCRS = iface.mapCanvas().mapSettings().destinationCrs()
            layCRS = layer.crs()
            coordTransform = QgsCoordinateTransform(layCRS, mapCRS)

        outFeat = QgsFeature()
        inGeom = QgsGeometry()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            inGeom = f.geometry()

            if method == 1:
                inGeom.transform(coordTransform)

            (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs)

            outFeat.setGeometry(inGeom)
            attrs = f.attributes()
            attrs.append(attr1)
            if attr2 is not None:
                attrs.append(attr2)

            # add point z/m
            if export_z:
                attrs.append(inGeom.geometry().z())
            if export_m:
                attrs.append(inGeom.geometry().m())

            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer
Ejemplo n.º 10
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(
            self.INPUT))
        method = self.getParameterValue(self.METHOD)

        geometryType = layer.geometryType()
        fields = layer.fields()

        export_z = False
        export_m = False
        if geometryType == QgsWkbTypes.PolygonGeometry:
            areaName = vector.createUniqueFieldName('area', fields)
            fields.append(QgsField(areaName, QVariant.Double))
            perimeterName = vector.createUniqueFieldName('perimeter', fields)
            fields.append(QgsField(perimeterName, QVariant.Double))
        elif geometryType == QgsWkbTypes.LineGeometry:
            lengthName = vector.createUniqueFieldName('length', fields)
            fields.append(QgsField(lengthName, QVariant.Double))
        else:
            xName = vector.createUniqueFieldName('xcoord', fields)
            fields.append(QgsField(xName, QVariant.Double))
            yName = vector.createUniqueFieldName('ycoord', fields)
            fields.append(QgsField(yName, QVariant.Double))
            if QgsWkbTypes.hasZ(layer.wkbType()):
                export_z = True
                zName = vector.createUniqueFieldName('zcoord', fields)
                fields.append(QgsField(zName, QVariant.Double))
            if QgsWkbTypes.hasM(layer.wkbType()):
                export_m = True
                zName = vector.createUniqueFieldName('mvalue', fields)
                fields.append(QgsField(zName, QVariant.Double))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields.toList(), layer.wkbType(), layer.crs())

        ellips = None
        crs = None
        coordTransform = None

        # Calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal

        if method == 2:
            ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid',
                                                     'NONE')[0]
            crs = layer.crs().srsid()
        elif method == 1:
            mapCRS = iface.mapCanvas().mapSettings().destinationCrs()
            layCRS = layer.crs()
            coordTransform = QgsCoordinateTransform(layCRS, mapCRS)

        outFeat = QgsFeature()
        inGeom = QgsGeometry()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            inGeom = f.geometry()

            if method == 1:
                inGeom.transform(coordTransform)

            (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs)

            outFeat.setGeometry(inGeom)
            attrs = f.attributes()
            attrs.append(attr1)
            if attr2 is not None:
                attrs.append(attr2)

            # add point z/m
            if export_z:
                attrs.append(inGeom.geometry().z())
            if export_m:
                attrs.append(inGeom.geometry().m())

            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer
Ejemplo n.º 11
0
  def export_geometry_info( self ):
    ellips = None
    crs = None
    coordTransform = None

    # calculate with:
    # 0 - layer CRS
    # 1 - project CRS
    # 2 - ellipsoidal
    if self.myCalcType == 2:
      settings = QSettings()
      ellips = settings.value( "/qgis/measure/ellipsoid", "WGS84" )
      crs = self.vlayer.crs().srsid()
    elif self.myCalcType == 1:
      mapCRS = self.parent.iface.mapCanvas().mapRenderer().destinationCrs()
      layCRS = self.vlayer.crs()
      coordTransform = QgsCoordinateTransform( layCRS, mapCRS )

    inFeat = QgsFeature()
    outFeat = QgsFeature()
    inGeom = QgsGeometry()
    nElement = 0

    vprovider = self.vlayer.dataProvider()
    self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0)
    self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, vprovider.featureCount() ) )

    ( fields, index1, index2 ) = self.checkMeasurementFields( self.vlayer, not self.writeShape )

    if self.writeShape:
      writer = QgsVectorFileWriter( self.myName, self.myEncoding, fields,
                                    vprovider.geometryType(), vprovider.crs() )

    fit = vprovider.getFeatures()
    while fit.nextFeature(inFeat):
      self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ),  nElement )
      nElement += 1
      inGeom = inFeat.geometry()

      if self.myCalcType == 1:
        inGeom.transform( coordTransform )

      ( attr1, attr2 ) = self.simpleMeasure( inGeom, self.myCalcType, ellips, crs )

      if self.writeShape:
        outFeat.setGeometry( inGeom )
        atMap = inFeat.attributes()
        maxIndex = index1 if index1 > index2 else index2
        if maxIndex >= len(atMap):
          atMap += [ "" ] * ( index2+1 - len(atMap) )
        atMap[ index1 ] = attr1
        if index1 != index2:
          atMap[ index2 ] = attr2
        outFeat.setAttributes( atMap )
        writer.addFeature( outFeat )
      else:
        changeMap = {}
        changeMap[ inFeat.id() ] = {}
        changeMap[ inFeat.id() ][ index1 ] = attr1
        if index1!=index2:
          changeMap[ inFeat.id() ][ index2 ] = attr2
        vprovider.changeAttributeValues( changeMap )
        self.vlayer.updateFields()

    if self.writeShape:
      del writer

    return True
    def copySourceFeaturesToTargetLayer(self):
        success = True
        layers = self.dependentLayers()
        for layer in layers:
            if layer.name(
            ) != YleiskaavaDatabase.KAAVAOBJEKTI_ALUE and layer.name(
            ) != YleiskaavaDatabase.KAAVAOBJEKTI_ALUE_TAYDENTAVA and layer.name(
            ) != YleiskaavaDatabase.KAAVAOBJEKTI_VIIVA and layer.name(
            ) != YleiskaavaDatabase.KAAVAOBJEKTI_PISTE and layer.name(
            ) != "kaavaobjekti_kaavamaarays_yhteys" and layer.name(
            ) != "kaavamääräykset":
                self.sourceLayer = layer
                self.sourceFeatures = layer.selectedFeatures()
                self.sourceFeatureCount = layer.selectedFeatureCount()
                self.sourceCRS = layer.sourceCrs()
                self.sourceLayerFields = layer.fields().toList()
            elif layer.name(
            ) != "kaavaobjekti_kaavamaarays_yhteys" and layer.name(
            ) != "kaavamääräykset":
                self.targetLayer = layer
                self.targetCRS = layer.sourceCrs()

        # QgsMessageLog.logMessage("copySourceFeaturesToTargetLayer - targetLayer.name(): " + str(self.targetLayer.name()), 'Yleiskaava-työkalu', Qgis.Info)
        # QgsMessageLog.logMessage("copySourceFeaturesToTargetLayer - targetCRS: " + self.targetCRS.authid(), 'Yleiskaava-työkalu', Qgis.Info)

        transform = None
        if self.sourceCRS != self.targetCRS:
            transform = QgsCoordinateTransform(self.sourceCRS, self.targetCRS,
                                               self.transformContext)

        for index, sourceFeature in enumerate(self.sourceFeatures):

            targetLayerFeature = QgsFeature()
            targetLayerFeature.setFields(self.targetLayer.fields())
            featureID = str(uuid.uuid4())
            targetLayerFeature.setAttribute("id", featureID)
            sourceGeom = sourceFeature.geometry()

            if not sourceGeom.isNull() and transform is not None:
                transformedSourceGeom = QgsGeometry(sourceGeom)
                transformedSourceGeom.transform(transform)
            else:
                transformedSourceGeom = QgsGeometry(sourceGeom)

            targetLayerFeature.setGeometry(transformedSourceGeom)

            success = self.setTargetFeatureValues(sourceFeature,
                                                  targetLayerFeature)
            if not success:
                return success

            # QgsMessageLog.logMessage("copySourceFeaturesToTargetLayer - targetLayerFeature['nro']: " + str(targetLayerFeature['nro']), 'Yleiskaava-työkalu', Qgis.Info)

            self.handleRegulationAndLandUseClassificationInSourceToTargetCopy(
                sourceFeature, self.targetSchemaTableName, targetLayerFeature,
                False)
            self.handleSpatialPlanRelationInSourceToTargetCopy(
                targetLayerFeature)

            return_data = self.yleiskaavaDatabase.createTargetFeature(
                self.targetSchemaTableName, sourceFeature, targetLayerFeature,
                self.targetCRS)

            # QgsMessageLog.logMessage('createTargetFeature valmis', 'Yleiskaava-työkalu', Qgis.Info)
            # QgsMessageLog.logMessage(json.dumps(return_data), 'Yleiskaava-työkalu', Qgis.Info)

            for item in return_data['messages']:
                CopySourceDataToDatabaseTask.yleiskaava_exceptions.append(item)
                QgsMessageLog.logMessage(
                    "lisätty poikkeuksiin: " + item['message'],
                    'Yleiskaava-työkalu', Qgis.Info)

            if not return_data['success']:
                # exception = "yleiskaavaDatabase.createTargetFeature epäonnistui, sourceFeature-attribuutit: "
                # for field in self.targetLayer.fields().toList():
                #     if sourceFeature[field.name()]:
                #         exception += str(sourceFeature[field.name()]) + ", "
                # exception = exception[:-2]
                # CopySourceDataToDatabaseTask.yleiskaava_exceptions.append(exception)
                break
            else:
                # Kaavakohteen pitää olla jo tallennettuna tietokannassa, jotta voidaan lisätä relaatio kaavamääräykseen
                self.handleRegulationAndLandUseClassificationInSourceToTargetCopy(
                    sourceFeature, self.targetSchemaTableName,
                    targetLayerFeature, True)

                if self.isCanceled():
                    break

                progress = (index / self.sourceFeatureCount) * 100
                self.setProgress(progress)

        return success
Ejemplo n.º 13
0
    def getSchnittpunkteAusPolygonen(self, overlapFeats, featureCrs,
                                     laengsProfil, feedback):
        schnittpunktFeatures = []
        schnittLinesFeatures = []
        ioFeat = 0
        countPoints = 0
        try:
            for feat in overlapFeats:
                #Feature bekommt neues Attribut Station
                if ioFeat == 0:
                    fields = feat.fields()
                    fields.append(QgsField("station", QVariant.Double))

                schnittpunktFeaturesOfThisPolygon = []
                schnittpunktListOfPolygon = [
                ]  #Liste [points, stations, feature.id's]
                #check if Multipolygon
                iMulti = 0
                iRing = 0

                tempGeom = QgsGeometry()
                tempGeom.fromWkb(feat.geometry().asWkb())
                #transform geom to Project.crs() if crs a different
                if not featureCrs.authid() == QgsProject.instance().crs(
                ).authid():
                    trafo = QgsCoordinateTransform(featureCrs,
                                                   QgsProject.instance().crs(),
                                                   QgsProject.instance())
                    #transform Geom to Project.crs()
                    tempGeom.transform(trafo,
                                       QgsCoordinateTransform.ForwardTransform,
                                       False)

                if tempGeom.isMultipart():
                    multiGeom = tempGeom.asMultiPolygon()
                    #Schleife zum Auflösen des Multiparts
                    for polygon in multiGeom:
                        for ring in polygon:
                            points = []
                            for pxy in ring:
                                #feedback.pushInfo(str(iMulti)+" "+str(iRing)+" "+str(pxy) + " " + str(type(pxy)))
                                points.append(QgsPoint(pxy.x(), pxy.y()))
                            singlePolygon = QgsGeometry().fromPolyline(points)
                            iRing = iRing + 1

                            #feedback.pushInfo(str(iMulti) + str(type(singlePolygon)) + str(polygon))

                            schnittpunktFeaturesOfThisPolygonItem = self.makeIntersectionFeatures(
                                feat, singlePolygon, laengsProfil, fields,
                                feedback)
                            for spfotp in schnittpunktFeaturesOfThisPolygonItem:
                                schnittpunktFeaturesOfThisPolygon.append(
                                    spfotp)
                            #Liste [points, stations, feature.id's]
                            schnittpunktListOfPolygonItem = self.makeIntersectionPointsStationList(
                                feat, singlePolygon, laengsProfil, fields,
                                feedback)
                            for sp in schnittpunktListOfPolygonItem:
                                schnittpunktListOfPolygon.append(sp)

                            iMulti = iMulti + 1

                else:  # single Geometry
                    schnittpunktFeaturesOfThisPolygon = self.makeIntersectionFeatures(
                        feat, tempGeom, laengsProfil, fields, feedback)
                    schnittpunktListOfPolygon = self.makeIntersectionPointsStationList(
                        feat, tempGeom, laengsProfil, fields, feedback)

                #create LineFeatures
                schnittLinesFeats = self.makeLineFeaturesFromPointStationList(
                    feat, schnittpunktListOfPolygon, laengsProfil, feedback)
                for f in schnittLinesFeats:
                    schnittLinesFeatures.append(f)

                #add to list
                for schnittFeat in schnittpunktFeaturesOfThisPolygon:  #Intersection Feature in project.crs()
                    schnittpunktFeatures.append(schnittFeat)
                    #feedback.pushInfo(str(schnittFeat.attributes()))
                ioFeat = ioFeat + 1
                #count Intersections
                countPoints = countPoints + len(
                    schnittpunktFeaturesOfThisPolygon)

        except:
            msg = self.tr(
                "Error: Creating Intersections Geometry {0} Feature {1}"
            ).format(str(type(feat.geometry())), str(feat.attributes()))
            feedback.reportError(msg)
            raise QgsProcessingException(msg)
        msgInfo = self.tr("Intersected Lines: {0} Intersections: {1}").format(
            ioFeat, countPoints)
        feedback.pushInfo(msgInfo)
        return schnittpunktFeatures, schnittLinesFeatures
Ejemplo n.º 14
0
  def features(self, request=None, clipGeom=None):
    settings = self.writer.settings
    mapTo3d = settings.mapTo3d()
    baseExtent = settings.baseExtent
    baseExtentGeom = baseExtent.geometry()
    rotation = baseExtent.rotation()
    prop = self.prop

    useZ = prop.useZ()
    if useZ:
      srs_from = osr.SpatialReference()
      srs_from.ImportFromProj4(str(self.layer.crs().toProj4()))
      srs_to = osr.SpatialReference()
      srs_to.ImportFromProj4(str(self.writer.settings.crs.toProj4()))

      ogr_transform = osr.CreateCoordinateTransformation(srs_from, srs_to)
      clipGeomWkb = clipGeom.asWkb() if clipGeom else None
      ogr_clipGeom = ogr.CreateGeometryFromWkb(clipGeomWkb) if clipGeomWkb else None

    else:
      # z_func: function to get elevation at given point (x, y) on surface
      if prop.isHeightRelativeToDEM():
        if self.geomType == QGis.Polygon and prop.type_index == 1:  # Overlay
          z_func = lambda x, y: 0
        else:
          # get elevation from DEM
          z_func = lambda x, y: self.writer.demProvider.readValue(x, y)
      else:
        z_func = lambda x, y: 0

    request = request or QgsFeatureRequest()
    for f in self.layer.getFeatures(request):
      geometry = f.geometry()
      if geometry is None:
        logMessage("null geometry skipped")
        continue

      # coordinate transformation - layer crs to project crs
      geom = QgsGeometry(geometry)
      if geom.transform(self.transform) != 0:
        logMessage("Failed to transform geometry")
        continue

      # check if geometry intersects with the base extent (rotated rect)
      if rotation and not baseExtentGeom.intersects(geom):
        continue

      # create feature
      feat = Feature(self.writer, self, f)

      # transform_func: function to transform the map coordinates to 3d coordinates
      relativeHeight = prop.relativeHeight(f)

      def transform_func(x, y, z):
        return mapTo3d.transform(x, y, z + relativeHeight)

      if useZ:
        ogr_geom = ogr.CreateGeometryFromWkb(geometry.asWkb())

        # transform geometry from layer CRS to project CRS
        if ogr_geom.Transform(ogr_transform) != 0:
          logMessage("Failed to transform geometry")
          continue

        # clip geometry
        if ogr_clipGeom and self.geomType == QGis.Line:
          ogr_geom = ogr_geom.Intersection(ogr_clipGeom)
          if ogr_geom is None:
            continue

        # check if geometry is empty
        if ogr_geom.IsEmpty():
          logMessage("empty geometry skipped")
          continue

        feat.geom = self.geomClass.fromOgrGeometry25D(ogr_geom, transform_func)

      else:
        # clip geometry
        if clipGeom and self.geomType in [QGis.Line, QGis.Polygon]:
          geom = geom.intersection(clipGeom)
          if geom is None:
            continue

        # check if geometry is empty
        if geom.isGeosEmpty():
          logMessage("empty geometry skipped")
          continue

        if self.geomType == QGis.Polygon:
          feat.geom = self.geomClass.fromQgsGeometry(geom, z_func, transform_func, self.hasLabel())
          if prop.type_index == 1 and prop.isHeightRelativeToDEM():   # Overlay and relative to DEM
            feat.geom.splitPolygon(self.writer.triangleMesh())

        else:
          feat.geom = self.geomClass.fromQgsGeometry(geom, z_func, transform_func)

      if feat.geom is None:
        continue

      yield feat
Ejemplo n.º 15
0
 def geomTransform(self, geom, crs_orig, crs_dest):
     g = QgsGeometry(geom)
     crsTransform = QgsCoordinateTransform(
         crs_orig, crs_dest, QgsCoordinateTransformContext())  # which context ?
     g.transform(crsTransform)
     return g
Ejemplo n.º 16
0
def setSelectFeatures(canvas, selectGeometry, doContains, doDifference, singleSelect=None):
    """
    QgsMapCanvas* canvas,
    QgsGeometry* selectGeometry,
    bool doContains,
    bool doDifference,
    bool singleSelect 
    """
    if selectGeometry.type() != QGis.Polygon:
        return

    vlayer = getCurrentVectorLayer(canvas)

    if vlayer == None:
        return

    #toLayerCoordinates will throw an exception for any 'invalid' points in
    #the rubber band.
    #For example, if you project a world map onto a globe using EPSG 2163
    #and then click somewhere off the globe, an exception will be thrown.
    selectGeomTrans = QgsGeometry(selectGeometry)

    if canvas.mapSettings().hasCrsTransformEnabled():
        try:
            ct = QgsCoordinateTransform(canvas.mapSettings().destinationCrs(), vlayer.crs())
            selectGeomTrans.transform( ct )
        except QgsCsException as cse:
            Q_UNUSED(cse)
            #catch exception for 'invalid' point and leave existing selection unchanged
            """
            QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) );
            QgisApp::instance()->messageBar()->pushMessage(
            QObject::tr( "CRS Exception" ),
            QObject::tr( "Selection extends beyond layer's coordinate system" ),
            QgsMessageBar::WARNING,
            QgisApp::instance()->messageTimeout() );
            """
            return

    QApplication.setOverrideCursor(Qt.WaitCursor)
    """
    QgsDebugMsg( "Selection layer: " + vlayer->name() );
    QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() );
    QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) );
    QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) );
    """

    context = QgsRenderContext().fromMapSettings(canvas.mapSettings())
    r = vlayer.rendererV2()

    if r:
        r.startRender(context, vlayer.pendingFields())

    request = QgsFeatureRequest()
    request.setFilterRect(selectGeomTrans.boundingBox())
    request.setFlags(QgsFeatureRequest.ExactIntersect)

    if r:
        request.setSubsetOfAttributes(r.usedAttributes(), vlayer.pendingFields())
    else:
        request.setSubsetOfAttributes(QgsAttributeList)

    fit = vlayer.getFeatures(request)

    newSelectedFeatures = [] #QgsFeatureIds
    f = QgsFeature() 
    closestFeatureId = 0 #QgsFeatureId 
    foundSingleFeature = False
    #double closestFeatureDist = std::numeric_limits<double>::max();
    closestFeatureDist = sys.float_info.max

    while fit.nextFeature(f):
        # make sure to only use features that are visible
        if r and not r.willRenderFeature( f ):
            continue;
        g = QgsGeometry(f.geometry())
        if doContains:
            if not selectGeomTrans.contains(g):
                continue
        else:
            if not selectGeomTrans.intersects(g):
                continue
        if singleSelect:
            foundSingleFeature = True
            distance = float(g.distance(selectGeomTrans))
            if ( distance <= closestFeatureDist ):
                closestFeatureDist = distance
                closestFeatureId = f.id()
        else:
            newSelectedFeatures.insert(0, f.id())

    if singleSelect and foundSingleFeature:
        newSelectedFeatures.insert(0, closestFeatureId)
    if r:
        r.stopRender(context)
    #QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) 

    if doDifference:
        layerSelectedFeatures = vlayer.selectedFeaturesIds()

        selectedFeatures = [] #QgsFeatureIds 
        deselectedFeatures = []# QgsFeatureIds

        # i = QgsFeatureIds.const_iterator(newSelectedFeatures.constEnd())
        # while i != newSelectedFeatures.constBegin():
        #     i = i - 1 
        #     if layerSelectedFeatures.contains(i):
        #         deselectedFeatures.insert(0, i)
        #     else:
        #         selectedFeatures.insert(0, i)

        for item in newSelectedFeatures:
            if item in layerSelectedFeatures:
                deselectedFeatures.insert(0, item)
            else:
                selectedFeatures.insert(0, item)


        vlayer.modifySelection(selectedFeatures, deselectedFeatures)
    else:
        vlayer.setSelectedFeatures(newSelectedFeatures)

    QApplication.restoreOverrideCursor()

    """
Ejemplo n.º 17
0
 def geomTransform(self, geom, crs_orig, crs_dest):
     g = QgsGeometry(geom)
     crsTransform = QgsCoordinateTransform(crs_orig, crs_dest, QgsProject().instance())
     g.transform(crsTransform)
     return g
Ejemplo n.º 18
0
    def setSelectFeaturesOrRubberband_Tas(canvas,
                                          selectGeometry,
                                          doContains=True,
                                          doDifference=False,
                                          singleSelect=False):
        if (selectGeometry.type() != QGis.Polygon):
            return
        vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer(canvas)
        if (vlayer == None):
            return

        #// toLayerCoordinates will throw an exception for any 'invalid' points in
        #// the rubber band.
        #// For example, if you project a world map onto a globe using EPSG 2163
        #// and then click somewhere off the globe, an exception will be thrown.
        selectGeomTrans = QgsGeometry(selectGeometry)

        if (canvas.mapSettings().hasCrsTransformEnabled()):
            try:

                ct = QgsCoordinateTransform(
                    canvas.mapSettings().destinationCrs(), vlayer.crs())
                #                 print selectGeomTrans.boundingBox().xMaximum ()
                #                 polygonList = []
                #                 for polygon in selectGeomTrans1.asPolygon():
                #                     pointList = []
                #                     for point in polygon:
                #                         transPoint = QgisHelper.CrsTransformPoint(point.x(), point.y(), define._mapCrs, vlayer.crs())
                #                         pointList.append(transPoint)
                #                     polygonList.extend(pointList)
                #                 selectGeomTrans = QgsGeometry.fromPolygon (pointList)
                selectGeomTrans.transform(ct)

            except QgsCsException as cse:
                raise UserWarning, "Coordinate Transform Error in QgsMapToolSelectUtils\n" + cse.message

        QApplication.setOverrideCursor(Qt.WaitCursor)

        fit = vlayer.getFeatures(QgsFeatureRequest().setFilterRect(
            selectGeomTrans.boundingBox()).setFlags(
                QgsFeatureRequest.ExactIntersect).setSubsetOfAttributes([]))

        newSelectedFeatures = []
        newSelectedFeatureList = []
        f = QgsFeature()
        closestFeatureId = 0
        foundSingleFeature = False
        closestFeatureDist = 9.0E+10
        for f in fit:
            g = f.geometry()
            if (doContains):
                if (not selectGeomTrans.contains(g)):
                    continue
            else:
                if (not selectGeomTrans.intersects(g)):
                    continue
            if (singleSelect):
                foundSingleFeature = True
                distance = g.distance(selectGeomTrans)
                if (distance <= closestFeatureDist):
                    closestFeatureDist = distance
                    closestFeatureId = f.id()
            else:
                newSelectedFeatures.append(f.id())

                newSelectedFeatureList.append(f)

        if (singleSelect and foundSingleFeature):
            newSelectedFeatures.append(closestFeatureId)
            featIter = vlayer.getFeatures(QgsFeatureRequest(closestFeatureId))
            for feat in featIter:
                newSelectedFeatureList.append(feat)

        if (doDifference):
            layerSelectedFeatures = vlayer.selectedFeaturesIds()
            deselectedFeatures = []
            selectedFeatures = []
            for i in newSelectedFeatures.reverse():
                if i in layerSelectedFeatures:
                    deselectedFeatures.append(i)
                else:
                    selectedFeatures.append(i)

            vlayer.modifySelection(selectedFeatures, deselectedFeatures)
        else:
            vlayer.setSelectedFeatures(newSelectedFeatures)

        QApplication.restoreOverrideCursor()
        return newSelectedFeatureList
def split_line_at_points(
    polyline_input,
    point_features,
    point_feature_id_field="id",
    start_node_id=None,
    end_node_id=None,
):
    """Split line at points

    Args:
        polyline (QgsPolyline):
        point_features (iteratable object of QgsFeature or list of dictonaries with id and geometry ('geom'):
        point_feature_id_field (str): fieldname if the id field of the point_features
        start_node_id (str or int): node id of point at begin of polyline
        end_node_id (str or int): node id of point at end of polyline

    Returns:
         (list of dict): Splitted polyline into parts as dictonary with:
                geom: Polyline geometry
                start_node_id: id of node at starting point of line
                end_node_id: id of node at end point of line
                distance at line: is distance of original line at the begin of this line part

    """

    snap_points = []

    source_crs = QgsCoordinateReferenceSystem(4326)
    dest_crs = QgsCoordinateReferenceSystem(3857)

    transform = QgsCoordinateTransform(source_crs, dest_crs,
                                       QgsProject.instance())
    transform_back = QgsCoordinateTransform(dest_crs, source_crs,
                                            QgsProject.instance())

    polyline = QgsGeometry(polyline_input)
    polyline.transform(transform)

    for point in point_features:
        if type(point) == QgsFeature:
            point = {
                point_feature_id_field: point[point_feature_id_field],
                "geom": point.geometry(),
            }

        if hasattr(point["geom"], "asPoint"):
            geom = point["geom"].asPoint()
        else:
            geom = point["geom"]

        geom = QgsGeometry.fromPointXY(geom)
        geom.transform(transform)
        geom = geom.asPoint()

        closest_seg = polyline.closestSegmentWithContext(geom)
        # get nearest point (related to the point) on the line
        point_on_line = closest_seg[1]
        point_geom_on_line = QgsPoint(point_on_line[0], point_on_line[1])

        # get nr of vertex (at the end of the line where the closest point is
        # found
        end_vertex_nr = closest_seg[2]
        start_vertex_nr = end_vertex_nr - 1

        p1 = polyline.asPolyline()[start_vertex_nr]  # first vertex
        p2 = point_geom_on_line

        distance_on_subline = math.hypot(p2.x() - p1.x(), p2.y() - p1.y())

        snap_points.append((
            start_vertex_nr,
            distance_on_subline,
            point_geom_on_line,
            point[point_feature_id_field],
        ))

    # order on vertex nr and if same vertex nr on distance
    snap_points.sort(key=lambda x: x[1])
    snap_points.sort(key=lambda x: x[0])

    # create line parts
    line_parts = []
    line_points = []
    start_point_id = start_node_id
    total_line_distance = 0

    for i, vertex in enumerate(polyline.asPolyline()):
        line_points.append(QgsPoint(vertex[0], vertex[1]))

        # get points after this vertex
        split_points_on_segment = [p for p in snap_points if p[0] == i]
        for point in split_points_on_segment:
            # only add another point if point is not equal to last vertex
            # todo: throw error when at begin or end vertex of original line?
            # todo: what to do of multiple points on same location?
            line_points.append(point[2])
            geom = QgsGeometry.fromPolyline(line_points)

            # length, unit_type = d.convertMeasurement(
            #     d.computeDistance(line_points),
            #     Qgis.Meters, Qgis.Meters, False)  # Qgis.Degrees

            length = geom.length()

            # add line parts
            line_parts.append({
                "geom": geom.transform(transform_back),
                "start_point_id": start_point_id,
                "end_point_id": point[3],
                "distance_at_line": total_line_distance,
                "length": length,
            })
            # create starting point of new line
            line_points = [point[2]]
            start_point_id = point[3]
            total_line_distance += length

    # last part of the line
    geom = QgsGeometry.fromPolyline(line_points)
    length = geom.length()
    # length, something = d.convertMeasurement(
    #     d.computeDistance(line_points),
    #     Qgis.Meters, Qgis.Meters, False)

    line_parts.append({
        "geom": geom,
        "start_point_id": start_point_id,
        "end_point_id": end_node_id,
        "distance_at_line": total_line_distance,
        "length": length,
    })

    return line_parts
Ejemplo n.º 20
0
    def do_indexjoin(self, feat):
        '''Find the nearest neigbour using an index, if possible

        Parameter: feat -- The feature for which a neighbour is
                           sought
        '''
        infeature = feat
        infeatureid = infeature.id()
        inputgeom = QgsGeometry(infeature.geometry())
        # Shall approximate input geometries be used?
        if self.approximateinputgeom:
            # Use the centroid as the input geometry
            inputgeom = QgsGeometry(infeature.geometry()).centroid()
        # Check if the coordinate systems are equal, if not,
        # transform the input feature!
        if (self.inpvl.crs() != self.joinvl.crs()):
            try:
                inputgeom.transform(QgsCoordinateTransform(
                    self.inpvl.crs(), self.joinvl.crs()))
            except:
                import traceback
                self.error.emit(self.tr('CRS Transformation error!') +
                                ' - ' + traceback.format_exc())
                self.abort = True
                return
        nnfeature = None
        mindist = float("inf")
        ## Find the closest feature!
        if (self.approximateinputgeom or
                self.inpvl.wkbType() == QGis.WKBPoint or
                self.inpvl.wkbType() == QGis.WKBPoint25D):
            # The input layer's geometry type is point, or shall be
            # approximated to point (centroid).
            # Then a join index will always be used.
            if (self.usejoinlayerapprox or
                    self.joinvl.wkbType() == QGis.WKBPoint or
                    self.joinvl.wkbType() == QGis.WKBPoint25D):
                # The join layer's geometry type is point, or the
                # user wants approximate join geometries to be used.
                # Then the join index nearest neighbour function can
                # be used without refinement.
                if self.selfjoin:
                    # Self join!
                    # Have to get the two nearest neighbours
                    nearestids = self.joinlind.nearestNeighbor(
                                             inputgeom.asPoint(), 2)
                    if nearestids[0] == infeatureid and len(nearestids) > 1:
                        # The first feature is the same as the input
                        # feature, so choose the second one
                        nnfeature = self.joinvl.getFeatures(
                            QgsFeatureRequest(nearestids[1])).next()
                    else:
                        # The first feature is not the same as the
                        # input feature, so choose it
                        nnfeature = self.joinvl.getFeatures(
                            QgsFeatureRequest(nearestids[0])).next()
                    ## Pick the second closest neighbour!
                    ## (the first is supposed to be the point itself)
                    ## Should we check for coinciding points?
                    #nearestid = self.joinlind.nearestNeighbor(
                    #    inputgeom.asPoint(), 2)[1]
                    #nnfeature = self.joinvl.getFeatures(
                    #    QgsFeatureRequest(nearestid)).next()
                else:
                    # Not a self join, so we can search for only the
                    # nearest neighbour (1)
                    nearestid = self.joinlind.nearestNeighbor(
                                           inputgeom.asPoint(), 1)[0]
                    nnfeature = self.joinvl.getFeatures(
                                 QgsFeatureRequest(nearestid)).next()
                mindist = inputgeom.distance(nnfeature.geometry())
            elif (self.joinvl.wkbType() == QGis.WKBPolygon or
                  self.joinvl.wkbType() == QGis.WKBPolygon25D or
                  self.joinvl.wkbType() == QGis.WKBLineString or
                  self.joinvl.wkbType() == QGis.WKBLineString25D):
                # Use the join layer index to speed up the join when
                # the join layer geometry type is polygon or line
                # and the input layer geometry type is point or an
                # approximation (point)
                nearestindexid = self.joinlind.nearestNeighbor(
                    inputgeom.asPoint(), 1)[0]
                # Check for self join
                if self.selfjoin and nearestindexid == infeatureid:
                    # Self join and same feature, so get the two
                    # first two neighbours
                    nearestindexes = self.joinlind.nearestNeighbor(
                                             inputgeom.asPoint(), 2)
                    nearestindexid = nearestindexes[0]
                    if (nearestindexid == infeatureid and
                                  len(nearestindexes) > 1):
                        nearestindexid = nearestindexes[1]
                nnfeature = self.joinvl.getFeatures(
                    QgsFeatureRequest(nearestindexid)).next()
                mindist = inputgeom.distance(nnfeature.geometry())
                px = inputgeom.asPoint().x()
                py = inputgeom.asPoint().y()
                closefids = self.joinlind.intersects(QgsRectangle(
                    px - mindist,
                    py - mindist,
                    px + mindist,
                    py + mindist))
                for closefid in closefids:
                    if self.abort is True:
                        break
                    # Check for self join and same feature
                    if self.selfjoin and closefid == infeatureid:
                        continue
                    closef = self.joinvl.getFeatures(
                        QgsFeatureRequest(closefid)).next()
                    thisdistance = inputgeom.distance(closef.geometry())
                    if thisdistance < mindist:
                        mindist = thisdistance
                        nnfeature = closef
                    if mindist == 0:
                        break
            else:
                # Join with no index use
                # Go through all the features from the join layer!
                for inFeatJoin in self.joinf:
                    if self.abort is True:
                        break
                    joingeom = QgsGeometry(inFeatJoin.geometry())
                    thisdistance = inputgeom.distance(joingeom)
                    # If the distance is 0, check for equality of the
                    # features (in case it is a self join)
                    if (thisdistance == 0 and self.selfjoin and
                            infeatureid == inFeatJoin.id()):
                        continue
                    if thisdistance < mindist:
                        mindist = thisdistance
                        nnfeature = inFeatJoin
                    # For 0 distance, settle with the first feature
                    if mindist == 0:
                        break
        else:
            # non-simple point input geometries (could be multipoint)
            if (self.nonpointexactindex):
                # Use the spatial index on the join layer (default).
                # First we do an approximate search
                # Get the input geometry centroid
                centroid = QgsGeometry(infeature.geometry()).centroid()
                centroidgeom = centroid.asPoint()
                # Find the nearest neighbour (index geometries only)
                nearestid = self.joinlind.nearestNeighbor(centroidgeom, 1)[0]
                # Check for self join
                if self.selfjoin and nearestid == infeatureid:
                    # Self join and same feature, so get the two
                    # first two neighbours
                    nearestindexes = self.joinlind.nearestNeighbor(
                        centroidgeom, 2)
                    nearestid = nearestindexes[0]
                    if nearestid == infeatureid and len(nearestindexes) > 1:
                        nearestid = nearestindexes[1]
                nnfeature = self.joinvl.getFeatures(
                    QgsFeatureRequest(nearestid)).next()
                mindist = inputgeom.distance(nnfeature.geometry())
                # Calculate the search rectangle (inputgeom BBOX
                inpbbox = infeature.geometry().boundingBox()
                minx = inpbbox.xMinimum() - mindist
                maxx = inpbbox.xMaximum() + mindist
                miny = inpbbox.yMinimum() - mindist
                maxy = inpbbox.yMaximum() + mindist
                #minx = min(inpbbox.xMinimum(), centroidgeom.x() - mindist)
                #maxx = max(inpbbox.xMaximum(), centroidgeom.x() + mindist)
                #miny = min(inpbbox.yMinimum(), centroidgeom.y() - mindist)
                #maxy = max(inpbbox.yMaximum(), centroidgeom.y() + mindist)
                searchrectangle = QgsRectangle(minx, miny, maxx, maxy)
                # Fetch the candidate join geometries
                closefids = self.joinlind.intersects(searchrectangle)
                # Loop through the geometries and choose the closest
                # one
                for closefid in closefids:
                    if self.abort is True:
                        break
                    # Check for self join and identical feature
                    if self.selfjoin and closefid == infeatureid:
                        continue
                    closef = self.joinvl.getFeatures(
                        QgsFeatureRequest(closefid)).next()
                    thisdistance = inputgeom.distance(closef.geometry())
                    if thisdistance < mindist:
                        mindist = thisdistance
                        nnfeature = closef
                    if mindist == 0:
                        break
            else:
                # Join with no index use
                # Check all the features of the join layer!
                mindist = float("inf")  # should not be necessary
                for inFeatJoin in self.joinf:
                    if self.abort is True:
                        break
                    joingeom = QgsGeometry(inFeatJoin.geometry())
                    thisdistance = inputgeom.distance(joingeom)
                    # If the distance is 0, check for equality of the
                    # features (in case it is a self join)
                    if (thisdistance == 0 and self.selfjoin and
                            infeatureid == inFeatJoin.id()):
                        continue
                    if thisdistance < mindist:
                        mindist = thisdistance
                        nnfeature = inFeatJoin
                    # For 0 distance, settle with the first feature
                    if mindist == 0:
                        break
        if not self.abort:
            atMapA = infeature.attributes()
            atMapB = nnfeature.attributes()
            attrs = []
            attrs.extend(atMapA)
            attrs.extend(atMapB)
            attrs.append(mindist)

            outFeat = QgsFeature()
            # Use the original input layer geometry!:
            outFeat.setGeometry(QgsGeometry(infeature.geometry()))
            # Use the modified input layer geometry (could be
            # centroid)
            #outFeat.setGeometry(QgsGeometry(inputgeom))
            outFeat.setAttributes(attrs)
            self.calculate_progress()
            self.features.append(outFeat)
Ejemplo n.º 21
0
    def processAlgorithm(self, parameters, context, feedback):
        if DEBUG_MODE:
            logMessage("processAlgorithm(): {}".format(
                self.__class__.__name__))

        source = self.parameterAsSource(parameters, self.INPUT, context)
        source_layer = self.parameterAsLayer(parameters, self.INPUT, context)
        title_field = self.parameterAsString(parameters, self.TITLE_FIELD,
                                             context)
        cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context)
        fixed_scale = self.parameterAsEnum(parameters, self.SCALE,
                                           context)  # == 1
        buf = self.parameterAsDouble(parameters, self.BUFFER, context)
        tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context)
        orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT,
                                              context)
        out_dir = self.parameterAsString(parameters, self.OUTPUT, context)

        mapSettings = self.controller.settings.mapSettings
        baseExtent = self.controller.settings.baseExtent
        rotation = mapSettings.rotation()
        orig_size = mapSettings.outputSize()

        if cf_filter:
            #TODO: FIX ME
            #cf_layer = QgsMemoryProviderUtils.createMemoryLayer("current feature",
            #                                                    source_layer.fields(),
            #                                                    source_layer.wkbType(),
            #                                                    source_layer.crs())

            doc = QDomDocument("qgis")
            source_layer.exportNamedStyle(doc)

            orig_layers = mapSettings.layers()

        total = source.featureCount()
        for current, feature in enumerate(source.getFeatures()):
            if feedback.isCanceled():
                break

            if cf_filter:
                cf_layer = QgsMemoryProviderUtils.createMemoryLayer(
                    "current feature", source_layer.fields(),
                    source_layer.wkbType(), source_layer.crs())
                cf_layer.startEditing()
                cf_layer.addFeature(feature)
                cf_layer.commitChanges()

                cf_layer.importNamedStyle(doc)

                layers = [
                    cf_layer if lyr == source_layer else lyr
                    for lyr in orig_layers
                ]
                mapSettings.setLayers(layers)

            title = feature.attribute(title_field)
            feedback.setProgressText("({}/{}) Exporting {}...".format(
                current + 1, total, title))

            # extent
            geometry = QgsGeometry(feature.geometry())
            geometry.transform(self.transform)
            center = geometry.centroid().asPoint()

            if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry:
                tex_height = orig_tex_height or int(
                    tex_width * orig_size.height() / orig_size.width())
                rect = RotatedRect(center, baseExtent.width(),
                                   baseExtent.width() * tex_height / tex_width,
                                   rotation).scale(1 + buf / 100)
            else:
                geometry.rotate(rotation, center)
                rect = geometry.boundingBox().scaled(1 + buf / 100)
                center = RotatedRect.rotatePoint(rect.center(), rotation,
                                                 center)
                if orig_tex_height:
                    tex_height = orig_tex_height
                    tex_ratio = tex_width / tex_height
                    rect_ratio = rect.width() / rect.height()
                    if tex_ratio > rect_ratio:
                        rect = RotatedRect(center,
                                           rect.height() * tex_ratio,
                                           rect.height(), rotation)
                    else:
                        rect = RotatedRect(center, rect.width(),
                                           rect.width() / tex_ratio, rotation)
                else:
                    # fit to buffered geometry bounding box
                    rect = RotatedRect(center, rect.width(), rect.height(),
                                       rotation)
                    tex_height = tex_width * rect.height() / rect.width()

            rect.toMapSettings(mapSettings)
            mapSettings.setOutputSize(QSize(tex_width, tex_height))

            self.controller.settings.setMapSettings(mapSettings)

            self.export(title, out_dir, feedback)

            feedback.setProgress(int(current / total * 100))

        return {}
Ejemplo n.º 22
0
    def in_mask(self, feature, srid=None):
        if feature is None:  # expression overview
            return False

        if self.layer is None:
            return False

        try:
            # layer is not None but destroyed ?
            self.layer.id()
        except:
            self.reset_mask_layer()
            return False

        # mask layer empty due to unloaded memlayersaver plugin > no filtering
        if self.layer.featureCount() == 0:
            return True

        mask_geom, bbox = self.mask_geometry()
        geom = QgsGeometry(feature.geometry())
        if not geom.isGeosValid():
            geom = geom.buffer(0.0, 1)

        if geom is None:
            return False

        if srid is not None and self.layer.crs().postgisSrid() != srid:
            src_crs = QgsCoordinateReferenceSystem(srid)
            dest_crs = self.layer.crs()
            xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance())
            try:
                geom.transform(xform)
            except:
                # transformation error. Check layer projection.
                pass

        if geom.type() == QgsWkbTypes.PolygonGeometry:
            if self.parameters.polygon_mask_method == 2 and not self.has_point_on_surface:
                self.parameters.polygon_mask_method = 1

            if self.parameters.polygon_mask_method == 0:
                # this method can only work when no geometry simplification is involved
                return (mask_geom.overlaps(geom) or mask_geom.contains(geom))
            elif self.parameters.polygon_mask_method == 1:
                # the fastest method, but with possible inaccuracies
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.centroid())
            elif self.parameters.polygon_mask_method == 2:
                # will always work
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.pointOnSurface())
            else:
                return False
        elif geom.type() == QgsWkbTypes.LineGeometry:
            if self.parameters.line_mask_method == 0:
                return mask_geom.intersects(geom)
            elif self.parameters.line_mask_method == 1:
                return mask_geom.contains(geom)
            else:
                return False
        elif geom.type() == QgsWkbTypes.PointGeometry:
            return mask_geom.intersects(geom)
        else:
            return False
Ejemplo n.º 23
0
    def export_geometry_info(self):
        ellips = None
        crs = None
        coordTransform = None

        # calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal
        if self.myCalcType == 2:
            settings = QSettings()
            ellips = settings.value("/qgis/measure/ellipsoid", "WGS84")
            crs = self.vlayer.crs().srsid()
        elif self.myCalcType == 1:
            mapCRS = self.parent.iface.mapCanvas().mapRenderer().destinationCrs()
            layCRS = self.vlayer.crs()
            coordTransform = QgsCoordinateTransform(layCRS, mapCRS)

        inFeat = QgsFeature()
        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        nElement = 0

        vprovider = self.vlayer.dataProvider()
        self.emit(SIGNAL("runStatus( PyQt_PyObject )"), 0)
        self.emit(SIGNAL("runRange( PyQt_PyObject )"), (0, vprovider.featureCount()))

        (fields, index1, index2) = self.checkMeasurementFields(self.vlayer, not self.writeShape)

        if self.writeShape:
            writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields,
                                         vprovider.geometryType(), vprovider.crs())

        fit = vprovider.getFeatures()
        while fit.nextFeature(inFeat):
            self.emit(SIGNAL("runStatus( PyQt_PyObject )"), nElement)
            nElement += 1
            inGeom = inFeat.geometry()

            if self.myCalcType == 1:
                inGeom.transform(coordTransform)

            (attr1, attr2) = self.simpleMeasure(inGeom, self.myCalcType, ellips, crs)

            if self.writeShape:
                outFeat.setGeometry(inGeom)
                atMap = inFeat.attributes()
                maxIndex = index1 if index1 > index2 else index2
                if maxIndex >= len(atMap):
                    atMap += [""] * (index2 + 1 - len(atMap))
                atMap[index1] = attr1
                if index1 != index2:
                    atMap[index2] = attr2
                outFeat.setAttributes(atMap)
                writer.addFeature(outFeat)
            else:
                changeMap = {}
                changeMap[inFeat.id()] = {}
                changeMap[inFeat.id()][index1] = attr1
                if index1 != index2:
                    changeMap[inFeat.id()][index2] = attr2
                vprovider.changeAttributeValues(changeMap)
                self.vlayer.updateFields()

        if self.writeShape:
            del writer

        return True
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer, context)
        preserve_final_pt = self.parameterAsBool(parameters, self.PrmPreserveFinalPoint, context)
        min_distance = self.parameterAsDouble(parameters, self.PrmMinDistance, context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context)

        # Get the minimum distance in meters
        min_distance = min_distance * conversionToMeters(units)

        wkbtype = source.wkbType()

        num_bad = 0
        if QgsWkbTypes.geometryType(wkbtype) != QgsWkbTypes.LineGeometry:
            feedback.reportError(tr("Please select a valid line layer."))
            return({})
            
        layercrs = source.sourceCrs()
        (sink, dest_id) = self.parameterAsSink(
            parameters, self.PrmOutputLayer, context, source.fields(), wkbtype, layercrs)

        if layercrs != epsg4326:
            transto4326 = QgsCoordinateTransform(layercrs, epsg4326, QgsProject.instance())
            transfrom4326 = QgsCoordinateTransform(epsg4326, layercrs, QgsProject.instance())

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        iterator = source.getFeatures()
        num_bad = 0
        for cnt, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            geom = feature.geometry()
            # Force the geometry to be in degrees so that we can use the geodesic algorithms
            if layercrs != epsg4326:
                results = geom.transform(transto4326)
                
            num_parts = geom.constGet().partCount()
            # feedback.pushInfo('num_parts {}'.format(num_parts))
            try:
                fline = QgsFeature()
                fgeom = QgsGeometry()
                is_valid = False
                for part in geom.constGet().parts():
                    vertex_cnt = part.vertexCount()
                    # feedback.pushInfo('vertex_cnt {}'.format(vertex_cnt))
                    if vertex_cnt <= 1: # line of 1 or less points is invalid
                        continue
                    pts = []
                    for vcnt, vertex in enumerate(part.vertices()):
                        if vcnt == 0:
                            # This is the first point so we will save it
                            pts.append(vertex)
                            ptLast = vertex
                        else:
                            ptNext = vertex
                            gline = geod.InverseLine(ptLast.y(), ptLast.x(), ptNext.y(), ptNext.x())
                            if gline.s13 >= min_distance:
                                pts.append(ptNext)
                                ptLast = ptNext
                            elif (vcnt == vertex_cnt - 1) and preserve_final_pt:
                                if len(pts) >= 2:
                                    # We have two or more points already on our pts list. Check to see if
                                    # the next to last entry distance and the end point are greater than the 
                                    # the minimum distance. If so replace the last entry with this one else
                                    # because the user has selected to preserve the last end point we will
                                    # accept the end point.
                                    gline = geod.InverseLine(pts[-2].y(), pts[-2].x(), ptNext.y(), ptNext.x())
                                    if gline.s13 >= min_distance:
                                        pts[-1] = ptNext
                                    else:
                                        pts.append(ptNext)
                                elif len(pts) == 1:
                                    # We have only the beginning point of the line and because the user has
                                    # selected that the last point to be preserved we will allow a distance less
                                    # than the minimum so that the line can be preserved.
                                    pts.append(ptNext)
                    if len(pts) > 1: # There must be more than one point to make a valid line
                        fgeom.addPoints(pts, QgsWkbTypes.LineGeometry)
                        is_valid = True
                if is_valid: # Only save the feature if it is valid
                    fline.setAttributes(feature.attributes())
                    if layercrs != epsg4326:
                        fgeom.transform(transfrom4326)
                    fline.setGeometry(fgeom)
                    sink.addFeature(fline)
                else:
                    num_bad += 1
            except Exception:
                '''s = traceback.format_exc()
                feedback.pushInfo(s)'''
                num_bad += 1
            
            feedback.setProgress(int(cnt * total))

        if num_bad > 0:
            feedback.pushInfo(tr("{} out of {} features from input layer were invalid and were skipped.".format(num_bad, source.featureCount())))

        return {self.PrmOutputLayer: dest_id}
Ejemplo n.º 25
0
    def features(self, request=None, clipGeom=None):
        settings = self.writer.settings
        mapTo3d = settings.mapTo3d()
        baseExtent = settings.baseExtent
        baseExtentGeom = baseExtent.geometry()
        rotation = baseExtent.rotation()
        prop = self.prop

        useZ = prop.useZ()
        if useZ:
            srs_from = osr.SpatialReference()
            srs_from.ImportFromProj4(str(self.layer.crs().toProj4()))
            srs_to = osr.SpatialReference()
            srs_to.ImportFromProj4(str(self.writer.settings.crs.toProj4()))

            ogr_transform = osr.CreateCoordinateTransformation(
                srs_from, srs_to)
            clipGeomWkb = clipGeom.asWkb() if clipGeom else None
            ogr_clipGeom = ogr.CreateGeometryFromWkb(
                clipGeomWkb) if clipGeomWkb else None

        else:
            # z_func: function to get elevation at given point (x, y) on surface
            if prop.isHeightRelativeToDEM():
                if self.geomType == QGis.Polygon and prop.type_index == 1:  # Overlay
                    z_func = lambda x, y: 0
                else:
                    # get elevation from DEM
                    z_func = lambda x, y: self.writer.demProvider.readValue(
                        x, y)
            else:
                z_func = lambda x, y: 0

        request = request or QgsFeatureRequest()
        for f in self.layer.getFeatures(request):
            geometry = f.geometry()
            if geometry is None:
                logMessage("null geometry skipped")
                continue

            # coordinate transformation - layer crs to project crs
            geom = QgsGeometry(geometry)
            if geom.transform(self.transform) != 0:
                logMessage("Failed to transform geometry")
                continue

            # check if geometry intersects with the base extent (rotated rect)
            if rotation and not baseExtentGeom.intersects(geom):
                continue

            # create feature
            feat = Feature(self.writer, self, f)

            # transform_func: function to transform the map coordinates to 3d coordinates
            relativeHeight = prop.relativeHeight(f)

            def transform_func(x, y, z):
                return mapTo3d.transform(x, y, z + relativeHeight)

            if useZ:
                ogr_geom = ogr.CreateGeometryFromWkb(geometry.asWkb())

                # transform geometry from layer CRS to project CRS
                if ogr_geom.Transform(ogr_transform) != 0:
                    logMessage("Failed to transform geometry")
                    continue

                # clip geometry
                if ogr_clipGeom and self.geomType == QGis.Line:
                    ogr_geom = ogr_geom.Intersection(ogr_clipGeom)
                    if ogr_geom is None:
                        continue

                # check if geometry is empty
                if ogr_geom.IsEmpty():
                    logMessage("empty geometry skipped")
                    continue

                feat.geom = self.geomClass.fromOgrGeometry25D(
                    ogr_geom, transform_func)

            else:
                # clip geometry
                if clipGeom and self.geomType in [QGis.Line, QGis.Polygon]:
                    geom = geom.intersection(clipGeom)
                    if geom is None:
                        continue

                # check if geometry is empty
                if geom.isGeosEmpty():
                    logMessage("empty geometry skipped")
                    continue

                if self.geomType == QGis.Polygon:
                    feat.geom = self.geomClass.fromQgsGeometry(
                        geom, z_func, transform_func, self.hasLabel())
                    if prop.type_index == 1 and prop.isHeightRelativeToDEM(
                    ):  # Overlay and relative to DEM
                        feat.geom.splitPolygon(self.writer.triangleMesh())

                else:
                    feat.geom = self.geomClass.fromQgsGeometry(
                        geom, z_func, transform_func)

            if feat.geom is None:
                continue

            yield feat
Ejemplo n.º 26
0
def multi_buffering(layer, radii, callback=None):
    """Buffer a vector layer using many buffers (for volcanoes or rivers).

    This processing algorithm will keep the original attribute table and
    will add a new one for the hazard class name according to
    safe.definitions.fields.hazard_value_field.

    radii = OrderedDict()
    radii[500] = 'high'
    radii[1000] = 'medium'
    radii[2000] = 'low'

    Issue https://github.com/inasafe/inasafe/issues/3185

    :param layer: The layer to polygonize.
    :type layer: QgsVectorLayer

    :param radii: A dictionary of radius.
    :type radii: OrderedDict

    :param callback: A function to all to indicate progress. The function
        should accept params 'current' (int), 'maximum' (int) and 'step' (str).
        Defaults to None.
    :type callback: function

    :return: The buffered vector layer.
    :rtype: QgsVectorLayer
    """
    # Layer output
    output_layer_name = buffer_steps['output_layer_name']
    processing_step = buffer_steps['step_name']

    input_crs = layer.crs()
    feature_count = layer.featureCount()

    fields = layer.fields()
    # Set the new hazard class field.
    new_field = create_field_from_definition(hazard_class_field)
    fields.append(new_field)
    # Set the new buffer distances field.
    new_field = create_field_from_definition(buffer_distance_field)
    fields.append(new_field)

    buffered = create_memory_layer(output_layer_name, QGis.Polygon, input_crs,
                                   fields)
    data_provider = buffered.dataProvider()

    # Reproject features if needed into UTM if the layer is in 4326.
    if layer.crs().authid() == 'EPSG:4326':
        center = layer.extent().center()
        utm = QgsCoordinateReferenceSystem(
            get_utm_epsg(center.x(), center.y(), input_crs))
        transform = QgsCoordinateTransform(layer.crs(), utm)
        reverse_transform = QgsCoordinateTransform(utm, layer.crs())
    else:
        transform = None
        reverse_transform = None

    for i, feature in enumerate(layer.getFeatures()):
        geom = QgsGeometry(feature.geometry())

        if transform:
            geom.transform(transform)

        inner_ring = None

        for radius in radii:
            attributes = feature.attributes()

            # We add the hazard value name to the attribute table.
            attributes.append(radii[radius])
            # We add the value of buffer distance to the attribute table.
            attributes.append(radius)

            circle = geom.buffer(radius, 30)

            if inner_ring:
                circle.addRing(inner_ring)

            inner_ring = circle.asPolygon()[0]

            new_feature = QgsFeature()
            if reverse_transform:
                circle.transform(reverse_transform)

            new_feature.setGeometry(circle)
            new_feature.setAttributes(attributes)

            data_provider.addFeatures([new_feature])

        if callback:
            callback(current=i, maximum=feature_count, step=processing_step)

    # We transfer keywords to the output.
    buffered.keywords = layer.keywords
    buffered.keywords['layer_geometry'] = 'polygon'
    buffered.keywords['layer_purpose'] = layer_purpose_hazard['key']
    buffered.keywords['inasafe_fields'][hazard_class_field['key']] = (
        hazard_class_field['field_name'])

    check_layer(buffered)
    return buffered
Ejemplo n.º 27
0
    def run(self):

        # Converter escala textual para numérica (denominador)
        escala = self.escalaAvaliacao.currentText() # '1:100.000'
        escalaAval = escala.split(':')[1].replace('.','')    
        escalaAval = int(escalaAval)
        
        self.canvas.zoomScale(escalaAval)

        listaHomologosXY = {} # dicionario yx.
        listaHomologosZ = {} # dicionario z.    
       
        # Raio definido
        raio = self.spinBox.value()

        # Layers selecionados
        layer1 = self.referenciaComboBox.currentLayer()
        layer2 = self.avaliacaoComboBox.currentLayer()

        # Teste para identificar se esta setado.
        XY = False 
        Z = False

        if self.xy.isChecked():
            XY = True 
        if self.z.isChecked(): 
            Z = True

        # Troca de referência CRS para uma que utiliza medição em metros (3857).
        source1 = layer1.crs()
        source2 = layer2.crs()
        dest = QgsCoordinateReferenceSystem(3857)

        tr1 = QgsCoordinateTransform(source1, dest)
        tr2 = QgsCoordinateTransform(source2, dest)

        lista1 = [feat1 for feat1 in layer1.getFeatures()]
        lista2 = [feat2 for feat2 in layer2.getFeatures()]
        lista3 = []
         
        spIndex1 = QgsSpatialIndex()
        neighbour = QgsFeature()
        
        for feat1 in lista1: 

            spIndex1.insertFeature(feat1)  # transforma features em indices espaciais
            geom1 = QgsGeometry(feat1.geometry()) 
            geom1.transform(tr1)        
            raioTeste = raio 
            neighbour = None
            encontrado =  False
                        
            for feat2 in lista2:

                pt = feat2.geometry().asPoint()
                nearestid = spIndex1.nearestNeighbor(pt, 2)[0] # realiza a analise do vizinho mais próximo, numero de vizinhos é definido no segundo argumento.
                #print nearestid
                request = QgsFeatureRequest().setFilterFid(nearestid)
                geom2 = QgsGeometry(feat2.geometry()) 
                geom2.transform(tr2) 

                if geom1.buffer (raioTeste, 20 ) .contains (geom2):
                     raioTeste = sqrt (geom1.asPoint (). sqrDist (geom2.asPoint ()))
                     neighbour = feat2  
                     encontrado = True
                  
            # apenas pra descobrir se não foi encontrado.
            if encontrado == False: 
                #print u'\nHouve pontos nao encontrados dentro do raio definido.'
                frase = ("<span style='color:purple'>HOUVE PONTOS NAO ENCONTRADOS.</span>")
                lista3.append(frase)
            
            else:
                if XY:
                    listaHomologosXY[int(feat1.id()), int(neighbour.id())] = (raioTeste)
                
                if Z:
                    listaHomologosZ[int(feat1.id()), int(neighbour.id())]  = feat1.geometry().geometry().z() - neighbour.geometry().geometry().z()
                lista2.remove(neighbour)     

        if XY or Z:   
            #print '\nHomologos: \n', listaHomologosXY.keys()
            distAcum = 0
             
            resultado2 = "<span style='color:orange'>DISTANCIA ENTRE PONTOS: </span>",[ round(v, 2) for v in listaHomologosXY.values()]
            resultado1 = "<span style='color:orange'>PONTOS HOMOLOGOS: </span>",listaHomologosXY.keys()
            #print '\nDistancia entre pontos Homologados:\n',resultado2
            lista3.append(resultado1)
            lista3.append(resultado2)      
        
        if XY: 
            distAcum = 0
            for valorXY in listaHomologosXY.values():
                distAcum += valorXY    

            resultado = int(distAcum / len(listaHomologosXY))
            #print '\nDistancia media:\n', round(resultado,2)  
            b = "<span style='color:orange'>DISTANCIA MEDIA: </span>", round(resultado,2)
            lista3.append(b)
        
        if Z:
            zAcum = 0     
            for valorZ in listaHomologosZ.values(): 
                zAcum += valorZ

            resultado = int(zAcum / len(listaHomologosZ)) 
            #print '\nDiferenca media de elevacao: \n', round(resultado,3)
            a = "<span style='color:orange'>DISTANCIA MEDIA DE ELEVACAO: </span>", round(resultado,3)
            lista3.append(a)

        # Formatação para apresentar QmessageBox de forma bem distribuida.
        message = u""
        one_data = u"<p>{0}</p>"
        two_data = u"<p>{0} {1}</p>"
        for data in lista3:
            message += one_data.format(data) if type(data) == str else two_data.format(data[0], data[1])
  
        QMessageBox.about(self, "RESULTADO: ", message )  
Ejemplo n.º 28
0
    def updateNavigationInfo(self):
        if self.gpsConnection is None:
            self.setMessage(self.tr("Cannot connect to GPS"))
            return
        try:
            gpsinfo = self.gpsConnection.currentGPSInformation()
        except RuntimeError:
            # if the GPS is closed in KADAS main interface, stop the navigation
            self.stopNavigation()
            return
        if gpsinfo is None:
            self.setMessage(self.tr("Cannot connect to GPS"))
            return
        layer = self.iface.activeLayer()
        LOG.debug("Debug: type(layer) = {}".format(type(layer)))
        point = QgsPointXY(gpsinfo.longitude, gpsinfo.latitude)
        if gpsinfo.speed > GPS_MIN_SPEED:
            # if we are moving, it is better for the user experience to
            # project the current point using the speed vector instead
            # of using 'point' directly, otherwise we get to feel of being
            # "behind the current position"
            qgsdistance = QgsDistanceArea()
            qgsdistance.setSourceCrs(
                QgsCoordinateReferenceSystem(4326),
                QgsProject.instance().transformContext(),
            )
            qgsdistance.setEllipsoid(qgsdistance.sourceCrs().ellipsoidAcronym())
            point = qgsdistance.computeSpheroidProject(
                point,
                (gpsinfo.speed / SPEED_DIVIDE_BY) * REFRESH_RATE_S,
                math.radians(gpsinfo.direction),
            )
        origCrs = QgsCoordinateReferenceSystem(4326)
        canvasCrs = self.iface.mapCanvas().mapSettings().destinationCrs()
        self.transform = QgsCoordinateTransform(
            origCrs, canvasCrs, QgsProject.instance()
        )

        if (
            isinstance(layer, QgsVectorLayer)
            and layer.geometryType() == QgsWkbTypes.LineGeometry
        ):
            feature = next(layer.getFeatures(), None)
            if feature:
                geom = feature.geometry()
                layer = self.getOptimalRouteLayerForGeometry(geom)
                if layer is not None:
                    rubbergeom = QgsGeometry(layer.geom)
                    rubbergeom.transform(self.transform)
                    self.rubberband.setToGeometry(rubbergeom)

        if hasattr(layer, "valhalla") and layer.hasRoute():
            try:
                maneuver = layer.maneuverForPoint(point, gpsinfo.speed)
                self.refreshCanvas(maneuver["closest_point"], gpsinfo)
                LOG.debug(maneuver)
            except NotInRouteException:
                self.refreshCanvas(point, gpsinfo)
                self.setMessage(self.tr("You are not on the route"))
                return
            self.setWidgetsVisibility(False)
            html = route_html_template.format(**maneuver)
            self.textBrowser.setHtml(html)
            self.textBrowser.setFixedHeight(self.textBrowser.document().size().height())
            self.setWarnings(maneuver["raw_distleft"])
        # FIXME: we could have some better way of differentiating this...
        elif not isinstance(layer, type(None)):
            if layer.name() != "Routes":
                self.setMessage(
                    self.tr("Select a route or waypoint layer for navigation")
                )
                self.stopNavigation()
                return
            waypoints = self.waypointsFromLayer(self.navLayer)
            if waypoints:
                if self.waypointLayer is None:
                    self.waypointLayer = self.navLayer
                    self.populateWaypoints(waypoints)
                else:
                    self.updateWaypoints()
                waypointItem = (
                    self.listWaypoints.currentItem() or self.listWaypoints.item(0)
                )
                waypoint = waypointItem.point
                instructions = getInstructionsToWaypoint(waypoint, gpsinfo)
                self.setCompass(instructions["heading"], instructions["wpangle"])
                html = waypoint_html_template.format(**instructions)
                self.textBrowser.setHtml(html)
                self.textBrowser.setFixedHeight(
                    self.textBrowser.document().size().height()
                )
                self.labelWaypointName.setText(
                    waypoint_name_html_template.format(name=waypointItem.name)
                )
                self.setWidgetsVisibility(True)
                self.setWarnings(instructions["raw_distleft"])
            else:
                self.setMessage(self.tr("The 'Routes' layer has no waypoints."))
                self.stopNavigation()
                return
        else:
            self.setMessage(self.tr("Select a route or waypoint layer for navigation"))
            self.stopNavigation()
            return
 def reprojectGeometry(self, geom: QgsGeometry) -> QgsGeometry:
     if geom is not None:
         geom.transform(self.transformation, QgsCoordinateTransform.ForwardTransform, self.hasZ)
         return geom
Ejemplo n.º 30
0
    def generateFootprintsForFilmVertical(self):
        self.reloadFpLayer()
        self.reloadCpLayer()

        # Error wenn nur ein punkt vorhanden
        if self.cpLayer.featureCount() > 1:
            caps = self.fpLayer.dataProvider().capabilities()
            if caps & QgsVectorDataProvider.AddFeatures:
                #Get FORM1 from FilmInfoDict
                f1 = self.currentFilmInfoDict["form1"]  # Image height
                f2 = self.currentFilmInfoDict["form2"]  # Image width

                iterFeatures = self.cpLayer.getFeatures()
                iterNext = self.cpLayer.getFeatures()
                existingFootpints = QgsVectorLayerUtils.getValues(
                    self.fpLayer, "bildnummer")[0]
                ft = QgsFeature()
                ftNext = QgsFeature()
                iterNext.nextFeature(ftNext)
                fpFeats = []
                kappasToUpdate = {}
                # iterate over points from CP Layer > LON, LAT
                i = 0
                while iterFeatures.nextFeature(ft):
                    i += 1
                    iterNext.nextFeature(ftNext)
                    p = QgsPointXY(ft.geometry().asPoint())
                    if ft['bildnummer'] in existingFootpints:
                        pPrevGeom = QgsGeometry(ft.geometry())
                        #QMessageBox.warning(None, u"Bild Nummern", u"Footprint für das Bild mit der Nummer {0} wurde bereits erstellt.".format(ft['BILD']))
                        continue
                    if i == 1:
                        pPrevGeom = QgsGeometry(ftNext.geometry())
                    #if iterNext.isClosed():
                    #    #use pPrev as pNext
                    #    pNext = QgsPoint(pPrev)
                    #else:
                    #    pNext = QgsPoint(ftNext.geometry().asPoint())

                    #kappa = p.azimuth(pPrev)

                    #kappa = p.azimuth(pNext)

                    # d = math.sqrt(2*((f1/2 * ft['MASS']/1000)**2))
                    d1 = f1 / 2 * ft['massstab'] / 1000
                    d2 = f2 / 2 * ft['massstab'] / 1000
                    #QMessageBox.warning(None, u"Bild Nummern", "{0}".format(d))

                    calcCrs = QgsCoordinateReferenceSystem()
                    calcCrs.createFromProj4(self.Proj4Utm(p))
                    ctF = QgsCoordinateTransform(self.cpLayer.crs(), calcCrs,
                                                 QgsProject.instance())

                    cpMetric = QgsGeometry(ft.geometry())
                    cpMetric.transform(ctF)
                    pPrevGeom.transform(ctF)
                    pMetric = QgsPointXY(cpMetric.asPoint())
                    pPrevMetric = QgsPointXY(pPrevGeom.asPoint())
                    kappaMetric = pMetric.azimuth(pPrevMetric)
                    pPrevGeom = QgsGeometry(ft.geometry())
                    left = pMetric.x() - d2
                    bottom = pMetric.y() - d1
                    right = pMetric.x() + d2
                    top = pMetric.y() + d1

                    #R = 6371
                    #D = (d/1000)
                    #cpLat = math.radians(p.y())
                    #cpLon = math.radians(p.x())
                    #urLat = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*math.cos(urBrng) )
                    #urLon = cpLon + math.atan2(math.sin(urBrng)*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(urLat))

                    #top = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R) )
                    #bottom = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*-1 )

                    #lat = math.asin( math.sin(cpLat)*math.cos(D/R) )
                    #right = cpLon + math.atan2(math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat))
                    #left = cpLon + math.atan2(-1*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat))

                    #QMessageBox.warning(None, u"Bild Nummern", "{0}, {1}, {2}, {3}".format(math.degrees(top), math.degrees(bottom), math.degrees(left), math.degrees(right)))

                    #rect = QgsRectangle(math.degrees(left), math.degrees(bottom), math.degrees(right), math.degrees(top))
                    #l = math.degrees(left)
                    #b = math.degrees(bottom)
                    #r = math.degrees(right)
                    #t = math.degrees(top)
                    p1 = QgsGeometry.fromPointXY(QgsPointXY(left, bottom))
                    p2 = QgsGeometry.fromPointXY(QgsPointXY(right, bottom))
                    p3 = QgsGeometry.fromPointXY(QgsPointXY(right, top))
                    p4 = QgsGeometry.fromPointXY(QgsPointXY(left, top))
                    #p1.rotate(kappa+90, p)
                    #p2.rotate(kappa+90, p)
                    #p3.rotate(kappa+90, p)
                    #p4.rotate(kappa+90, p)
                    pol = [[
                        p1.asPoint(),
                        p2.asPoint(),
                        p3.asPoint(),
                        p4.asPoint()
                    ]]
                    geom = QgsGeometry.fromPolygonXY(pol)
                    geom.rotate(kappaMetric, pMetric)
                    #Transform to DestinationCRS
                    ctB = QgsCoordinateTransform(calcCrs, self.fpLayer.crs(),
                                                 QgsProject.instance())
                    geom.transform(ctB)

                    feat = QgsFeature(self.fpLayer.fields())
                    feat.setGeometry(geom)
                    feat.setAttribute('filmnummer', self.currentFilmNumber)
                    feat.setAttribute('bildnummer', ft['bildnummer'])
                    da = QgsDistanceArea()
                    da.setEllipsoid(self.fpLayer.crs().ellipsoidAcronym())
                    feat.setAttribute('shape_length',
                                      da.measurePerimeter(geom))
                    feat.setAttribute('shape_area', da.measureArea(geom))
                    fpFeats.append(feat)

                    # update Kappa in cpLayer
                    kappasToUpdate[ft.id()] = {
                        ft.fieldNameIndex('kappa'): kappaMetric
                    }

                iterFeatures.close()
                iterNext.close()

                resCAVs = self.cpLayer.dataProvider().changeAttributeValues(
                    kappasToUpdate)
                QgsMessageLog.logMessage(
                    f"Kappa Update for {kappasToUpdate}, Success: {resCAVs}",
                    tag="APIS",
                    level=Qgis.Success if resCAVs else Qgis.Critical)

                (res,
                 outFeats) = self.fpLayer.dataProvider().addFeatures(fpFeats)

                self.fpLayer.updateExtents()
                if self.canvas.isCachingEnabled():
                    self.fpLayer.triggerRepaint()
                else:
                    self.canvas.refresh()
            else:
                #Caps
                QMessageBox.warning(None, "Layer Capabilities!",
                                    "Layer Capabilities!")
        else:
            #small feature count
            QMessageBox.warning(
                None, "Footprints",
                "Zum Berechnen der senkrecht Footprint müssen mindestens zwei Bilder kartiert werden!"
            )
Ejemplo n.º 31
0
    def processAlgorithm(self, parameters, context, feedback):
        if DEBUG_MODE:
            logMessage(
                "processAlgorithm(): {}".format(self.__class__.__name__),
                False)

        clayer = self.parameterAsLayer(parameters, self.INPUT, context)
        title_field = self.parameterAsString(parameters, self.TITLE_FIELD,
                                             context)
        cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context)
        fixed_scale = self.parameterAsEnum(parameters, self.SCALE,
                                           context)  # == 1
        buf = self.parameterAsDouble(parameters, self.BUFFER, context)
        tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context)
        orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT,
                                              context)

        header_exp = QgsExpression(
            self.parameterAsExpression(parameters, self.HEADER, context))
        footer_exp = QgsExpression(
            self.parameterAsExpression(parameters, self.FOOTER, context))

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(clayer))

        out_dir = self.parameterAsString(parameters, self.OUTPUT, context)
        if not QDir(out_dir).exists():
            QDir().mkpath(out_dir)

        if DEBUG_MODE:
            openDirectory(out_dir)

        mapSettings = self.controller.settings.mapSettings
        baseExtent = self.controller.settings.baseExtent
        rotation = mapSettings.rotation()
        orig_size = mapSettings.outputSize()

        if cf_filter:
            cf_layer = QgsMemoryProviderUtils.createMemoryLayer(
                "current feature", clayer.fields(), clayer.wkbType(),
                clayer.crs())
            layers = [
                cf_layer if lyr == clayer else lyr
                for lyr in mapSettings.layers()
            ]
            mapSettings.setLayers(layers)

            doc = QDomDocument("qgis")
            clayer.exportNamedStyle(doc)
            cf_layer.importNamedStyle(doc)

        total = clayer.featureCount()
        for current, feature in enumerate(clayer.getFeatures()):
            if feedback.isCanceled():
                break

            if cf_filter:
                cf_layer.startEditing()
                cf_layer.deleteFeatures(
                    [f.id() for f in cf_layer.getFeatures()])
                cf_layer.addFeature(feature)
                cf_layer.commitChanges()

            title = feature.attribute(title_field)
            feedback.setProgressText("({}/{}) Exporting {}...".format(
                current + 1, total, title))
            logMessage("Exporting {}...".format(title), False)

            # extent
            geometry = QgsGeometry(feature.geometry())
            geometry.transform(self.transform)
            center = geometry.centroid().asPoint()

            if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry:
                tex_height = orig_tex_height or int(
                    tex_width * orig_size.height() / orig_size.width())
                rect = RotatedRect(center, baseExtent.width(),
                                   baseExtent.width() * tex_height / tex_width,
                                   rotation).scale(1 + buf / 100)
            else:
                geometry.rotate(rotation, center)
                rect = geometry.boundingBox().scaled(1 + buf / 100)
                center = RotatedRect.rotatePoint(rect.center(), rotation,
                                                 center)
                if orig_tex_height:
                    tex_height = orig_tex_height
                    tex_ratio = tex_width / tex_height
                    rect_ratio = rect.width() / rect.height()
                    if tex_ratio > rect_ratio:
                        rect = RotatedRect(center,
                                           rect.height() * tex_ratio,
                                           rect.height(), rotation)
                    else:
                        rect = RotatedRect(center, rect.width(),
                                           rect.width() / tex_ratio, rotation)
                else:
                    # fit to buffered geometry bounding box
                    rect = RotatedRect(center, rect.width(), rect.height(),
                                       rotation)
                    tex_height = tex_width * rect.height() / rect.width()

            rect.toMapSettings(mapSettings)
            mapSettings.setOutputSize(QSize(tex_width, tex_height))

            self.controller.settings.setMapSettings(mapSettings)

            # labels
            exp_context.setFeature(feature)
            self.controller.settings.setHeaderLabel(
                header_exp.evaluate(exp_context))
            self.controller.settings.setFooterLabel(
                footer_exp.evaluate(exp_context))

            self.export(title, out_dir, feedback)

            feedback.setProgress(int(current / total * 100))

        if P_OPEN_DIRECTORY and not DEBUG_MODE:
            openDirectory(out_dir)

        return {}
Ejemplo n.º 32
0
    def in_mask(self, feature, srid=None):
        if feature is None:  # expression overview
            return False

        if self.layer is None:
            return False

        try:
            # layer is not None but destroyed ?
            self.layer.id()
        except:
            self.reset_mask_layer()
            return False

        # mask layer empty due to unloaded memlayersaver plugin > no filtering
        if self.layer.featureCount() == 0:
            return True

        mask_geom, bbox = self.mask_geometry()
        geom = QgsGeometry(feature.geometry())
        if not geom.isGeosValid():
            geom = geom.buffer(0.0, 1)

        if geom is None:
            return False

        if srid is not None and self.layer.crs().postgisSrid() != srid:
            src_crs = QgsCoordinateReferenceSystem(srid)
            dest_crs = self.layer.crs()
            xform = QgsCoordinateTransform(src_crs, dest_crs,
                                           QgsProject.instance())
            try:
                geom.transform(xform)

            except Exception as e:
                for m in e.args:
                    QgsMessageLog.logMessage("in_mask - {}".format(m),
                                             "Extensions")
                    # transformation error. Check layer projection.
                    pass

        if geom.type() == QgsWkbTypes.PolygonGeometry:
            if (self.parameters.polygon_mask_method == 2
                    and not self.has_point_on_surface):
                self.parameters.polygon_mask_method = 1

            if self.parameters.polygon_mask_method == 0:
                # this method can only work when no geometry simplification is involved
                return mask_geom.overlaps(geom) or mask_geom.contains(geom)
            elif self.parameters.polygon_mask_method == 1:
                # the fastest method, but with possible inaccuracies
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(
                    geom.centroid())
            elif self.parameters.polygon_mask_method == 2:
                # will always work
                pt = geom.vertexAt(0)
                return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(
                    geom.pointOnSurface())
            else:
                return False
        elif geom.type() == QgsWkbTypes.LineGeometry:
            if self.parameters.line_mask_method == 0:
                return mask_geom.intersects(geom)
            elif self.parameters.line_mask_method == 1:
                return mask_geom.contains(geom)
            else:
                return False
        elif geom.type() == QgsWkbTypes.PointGeometry:
            return mask_geom.intersects(geom)
        else:
            return False
Ejemplo n.º 33
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context)
        target_crs = self.parameterAsExtentCrs(parameters, self.TARGET_AREA, context)
        if self.TARGET_AREA_CRS in parameters:
            c = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS, context)
            if c.isValid():
                target_crs = c

        target_geom = QgsGeometry.fromRect(extent)

        fields = QgsFields()
        fields.append(QgsField('auth_id', QVariant.String, '', 20))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        # make intersection tests nice and fast
        engine = QgsGeometry.createGeometryEngine(target_geom.constGet())
        engine.prepareGeometry()

        layer_bounds = QgsGeometry.fromRect(source.sourceExtent())

        crses_to_check = QgsCoordinateReferenceSystem.validSrsIds()
        total = 100.0 / len(crses_to_check)

        found_results = 0

        transform_context = QgsCoordinateTransformContext()
        for current, srs_id in enumerate(crses_to_check):
            if feedback.isCanceled():
                break

            candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id)
            if not candidate_crs.isValid():
                continue

            transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs, transform_context)
            transformed_bounds = QgsGeometry(layer_bounds)
            try:
                if not transformed_bounds.transform(transform_candidate) == 0:
                    continue
            except:
                continue

            try:
                if engine.intersects(transformed_bounds.constGet()):
                    feedback.pushInfo(self.tr('Found candidate CRS: {}').format(candidate_crs.authid()))
                    f = QgsFeature(fields)
                    f.setAttributes([candidate_crs.authid()])
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    found_results += 1
            except:
                continue

            feedback.setProgress(int(current * total))

        if found_results == 0:
            feedback.reportError(self.tr('No matching projections found'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 34
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(
            self.INPUT))
        method = self.getParameterValue(self.METHOD)

        geometryType = layer.geometryType()
        fields = layer.pendingFields()

        if geometryType == QGis.Polygon:
            areaName = vector.createUniqueFieldName('area', fields)
            fields.append(QgsField(areaName, QVariant.Double))
            perimeterName = vector.createUniqueFieldName('perimeter', fields)
            fields.append(QgsField(perimeterName, QVariant.Double))
        elif geometryType == QGis.Line:
            lengthName = vector.createUniqueFieldName('length', fields)
            fields.append(QgsField(lengthName, QVariant.Double))
        else:
            xName = vector.createUniqueFieldName('xcoord', fields)
            fields.append(QgsField(xName, QVariant.Double))
            yName = vector.createUniqueFieldName('ycoord', fields)
            fields.append(QgsField(yName, QVariant.Double))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields.toList(),
            layer.dataProvider().geometryType(), layer.crs())

        ellips = None
        crs = None
        coordTransform = None

        # Calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal

        if method == 2:
            ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid',
                                                     'NONE')[0]
            crs = layer.crs().srsid()
        elif method == 1:
            mapCRS = iface.mapCanvas().mapRenderer().destinationCrs()
            layCRS = layer.crs()
            coordTransform = QgsCoordinateTransform(layCRS, mapCRS)

        outFeat = QgsFeature()
        inGeom = QgsGeometry()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

        current = 0
        features = vector.features(layer)
        total = 100.0 / float(len(features))
        for f in features:
            inGeom = f.geometry()

            if method == 1:
                inGeom.transform(coordTransform)

            (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs)

            outFeat.setGeometry(inGeom)
            attrs = f.attributes()
            attrs.append(attr1)
            if attr2 is not None:
                attrs.append(attr2)
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            current += 1
            progress.setPercentage(int(current * total))

        del writer
Ejemplo n.º 35
0
def multi_buffering(layer, radii, callback=None):
    """Buffer a vector layer using many buffers (for volcanoes or rivers).

    This processing algorithm will keep the original attribute table and
    will add a new one for the hazard class name according to
    safe.definitions.fields.hazard_value_field.

    radii = OrderedDict()
    radii[500] = 'high'
    radii[1000] = 'medium'
    radii[2000] = 'low'

    Issue https://github.com/inasafe/inasafe/issues/3185

    :param layer: The layer to polygonize.
    :type layer: QgsVectorLayer

    :param radii: A dictionary of radius.
    :type radii: OrderedDict

    :param callback: A function to all to indicate progress. The function
        should accept params 'current' (int), 'maximum' (int) and 'step' (str).
        Defaults to None.
    :type callback: function

    :return: The buffered vector layer.
    :rtype: QgsVectorLayer
    """
    # Layer output
    output_layer_name = buffer_steps['output_layer_name']
    processing_step = buffer_steps['step_name']

    input_crs = layer.crs()
    feature_count = layer.featureCount()

    fields = layer.fields()
    # Set the new hazard class field.
    new_field = create_field_from_definition(hazard_class_field)
    fields.append(new_field)
    # Set the new buffer distances field.
    new_field = create_field_from_definition(buffer_distance_field)
    fields.append(new_field)

    buffered = create_memory_layer(
        output_layer_name, QGis.Polygon, input_crs, fields)
    data_provider = buffered.dataProvider()

    # Reproject features if needed into UTM if the layer is in 4326.
    if layer.crs().authid() == 'EPSG:4326':
        center = layer.extent().center()
        utm = QgsCoordinateReferenceSystem(
            get_utm_epsg(center.x(), center.y(), input_crs))
        transform = QgsCoordinateTransform(layer.crs(), utm)
        reverse_transform = QgsCoordinateTransform(utm, layer.crs())
    else:
        transform = None
        reverse_transform = None

    for i, feature in enumerate(layer.getFeatures()):
        geom = QgsGeometry(feature.geometry())

        if transform:
            geom.transform(transform)

        inner_ring = None

        for radius in radii:
            attributes = feature.attributes()

            # We add the hazard value name to the attribute table.
            attributes.append(radii[radius])
            # We add the value of buffer distance to the attribute table.
            attributes.append(radius)

            circle = geom.buffer(radius, 30)

            if inner_ring:
                circle.addRing(inner_ring)

            inner_ring = circle.asPolygon()[0]

            new_feature = QgsFeature()
            if reverse_transform:
                circle.transform(reverse_transform)

            new_feature.setGeometry(circle)
            new_feature.setAttributes(attributes)

            data_provider.addFeatures([new_feature])

        if callback:
            callback(current=i, maximum=feature_count, step=processing_step)

    # We transfer keywords to the output.
    buffered.keywords = layer.keywords
    buffered.keywords['layer_geometry'] = 'polygon'
    buffered.keywords['layer_purpose'] = layer_purpose_hazard['key']
    buffered.keywords['inasafe_fields'][hazard_class_field['key']] = (
        hazard_class_field['field_name'])

    check_layer(buffered)
    return buffered
Ejemplo n.º 36
0
class GeometryHighlight(QgsMapCanvasItem):

    _mapCanvas = None  # QgsMapCanvas
    _geometry = None  # QgsGeometry()
    _brush = QBrush()
    _pen = QPen()

    def __init__(self, mapCanvas, geometry, layer):
        super(GeometryHighlight, self).__init__(mapCanvas)
        self._mapCanvas = mapCanvas
        if not geometry or not isinstance(geometry, QgsGeometry) or geometry.isEmpty() or not geometry.isGeosValid():
            return
        self._geometry = QgsGeometry(geometry) # Force deep copy
        self.setLineColor(Project.highlightLineColor())
        self.setFillColor(Project.highlightFillColor())
        if (layer and self._mapCanvas.mapSettings().hasCrsTransformEnabled()):
            ct = self._mapCanvas.mapSettings().layerTransform(layer)
            if ct:
                self._geometry.transform(ct)
        self.updateRect()
        self.update()

    def remove(self):
        self._mapCanvas.scene().removeItem(self)

    def setLineWidth(self, width):
        self._pen.setWidth(width)

    def setLineColor(self, color):
        lineColor = QColor(color)
        lineColor.setAlpha(255)
        self._pen.setColor(lineColor)

    def setFillColor(self, fillColor):
        self._brush.setColor(fillColor)
        self._brush.setStyle(Qt.SolidPattern)

    def updatePosition(self):
        pass

    # protected:
    def paint(self, painter, option=None, widget=None): # Override
        if not self._geometry:
            return

        painter.setPen(self._pen)
        painter.setBrush(self._brush)

        wkbType = self._geometry.wkbType()
        if wkbType == QGis.WKBPoint or wkbType == QGis.WKBPoint25D:
            self._paintPoint(painter, self._geometry.asPoint())
        elif wkbType == QGis.WKBMultiPoint or wkbType == QGis.WKBMultiPoint25D:
            for point in self._geometry.asMultiPoint():
                self._paintPoint(painter, point)
        elif wkbType == QGis.WKBLineString or wkbType == QGis.WKBLineString25D:
            self._paintLine(painter, self._geometry.asPolyline())
        elif wkbType == QGis.WKBMultiLineString or wkbType == QGis.WKBMultiLineString25D:
            for line in self._geometry.asMultiPolyline():
                self._paintLine(painter, line)
        elif wkbType == QGis.WKBPolygon or wkbType == QGis.WKBPolygon25D:
            self._paintPolygon(painter, self._geometry.asPolygon())
        elif wkbType == QGis.WKBMultiPolygon or wkbType == QGis.WKBMultiPolygon25D:
            for polygon in self._geometry.asMultiPolygon():
                self._paintPolygon(painter, polygon)

    def updateRect(self):
        if self._geometry:
            r = self._geometry.boundingBox()
            if r.isEmpty():
                d = self._mapCanvas.extent().width() * 0.005
                r.setXMinimum(r.xMinimum() - d)
                r.setYMinimum(r.yMinimum() - d)
                r.setXMaximum(r.xMaximum() + d)
                r.setYMaximum(r.yMaximum() + d)
            self.setRect(r)
            self.setVisible(True)
        else:
            self.setRect(QgsRectangle())

    # private:

    def _paintPoint(self, painter, point):
        painter.drawEllipse(self.toCanvasCoordinates(point) - self.pos(), 2, 2)

    def _paintLine(self, painter, line):
        polyline = QPolygonF()
        for point in line:
            polyline.append(self.toCanvasCoordinates(point) - self.pos())
        painter.drawPolyline(polyline)

    def _paintPolygon(self, painter, polygon):
        path = QPainterPath()
        for line in polygon:
            ring = QPolygonF()
            for point in line:
                cur = self.toCanvasCoordinates(point) - self.pos()
                ring.append(cur)
            ring.append(ring[0])
            path.addPolygon(ring)
        painter.drawPath(path)
Ejemplo n.º 37
0
    def run(self):
        """Experimental impact function."""
        self.validate()
        self.prepare()

        self.provenance.append_step(
            'Calculating Step',
            'Impact function is calculating the impact.')

        # Get parameters from layer's keywords
        self.hazard_class_attribute = self.hazard.keyword('field')
        self.hazard_class_mapping = self.hazard.keyword('value_map')
        self.exposure_class_attribute = self.exposure.keyword(
            'structure_class_field')

        # Prepare Hazard Layer
        hazard_provider = self.hazard.layer.dataProvider()

        # Check affected field exists in the hazard layer
        affected_field_index = hazard_provider.fieldNameIndex(
            self.hazard_class_attribute)
        if affected_field_index == -1:
            message = tr(
                'Field "%s" is not present in the attribute table of the '
                'hazard layer. Please change the Affected Field parameter in '
                'the IF Option.') % self.hazard_class_attribute
            raise GetDataError(message)

        srs = self.exposure.layer.crs().toWkt()
        exposure_provider = self.exposure.layer.dataProvider()
        exposure_fields = exposure_provider.fields()

        # Check self.exposure_class_attribute exists in exposure layer
        building_type_field_index = exposure_provider.fieldNameIndex(
            self.exposure_class_attribute)
        if building_type_field_index == -1:
            message = tr(
                'Field "%s" is not present in the attribute table of '
                'the exposure layer. Please change the Building Type '
                'Field parameter in the IF Option.'
            ) % self.exposure_class_attribute
            raise GetDataError(message)

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

        # Create layer to store the buildings from E and extent
        buildings_are_points = is_point_layer(self.exposure.layer)
        if buildings_are_points:
            building_layer = QgsVectorLayer(
                'Point?crs=' + srs, 'impact_buildings', 'memory')
        else:
            building_layer = QgsVectorLayer(
                'Polygon?crs=' + srs, 'impact_buildings', 'memory')
        building_provider = building_layer.dataProvider()

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

        # Filter geometry and data using the requested extent
        requested_extent = QgsRectangle(*self.requested_extent)

        # This is a hack - we should be setting the extent CRS
        # in the IF base class via safe/engine/core.py:calculate_impact
        # for now we assume the extent is in 4326 because it
        # is set to that from geo_extent
        # See issue #1857
        transform = QgsCoordinateTransform(
            self.requested_extent_crs, self.hazard.crs())
        projected_extent = transform.transformBoundingBox(requested_extent)
        request = QgsFeatureRequest()
        request.setFilterRect(projected_extent)

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

        # make spatial index of affected polygons
        hazard_index = QgsSpatialIndex()
        hazard_geometries = {}  # key = feature id, value = geometry
        has_hazard_objects = False
        for feature in self.hazard.layer.getFeatures(request):
            value = feature[affected_field_index]
            if value not in self.hazard_class_mapping[self.wet]:
                continue
            hazard_index.insertFeature(feature)
            hazard_geometries[feature.id()] = QgsGeometry(feature.geometry())
            has_hazard_objects = True

        if not has_hazard_objects:
            message = tr(
                'There are no objects in the hazard layer with %s '
                'value in %s. Please check your data or use another '
                'attribute.') % (
                    self.hazard_class_attribute,
                    ', '.join(self.hazard_class_mapping[self.wet]))
            raise GetDataError(message)

        # Filter out just those EXPOSURE features in the analysis extents
        transform = QgsCoordinateTransform(
            self.requested_extent_crs, self.exposure.layer.crs())
        projected_extent = transform.transformBoundingBox(requested_extent)
        request = QgsFeatureRequest()
        request.setFilterRect(projected_extent)

        # We will use this transform to project each exposure feature into
        # the CRS of the Hazard.
        transform = QgsCoordinateTransform(
            self.exposure.crs(), self.hazard.crs())
        features = []
        for feature in self.exposure.layer.getFeatures(request):
            # Make a deep copy as the geometry is passed by reference
            # If we don't do this, subsequent operations will affect the
            # original feature geometry as well as the copy TS
            building_geom = QgsGeometry(feature.geometry())
            # Project the building geometry to hazard CRS
            building_bounds = transform.transform(building_geom.boundingBox())
            affected = False
            # get tentative list of intersecting hazard features
            # only based on intersection of bounding boxes
            ids = hazard_index.intersects(building_bounds)
            for fid in ids:
                # run (slow) exact intersection test
                building_geom.transform(transform)
                if hazard_geometries[fid].intersects(building_geom):
                    affected = True
                    break
            new_feature = QgsFeature()
            # We write out the original feature geom, not the projected one
            new_feature.setGeometry(feature.geometry())
            new_feature.setAttributes(feature.attributes())
            new_feature[target_field_index] = 1 if affected else 0
            features.append(new_feature)

            # every once in a while commit the created features
            # to the output layer
            if len(features) == 1000:
                (_, __) = building_provider.addFeatures(features)
                features = []

        (_, __) = building_provider.addFeatures(features)
        building_layer.updateExtents()

        # Generate simple impact report
        self.buildings = {}
        self.affected_buildings = OrderedDict([
            (tr('Flooded'), {})
        ])
        buildings_data = building_layer.getFeatures()
        building_type_field_index = building_layer.fieldNameIndex(
            self.exposure_class_attribute)
        for building in buildings_data:
            record = building.attributes()
            building_type = record[building_type_field_index]
            if building_type in [None, 'NULL', 'null', 'Null']:
                building_type = 'Unknown type'
            if building_type not in self.buildings:
                self.buildings[building_type] = 0
                for category in self.affected_buildings.keys():
                    self.affected_buildings[category][
                        building_type] = OrderedDict([
                            (tr('Buildings Affected'), 0)])
            self.buildings[building_type] += 1

            if record[target_field_index] == 1:
                self.affected_buildings[tr('Flooded')][building_type][
                    tr('Buildings Affected')] += 1

        # Lump small entries and 'unknown' into 'other' category
        # Building threshold #2468
        postprocessors = self.parameters['postprocessors']
        building_postprocessors = postprocessors['BuildingType'][0]
        self.building_report_threshold = building_postprocessors.value[0].value
        self._consolidate_to_other()

        impact_summary = self.html_report()

        # For printing map purpose
        map_title = tr('Buildings inundated')
        legend_title = tr('Structure inundated status')

        style_classes = [
            dict(label=tr('Not Inundated'), value=0, colour='#1EFC7C',
                 transparency=0, size=0.5),
            dict(label=tr('Inundated'), value=1, colour='#F31A1C',
                 transparency=0, size=0.5)]
        style_info = dict(
            target_field=self.target_field,
            style_classes=style_classes,
            style_type='categorizedSymbol')

        # Convert QgsVectorLayer to inasafe layer and return it.
        if building_layer.featureCount() < 1:
            raise ZeroImpactException(tr(
                'No buildings were impacted by this flood.'))

        extra_keywords = {
            'impact_summary': impact_summary,
            'map_title': map_title,
            'legend_title': legend_title,
            'target_field': self.target_field,
            'buildings_total': self.total_buildings,
            'buildings_affected': self.total_affected_buildings
        }

        self.set_if_provenance()

        impact_layer_keywords = self.generate_impact_keywords(extra_keywords)

        building_layer = Vector(
            data=building_layer,
            name=tr('Flooded buildings'),
            keywords=impact_layer_keywords,
            style_info=style_info)
        self._impact = building_layer
        return building_layer
Ejemplo n.º 38
0
    def generateFootprintsForFilmOblique(self):
        self.reloadFpLayer()
        self.reloadCpLayer()

        caps = self.fpLayer.dataProvider().capabilities()
        if caps & QgsVectorDataProvider.AddFeatures:
            if self.cpLayer.dataProvider().featureCount() > 0:
                iter = self.cpLayer.getFeatures()
                existingFootpints = QgsVectorLayerUtils.getValues(
                    self.fpLayer, "bildnummer")[0]
                cpFt = QgsFeature()
                fpFts = []
                #iterate over points from CP Layer > LON, LAT
                while iter.nextFeature(cpFt):
                    if cpFt['bildnummer'] in existingFootpints:
                        #QMessageBox.warning(None, u"Bild Nummern", u"Footprint für das Bild mit der Nummer {0} wurde bereits erstellt.".format(ft['BILD']))
                        continue
                    cp = cpFt.geometry()
                    cpMetric = QgsGeometry(cp)
                    destCrs = QgsCoordinateReferenceSystem()
                    destCrs.createFromProj4(self.Proj4Utm(cp.asPoint()))
                    coordTransformF = QgsCoordinateTransform(
                        self.cpLayer.crs(), destCrs, QgsProject.instance())
                    coordTransformB = QgsCoordinateTransform(
                        destCrs, self.cpLayer.crs(), QgsProject.instance())
                    cpMetric.transform(coordTransformF)
                    if cpFt['radius'] == '':
                        r = 175
                    else:
                        r = float(cpFt['radius'])
                    fpMetric = QgsGeometry(cpMetric.buffer(r, 18))
                    fp = QgsGeometry(fpMetric)
                    fp.transform(coordTransformB)

                    fpFt = QgsFeature(self.fpLayer.fields())
                    fpFt.setGeometry(fp)
                    fpFt.setAttribute("bildnummer", cpFt["bildnummer"])
                    fpFt.setAttribute("filmnummer", cpFt["filmnummer"])
                    da = QgsDistanceArea()
                    da.setEllipsoid(self.fpLayer.crs().ellipsoidAcronym())
                    fpFt.setAttribute('shape_length', da.measurePerimeter(fp))
                    fpFt.setAttribute('shape_area', da.measureArea(fp))
                    fpFts.append(fpFt)

                (res,
                 outFeats) = self.fpLayer.dataProvider().addFeatures(fpFts)
                self.fpLayer.updateExtents()
                if self.canvas.isCachingEnabled():
                    self.fpLayer.triggerRepaint()
                else:
                    self.canvas.refresh()
            else:
                QMessageBox.warning(
                    None, "Keine Bildmittelpunkte",
                    "Keine Bildmittelpunkte für den Film {0} vorhanden.".
                    format(self.currentFilmNumber))
        else:
            QMessageBox.warning(
                None, "Layer Capabilities",
                "AddFeature is not enabled ({0})".format(
                    self.fpLayer.dataProvider().capabilitiesString()))
Ejemplo n.º 39
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        method = self.getParameterValue(self.METHOD)

        geometryType = layer.geometryType()
        fields = layer.pendingFields()

        if geometryType == QGis.Polygon:
            areaName = vector.createUniqueFieldName('area', fields)
            fields.append(QgsField(areaName, QVariant.Double))
            perimeterName = vector.createUniqueFieldName('perimeter', fields)
            fields.append(QgsField(perimeterName, QVariant.Double))
        elif geometryType == QGis.Line:
            lengthName = vector.createUniqueFieldName('length', fields)
            fields.append(QgsField(lengthName, QVariant.Double))
        else:
            xName = vector.createUniqueFieldName('xcoord', fields)
            fields.append(QgsField(xName, QVariant.Double))
            yName = vector.createUniqueFieldName('ycoord', fields)
            fields.append(QgsField(yName, QVariant.Double))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields.toList(), layer.dataProvider().geometryType(), layer.crs())

        ellips = None
        crs = None
        coordTransform = None

        # Calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal

        if method == 2:
            ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid',
                                                     'NONE')[0]
            crs = layer.crs().srsid()
        elif method == 1:
            mapCRS = iface.mapCanvas().mapSettings().destinationCrs()
            layCRS = layer.crs()
            coordTransform = QgsCoordinateTransform(layCRS, mapCRS)

        outFeat = QgsFeature()
        inGeom = QgsGeometry()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            inGeom = f.geometry()

            if method == 1:
                inGeom.transform(coordTransform)

            (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs)

            outFeat.setGeometry(inGeom)
            attrs = f.attributes()
            attrs.append(attr1)
            if attr2 is not None:
                attrs.append(attr2)
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer
Ejemplo n.º 40
0
def setSelectFeatures(canvas,
                      selectGeometry,
                      doContains,
                      doDifference,
                      singleSelect=None):
    """
    QgsMapCanvas* canvas,
    QgsGeometry* selectGeometry,
    bool doContains,
    bool doDifference,
    bool singleSelect 
    """
    if selectGeometry.type() != QGis.Polygon:
        return

    vlayer = getCurrentVectorLayer(canvas)

    if vlayer == None:
        return

    #toLayerCoordinates will throw an exception for any 'invalid' points in
    #the rubber band.
    #For example, if you project a world map onto a globe using EPSG 2163
    #and then click somewhere off the globe, an exception will be thrown.
    selectGeomTrans = QgsGeometry(selectGeometry)

    if canvas.mapSettings().hasCrsTransformEnabled():
        try:
            ct = QgsCoordinateTransform(canvas.mapSettings().destinationCrs(),
                                        vlayer.crs())
            selectGeomTrans.transform(ct)
        except QgsCsException as cse:
            Q_UNUSED(cse)
            #catch exception for 'invalid' point and leave existing selection unchanged
            """
            QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) );
            QgisApp::instance()->messageBar()->pushMessage(
            QObject::tr( "CRS Exception" ),
            QObject::tr( "Selection extends beyond layer's coordinate system" ),
            QgsMessageBar::WARNING,
            QgisApp::instance()->messageTimeout() );
            """
            return

    QApplication.setOverrideCursor(Qt.WaitCursor)
    """
    QgsDebugMsg( "Selection layer: " + vlayer->name() );
    QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() );
    QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) );
    QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) );
    """

    context = QgsRenderContext().fromMapSettings(canvas.mapSettings())
    r = vlayer.rendererV2()

    if r:
        r.startRender(context, vlayer.pendingFields())

    request = QgsFeatureRequest()
    request.setFilterRect(selectGeomTrans.boundingBox())
    request.setFlags(QgsFeatureRequest.ExactIntersect)

    if r:
        request.setSubsetOfAttributes(r.usedAttributes(),
                                      vlayer.pendingFields())
    else:
        request.setSubsetOfAttributes(QgsAttributeList)

    fit = vlayer.getFeatures(request)

    newSelectedFeatures = []  #QgsFeatureIds
    f = QgsFeature()
    closestFeatureId = 0  #QgsFeatureId
    foundSingleFeature = False
    #double closestFeatureDist = std::numeric_limits<double>::max();
    closestFeatureDist = sys.float_info.max

    while fit.nextFeature(f):
        # make sure to only use features that are visible
        if r and not r.willRenderFeature(f):
            continue
        g = QgsGeometry(f.geometry())
        if doContains:
            if not selectGeomTrans.contains(g):
                continue
        else:
            if not selectGeomTrans.intersects(g):
                continue
        if singleSelect:
            foundSingleFeature = True
            distance = float(g.distance(selectGeomTrans))
            if (distance <= closestFeatureDist):
                closestFeatureDist = distance
                closestFeatureId = f.id()
        else:
            newSelectedFeatures.insert(0, f.id())

    if singleSelect and foundSingleFeature:
        newSelectedFeatures.insert(0, closestFeatureId)
    if r:
        r.stopRender(context)
    #QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() )

    if doDifference:
        layerSelectedFeatures = vlayer.selectedFeaturesIds()

        selectedFeatures = []  #QgsFeatureIds
        deselectedFeatures = []  # QgsFeatureIds

        # i = QgsFeatureIds.const_iterator(newSelectedFeatures.constEnd())
        # while i != newSelectedFeatures.constBegin():
        #     i = i - 1
        #     if layerSelectedFeatures.contains(i):
        #         deselectedFeatures.insert(0, i)
        #     else:
        #         selectedFeatures.insert(0, i)

        for item in newSelectedFeatures:
            if item in layerSelectedFeatures:
                deselectedFeatures.insert(0, item)
            else:
                selectedFeatures.insert(0, item)

        vlayer.modifySelection(selectedFeatures, deselectedFeatures)
    else:
        vlayer.setSelectedFeatures(newSelectedFeatures)

    QApplication.restoreOverrideCursor()
    """