def create_line(self, centroid, degree, radius):
        outer_ring = []

        outer_ring.append(centroid)
        outer_ring.append(self.create_point(centroid, math.radians(degree), radius))

        return QgsGeometry.fromPolylineXY(outer_ring)
Example #2
0
    def canvasReleaseEvent(self, event):
        if self.m2 and self.m1:
            self.reset()

        point = self.snappoint(event.pos())

        if not self.m1:
            self.m1 = QgsVertexMarker(self.canvas())
            self.m1.setIconType(1)
            self.m1.setColor(Qt.blue)
            self.m1.setIconSize(6)
            self.m1.setPenWidth(3)
            self.m1.setCenter(point)
            self.p1 = point
            return

        if not self.m2:
            self.m2 = QgsVertexMarker(self.canvas())
            self.m2.setIconType(1)
            self.m2.setColor(Qt.red)
            self.m2.setIconSize(6)
            self.m2.setPenWidth(3)
            self.m2.setCenter(point)
            self.p2 = point

        if self.m2 and self.m1:
            geom = QgsGeometry.fromPolylineXY([self.p1, self.p2])
            self.band.setToGeometry(geom, None)
            self.geometryComplete.emit(geom)
 def __moved(self, position):
     if len(self.pointsToDraw) > 0:
         mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"])
         self.rubberband.reset(self.polygon)
         newPnt = QgsPointXY(mapPos.x(), mapPos.y())
         pnts = self.pointsToDraw + [newPnt]
         self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(pnts), None)
 def __signal_pbCopyKml_clicked(self, cheked):
     # Extent Openlayers
     action = "map.getExtent().toGeometry().toString();"
     wkt = self.webViewMap.page().mainFrame().evaluateJavaScript(action)
     rect = QgsGeometry.fromWkt(wkt).boundingBox()
     srsGE = QgsCoordinateReferenceSystem(
         4326, QgsCoordinateReferenceSystem.EpsgCrsId)
     coodTrans = QgsCoordinateTransform(self.__srsOL, srsGE,
                                        QgsProject.instance())
     rect = coodTrans.transform(
         rect, QgsCoordinateTransform.ForwardTransform)
     line = QgsGeometry.fromRect(rect).asPolygon()[0]
     wkt = str(QgsGeometry.fromPolylineXY(line).asWkt())
     # Kml
     proj4 = str(srsGE.toProj4())
     kmlLine = bindogr.exportKml(wkt, proj4)
     kml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"\
           "<kml xmlns=\"http://www.opengis.net/kml/2.2\" " \
           "xmlns:gx=\"http://www.google.com/kml/ext/2.2\" " \
           "xmlns:kml=\"http://www.opengis.net/kml/2.2\" " \
           "xmlns:atom=\"http://www.w3.org/2005/Atom\">" \
           "<Placemark>" \
           "<name>KML from Plugin Openlayers Overview for QGIS</name>" \
           "<description>Extent of openlayers map from Plugin Openlayers \
           Overview for QGIS</description>"\
           "%s" \
           "</Placemark></kml>" % kmlLine
     clipBoard = QApplication.clipboard()
     clipBoard.setText(kml)
Example #5
0
    def processAlgorithm(self, parameters, context, feedback):
        if parameters[self.INPUT] == parameters[self.HUBS]:
            raise QgsProcessingException(
                self.tr('Same layer given for both hubs and spokes'))

        point_source = self.parameterAsSource(parameters, self.INPUT, context)
        hub_source = self.parameterAsSource(parameters, self.HUBS, context)
        fieldName = self.parameterAsString(parameters, self.FIELD, context)

        units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)]

        fields = point_source.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.LineString, point_source.sourceCrs())

        index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))

        distance = QgsDistanceArea()
        distance.setSourceCrs(point_source.sourceCrs(), context.transformContext())
        distance.setEllipsoid(context.project().ellipsoid())

        # Scan source points, find nearest hub, and write to output file
        features = point_source.getFeatures()
        total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                sink.addFeature(f, QgsFeatureSink.FastInsert)
                continue
            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            if units != self.LAYER_UNITS:
                hub_dist_in_desired_units = distance.convertLengthMeasurement(hubDist, units)
            else:
                hub_dist_in_desired_units = hubDist

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            attributes.append(hub_dist_in_desired_units)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPolylineXY([src, closest]))

            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #6
0
def createLayerWithOneLine():
    # create a temporary layer
    # linelayer = iface.addVectorLayer("LineString?crs=epsg:4326&field=gid:int&field=name:string", "simple_line", "memory")
    linelayer = QgsVectorLayer("LineString?crs=epsg:4326&field=gid:int&field=name:string", "simple_line", "memory")
    one = QgsFeature(linelayer.dataProvider().fields(), 0)
    one.setAttributes([1, 'one'])
    one.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(-7, 38), QgsPointXY(-8, 42)]))
    linelayer.dataProvider().addFeatures([one])
    return linelayer
Example #7
0
 def _setRubberBandMarker(self, geom):
     m = QgsRubberBand(self.qgisIface.mapCanvas(), False)  # not polygon
     if QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.LineGeometry:
         linegeom = geom
     elif QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.PolygonGeometry:
         linegeom = QgsGeometry.fromPolylineXY(geom.asPolygon()[0])
     m.setToGeometry(linegeom, None)
     m.setColor(QColor(self.config['rubber_color']))
     m.setWidth(self.config['rubber_width'])
     return m
Example #8
0
 def testMeasureLine(self):
     #   +-+
     #   | |
     # +-+ +
     linestring = QgsGeometry.fromPolylineXY(
         [QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 0), ]
     )
     da = QgsDistanceArea()
     length = da.measureLength(linestring)
     myMessage = ('Expected:\n%f\nGot:\n%f\n' %
                  (4, length))
     assert length == 4, myMessage
Example #9
0
 def testWFSLineStrings(self):
     """
     Adds some lines, then check and clear all
     """
     layer_name = 'test_linestring'
     layer = self._getLayer(layer_name)
     wfs_layer = self._getWFSLayer(layer_name)
     feat1 = QgsFeature(wfs_layer.pendingFields())
     feat1['id'] = 11
     feat1['name'] = 'name 11'
     feat1.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9, 45), QgsPointXY(10, 46)]))
     feat2 = QgsFeature(wfs_layer.pendingFields())
     feat2.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9.5, 45.5), QgsPointXY(10.5, 46.5)]))
     feat2['id'] = 12
     feat2['name'] = 'name 12'
     old_features = [feat1, feat2]
     # Change feat1
     new_feat1 = QgsFeature(wfs_layer.pendingFields())
     new_feat1['id'] = 121
     new_feat1['name'] = 'name 121'
     new_feat1.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9.8, 45.8), QgsPointXY(10.8, 46.8)]))
     new_features = [new_feat1, feat2]
     self._testLayer(wfs_layer, layer, old_features, new_features)
def _swap_qgs_geometry(qgsgeom):
    if qgsgeom.wkbType() == QgsWkbTypes.Point:
        p = qgsgeom.asPoint()
        qgsgeom = QgsGeometry.fromPointXY(QgsPointXY(p[1], p[0]))
    elif qgsgeom.wkbType() == QgsWkbTypes.MultiPoint:
        mp = qgsgeom.asMultiPoint()
        qgsgeom = QgsGeometry.fromMultiPointXY([QgsPointXY(p[1], p[0]) for p in mp])
    elif qgsgeom.wkbType() == QgsWkbTypes.LineString:
        pl = qgsgeom.asPolyline()
        qgsgeom = QgsGeometry.fromPolylineXY([QgsPointXY(p[1],p[0]) for p in pl])
    elif qgsgeom.wkbType() == QgsWkbTypes.MultiLineString:
        mls = qgsgeom.asMultiPolyline()
        qgsgeom = QgsGeometry.fromMultiPolylineXY([[QgsPointXY(p[1],p[0]) for p in pl] for pl in mls])
    elif qgsgeom.wkbType() == QgsWkbTypes.Polygon:
        pl = qgsgeom.asPolygon()
        qgsgeom = QgsGeometry.fromPolygonXY([[QgsPointXY(p[1],p[0]) for p in r] for r in pl])
    elif qgsgeom.wkbType() == QgsWkbTypes.MultiPolygon:
        mp = qgsgeom.asMultiPolygon()
        qgsgeom = QgsGeometry.fromMultiPolygonXY([[[QgsPointXY(p[1],p[0]) for p in r] for r in pl] for pl in mp])
    return qgsgeom
    def canvasPressEvent(self, e):
        # find the side of the rectangle closest to the click and some data
        # necessary to compute the new cneter and scale
        topLeft, topRight, bottomRight, bottomLeft = \
            self.layer.cornerCoordinates()
        top = [topLeft, topRight]
        right = [bottomRight, topRight]
        bottom = [bottomRight, bottomLeft]
        left = [bottomLeft, topLeft]

        click = QgsGeometry.fromPointXY(self.toMapCoordinates(e.pos()))

        # order is important (for referenceSide)
        sides = [top, right, bottom, left]
        distances = [click.distance(
            QgsGeometry.fromPolylineXY(side)) for side in sides]
        self.indexSide = self.minDistance(distances)
        self.side = sides[self.indexSide]
        self.sidePoint = self.center(self.side)
        self.vector = self.directionVector(self.side)
        # side that does not move (opposite of indexSide)
        self.referenceSide = sides[(self.indexSide + 2) % 4]
        self.referencePoint = self.center(self.referenceSide)
        self.referenceDistance = self.distance(
            self.sidePoint, self.referencePoint)
        self.isXScale = self.indexSide % 2 == 1

        self.startPoint = click.asPoint()
        self.endPoint = self.startPoint
        self.isEmittingPoint = True

        self.isLayerVisible = isLayerVisible(self.iface,
                                             self.layer)
        setLayerVisible(self.iface, self.layer, False)

        adjustment = self.computeAdjustment()
        self.showAdjustment(*adjustment)
        self.layer.history.append(
            {"action": "adjust", "center": self.layer.center, "xScale": self.layer.xScale, "yScale": self.layer.yScale})
Example #12
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS,
                                             context)
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context,
                                         network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters,
                                                    self.DIRECTION_FIELD,
                                                    context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD,
                                              context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD,
                                               context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH,
                                           context)
        defaultDirection = self.parameterAsEnum(parameters,
                                                self.DEFAULT_DIRECTION,
                                                context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD,
                                                context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED,
                                              context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = startPoints.fields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        feat = QgsFeature()
        feat.setFields(fields)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.LineString,
                                               network.sourceCrs())

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network, directionField,
                                          forwardValue, backwardValue,
                                          bothValue, defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance)

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathLayerToPoint',
                                       'Loading start points…'))
        request = QgsFeatureRequest()
        request.setDestinationCrs(network.sourceCrs(),
                                  context.transformContext())
        features = startPoints.getFeatures(request)
        total = 100.0 / startPoints.featureCount() if startPoints.featureCount(
        ) else 0

        points = [endPoint]
        source_attributes = {}
        i = 1
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            for p in f.geometry().vertices():
                points.append(QgsPointXY(p))
                source_attributes[i] = f.attributes()
                i += 1

            feedback.setProgress(int(current * total))

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathLayerToPoint',
                                       'Building graph…'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathLayerToPoint',
                                       'Calculating shortest paths…'))
        graph = builder.graph()

        idxEnd = graph.findVertex(snappedPoints[0])

        nPoints = len(snappedPoints)
        total = 100.0 / nPoints if nPoints else 1
        for i in range(1, nPoints):
            if feedback.isCanceled():
                break

            idxStart = graph.findVertex(snappedPoints[i])

            tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

            if tree[idxEnd] == -1:
                msg = self.tr(
                    'There is no route from start point ({}) to end point ({}).'
                    .format(points[i].toString(), endPoint.toString()))
                feedback.reportError(msg)
                # add feature with no geometry
                feat.clearGeometry()
                attrs = source_attributes[i]
                attrs.append(points[i].toString())
                feat.setAttributes(attrs)
                sink.addFeature(feat, QgsFeatureSink.FastInsert)
                continue

            route = [graph.vertex(idxEnd).point()]
            cost = costs[idxEnd]
            current = idxEnd
            while current != idxStart:
                current = graph.edge(tree[current]).fromVertex()
                route.append(graph.vertex(current).point())

            route.reverse()

            geom = QgsGeometry.fromPolylineXY(route)
            feat.setGeometry(geom)
            attrs = source_attributes[i]
            attrs.extend(
                [points[i].toString(),
                 endPoint.toString(), cost / multiplier])
            feat.setAttributes(attrs)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Example #13
0
    def updateRubberGeom(self):
        if self.pA is None:
            return

        self.zoneWidth = self.pA.distance(self.pB)
        self.zoneDepth = self.pA.distance(self.pD)
        self.pM = QgsPointXY((self.pC.x() + self.pD.x()) / 2,
                             (self.pC.y() + self.pD.y()) / 2)
        self.d0 = self.pM.distance(self.pY)
        # self.widget.updateZ(self.pY)

        self.rb.setToGeometry(
            QgsGeometry.fromPolygonXY(
                [[self.pD, self.pA, self.pB, self.pC, self.pD]]))
        self.rbFoc.setToGeometry(
            QgsGeometry.fromPolylineXY([self.pD, self.pY, self.pC]))

        for p, rb in [
            [self.pA, self.rbPA],
            [self.pB, self.rbPB],
            [self.pC, self.rbPC],
            [self.pD, self.rbPD],
            [self.pY, self.rbPY],
            [self.pH, self.rbPH],
            [self.pL, self.rbPL],
        ]:
            rb.setToGeometry(QgsGeometry.fromPointXY(p))

        leftEdge = (QgsGeometry.fromPolylineXY([
            self.pA, self.pD
        ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline())
        rightEdge = (QgsGeometry.fromPolylineXY([
            self.pB, self.pC
        ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline())

        # Plot edges lines
        polyline = list(zip(leftEdge, rightEdge))

        backSide = (QgsGeometry.fromPolylineXY([
            self.pA, self.pB
        ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline())
        frontSide = (QgsGeometry.fromPolylineXY([
            self.pD, self.pC
        ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline())
        polylineX = list(zip(frontSide[:], backSide[:]))

        self.finalWidth = self.zoneWidth

        self.rowLines = polyline
        self.columnLines = polylineX
        self.allLines = polyline + polylineX
        self.rbLines.setToGeometry(
            QgsGeometry.fromMultiPolylineXY(
                polylineX + polyline + polyline[::max(1, 1 + len(polyline))]))
        if self.widget.cbReverseRows.isChecked():
            if self.widget.cbReverseColumns.isChecked():
                self.rbPC.setColor(Qt.red)
                self.rbPD.setColor(Qt.red)
                self.rbPA.setColor(Qt.red)
                self.rbPB.setColor(QColor(0, 200, 150, 255))
            else:
                self.rbPC.setColor(Qt.red)
                self.rbPD.setColor(Qt.red)
                self.rbPB.setColor(Qt.red)
                self.rbPA.setColor(QColor(0, 200, 150, 255))
        else:
            if self.widget.cbReverseColumns.isChecked():
                self.rbPA.setColor(Qt.red)
                self.rbPB.setColor(Qt.red)
                self.rbPD.setColor(Qt.red)
                self.rbPC.setColor(QColor(0, 200, 150, 255))
            else:
                self.rbPA.setColor(Qt.red)
                self.rbPB.setColor(Qt.red)
                self.rbPC.setColor(Qt.red)
                self.rbPD.setColor(QColor(0, 200, 150, 255))

        self.widget.alert.setText("Total plots: {}".format(
            self.widget.columnCount.value() * self.widget.rowCount.value()))
Example #14
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        lobescol = self.parameterAsString(parameters, self.PrmLobesField,
                                          context)
        startanglecol = self.parameterAsString(parameters,
                                               self.PrmStartingAngleField,
                                               context)
        radiuscol = self.parameterAsString(parameters, self.PrmRadiusField,
                                           context)
        radius = self.parameterAsDouble(parameters, self.PrmRadius, context)
        startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle,
                                            context)
        lobes = self.parameterAsInt(parameters, self.PrmLobes, context)
        segments = self.parameterAsInt(parameters, self.PrmDrawingSegments,
                                       context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                    context)
        export_geom = self.parameterAsBool(parameters,
                                           self.PrmExportInputGeometry,
                                           context)

        measureFactor = conversionToMeters(units)
        radius *= measureFactor
        r = radius / lobes

        srcCRS = source.sourceCrs()
        fields = source.fields()
        if export_geom:
            names = fields.names()
            name_x, name_y = settings.getGeomNames(names)
            fields.append(QgsField(name_x, QVariant.Double))
            fields.append(QgsField(name_y, QVariant.Double))
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                                                   self.PrmOutputLayer,
                                                   context, fields,
                                                   QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, fields,
                                             QgsWkbTypes.LineString, srcCRS)

        if srcCRS != epsg4326:
            geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326,
                                                QgsProject.instance())
            toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS,
                                               QgsProject.instance())

        featureCount = source.featureCount()
        total = 100.0 / featureCount if featureCount else 0

        step = 360.0 / segments
        numbad = 0
        iterator = source.getFeatures()
        for index, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                if startanglecol:
                    sangle = float(feature[startanglecol])
                else:
                    sangle = startAngle
                if lobescol:
                    lobes2 = int(feature[lobescol])
                else:
                    lobes2 = lobes
                if radiuscol:
                    radius2 = float(feature[radiuscol]) * measureFactor
                else:
                    radius2 = radius
                r = radius2 / lobes2
            except:
                numbad += 1
                continue
            pts = []
            pt = feature.geometry().asPoint()
            pt_orig_x = pt.x()
            pt_orig_y = pt.y()
            # make sure the coordinates are in EPSG:4326
            if srcCRS != epsg4326:
                pt = geomTo4326.transform(pt.x(), pt.y())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle - sangle)
                x = r * (lobes2 - 1.0) * math.cos(a) + r * math.cos(
                    (lobes2 - 1.0) * a)
                y = r * (lobes2 - 1.0) * math.sin(a) - r * math.sin(
                    (lobes2 - 1.0) * a)
                dist = math.sqrt(x * x + y * y)
                g = geod.Direct(pt.y(), pt.x(), angle, dist,
                                Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += step

            # If the Output crs is not 4326 transform the points to the proper crs
            if srcCRS != epsg4326:
                for x, ptout in enumerate(pts):
                    pts[x] = toSinkCrs.transform(ptout)

            f = QgsFeature()
            if shapetype == 0:
                f.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            else:
                f.setGeometry(QgsGeometry.fromPolylineXY(pts))
            attr = feature.attributes()
            if export_geom:
                attr.append(pt_orig_x)
                attr.append(pt_orig_y)
            f.setAttributes(attr)
            sink.addFeature(f)

            if index % 100 == 0:
                feedback.setProgress(int(index * total))

        return {self.PrmOutputLayer: dest_id}
Example #15
0
def run(bar,layer1_path,layer2_path,obstacles_path,research_ray):

    output = {}
    #layer1 receiver
    layer1 = QgsVectorLayer(layer1_path,"layer1","ogr")
    #layer 2 source
    layer2 = QgsVectorLayer(layer2_path,"layer2","ogr")
    layer2_feat_all_dict = {}
    layer2_feat_all = layer2.dataProvider().getFeatures()
    layer2_spIndex = QgsSpatialIndex()
    for layer2_feat in layer2_feat_all:
        layer2_spIndex.insertFeature(layer2_feat)
        layer2_feat_all_dict[layer2_feat.id()] = layer2_feat


    if obstacles_path is not None:
        obstacles_layer = QgsVectorLayer(obstacles_path,"obstacles","ogr")
        obstacles_feat_all = obstacles_layer.dataProvider().getFeatures()
        obstacles_spIndex = QgsSpatialIndex()
        obstacles_feat_all_dict = {}
        for obstacles_feat in obstacles_feat_all:
            obstacles_spIndex.insertFeature(obstacles_feat)
            obstacles_feat_all_dict[obstacles_feat.id()] = obstacles_feat


    layer1_feat_all = layer1.dataProvider().getFeatures()
    layer1_feat_total = layer1.dataProvider().featureCount()
    layer1_feat_number = 0

    for layer1_feat in layer1_feat_all:

        layer1_feat_number = layer1_feat_number + 1
        barValue = layer1_feat_number/float(layer1_feat_total)*100
        bar.setValue(barValue)

        # researches the layer2 points in a rectangle created by the research_ray
        # creates the search rectangle
        rect = QgsRectangle()
        rect.setXMinimum( layer1_feat.geometry().asPoint().x() - research_ray )
        rect.setXMaximum( layer1_feat.geometry().asPoint().x() + research_ray )
        rect.setYMinimum( layer1_feat.geometry().asPoint().y() - research_ray )
        rect.setYMaximum( layer1_feat.geometry().asPoint().y() + research_ray )

        layer2_request = layer2_spIndex.intersects(rect)

        layer2_points = []

        for layer2_id in layer2_request:

            layer2_feat = layer2_feat_all_dict[layer2_id]

            ray_to_test_length = compute_distance(layer1_feat.geometry().asPoint(),layer2_feat.geometry().asPoint())

            if ray_to_test_length <= research_ray:

                ray_to_test = QgsGeometry.fromPolylineXY( [ layer1_feat.geometry().asPoint() , layer2_feat.geometry().asPoint() ] )

                intersect = 0

                if obstacles_path is not None:
                    obstacles_request = obstacles_spIndex.intersects(ray_to_test.boundingBox())
                    for obstacles_id in obstacles_request:
                        if obstacles_feat_all_dict[obstacles_id].geometry().crosses(ray_to_test) == 1:
                            intersect = 1
                            break

                if intersect == 0:

                    layer2_points.append(layer2_feat.id())

                    output[layer1_feat.id()] = layer2_points

    return output
Example #16
0
    def processAlgorithm(self, parameters, context, feedback):
        if parameters[self.INPUT] == parameters[self.HUBS]:
            raise QgsProcessingException(
                self.tr('Same layer given for both hubs and spokes'))

        point_source = self.parameterAsSource(parameters, self.INPUT, context)
        if point_source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        hub_source = self.parameterAsSource(parameters, self.HUBS, context)
        if hub_source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.HUBS))

        fieldName = self.parameterAsString(parameters, self.FIELD, context)

        units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT,
                                                context)]

        fields = point_source.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

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

        index = QgsSpatialIndex(
            hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(point_source.sourceCrs(),
                                      context.transformContext())))

        distance = QgsDistanceArea()
        distance.setSourceCrs(point_source.sourceCrs(),
                              context.transformContext())
        distance.setEllipsoid(context.project().ellipsoid())

        # Scan source points, find nearest hub, and write to output file
        features = point_source.getFeatures()
        total = 100.0 / point_source.featureCount(
        ) if point_source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                sink.addFeature(f, QgsFeatureSink.FastInsert)
                continue
            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(
                hub_source.getFeatures(QgsFeatureRequest().setFilterFid(
                    neighbors[0]).setSubsetOfAttributes(
                        [fieldName], hub_source.fields()).setDestinationCrs(
                            point_source.sourceCrs(),
                            context.transformContext())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            if units != self.LAYER_UNITS:
                hub_dist_in_desired_units = distance.convertLengthMeasurement(
                    hubDist, units)
            else:
                hub_dist_in_desired_units = hubDist

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            attributes.append(hub_dist_in_desired_units)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPolylineXY([src, closest]))

            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #17
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))
            
        use_ring_count = False;
        fields_or_rings = self.parameterAsString(parameters, self.FIELDS_OR_RINGS, context)
        if (self.is_number(fields_or_rings)):
            ring_num = int(fields_or_rings)
            use_ring_count = True
        else:
            input_fields = fields_or_rings.strip().split(',')
            ring_num = len(input_fields)
            for idx in range(ring_num):
                input_fields[idx] = input_fields[idx].strip()
        if (ring_num == 0):
            raise QgsProcessingException('The count of Rings must be greater than zero')

        ring_value_field = self.parameterAsString(parameters, self.RING_VALUE_FIELD, context)

        self.GAPS = self.parameterAsInt(parameters, self.RING_GAP, context)
        if self.GAPS < 0 or self.GAPS > 10:
            raise QgsProcessingException('The Gap value must be between 0 and 10.')
        
        # calculate layer's extent & feature count
        feature_count = source.featureCount()
        extent = self.calculate_layer_extent(source)

        # create spatial index & convert to points
        (spatial_index, centroid_features) = self.create_spatial_index(source)

        center_point = extent.center(); # QgsPoint

        minx = extent.xMinimum()
        miny = extent.yMinimum()
        maxx = extent.xMaximum()
        maxy = extent.yMaximum()

        radius = (((maxx - minx)**2 + (maxy - miny)**2) **0.5) / 2.0
        radius_interval = radius / ring_num

        ring_fields = source.fields()
        ring_fields.append(QgsField("ring_num", QVariant.Int))
        ring_fields.append(QgsField(ring_value_field, QVariant.Double))
        
        idx_fields = []
        for idx in range(ring_num):
            if (use_ring_count):
                idx_fields.append(-1)
            else:
                idx_fields.append(ring_fields.lookupField(input_fields[idx]))

        (sink_ring, ring_id) = self.parameterAsSink(parameters, self.OUTPUT_RING, context,
                          ring_fields, QgsWkbTypes.Polygon, source.sourceCrs())
        (sink_anchor, anchor_id) = self.parameterAsSink(parameters, self.OUTPUT_ANCHOR, context,
                          source.fields(), QgsWkbTypes.LineString, source.sourceCrs())
                          
        if sink_ring is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT_RING))
        if sink_anchor is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT_ANCHOR))
            
        step_angle = 360.0 / feature_count
        half_step = step_angle / 2.0
        total = 100.0 / feature_count if feature_count else 0

        for idx_side in range(feature_count):
            if feedback.isCanceled():
                break
                
            from_deg = half_step + (idx_side * step_angle)
            to_deg = half_step + ((idx_side + 1) * step_angle)
            default_radius = radius
            
            for idx_radius in range(ring_num):
                cell = self.create_ring_cell(center_point, from_deg, to_deg, default_radius,  default_radius + radius_interval)
                cell_centroid_point = cell.centroid().asPoint()
                
                # find nearest feature & create anchor line
                if (idx_radius == 0):
                    fids = spatial_index.nearestNeighbor(cell_centroid_point, 1)
                    for fid in fids:
                        nearest_feature = centroid_features[fid]
                        nearest_point = nearest_feature.geometry().asPoint()
                        
                        anchor_feature = QgsFeature()
                        anchor_feature.setGeometry(QgsGeometry.fromPolylineXY([nearest_point, cell_centroid_point]))
                        anchor_feature.setAttributes(nearest_feature.attributes())
                        
                        # Add a new feature in the sink
                        sink_anchor.addFeature(anchor_feature, QgsFeatureSink.FastInsert)
                        
                        spatial_index.deleteFeature(nearest_feature)
                
                # create and write ring feature
                ring_feature = QgsFeature(ring_fields)
                ring_feature.setGeometry(cell)
                
                ring_attributes = nearest_feature.attributes()
                ring_attributes.append(idx_radius + 1) # ring_num
                if (idx_fields[idx_radius] == -1):
                    ring_attributes.append(0)  # default value = 0
                else:
                    ring_attributes.append(ring_attributes[idx_fields[idx_radius]]) # ring_val
                ring_feature.setAttributes(ring_attributes)
                
                # Add a new feature in the sink
                sink_ring.addFeature(ring_feature, QgsFeatureSink.FastInsert)
                
                default_radius += radius_interval
            
            # Update the progress bar
            feedback.setProgress(int(idx_side * total))

        # cleanup
        del centroid_features
        
        return {self.OUTPUT_RING: ring_id, self.OUTPUT_ANCHOR: anchor_id}
Example #18
0
 def canvasMoveEvent(self, event):
     if len(self.pointsToDraw) > 0:
         self.rubberband.reset()
         line = [self.pointsToDraw[0], event.mapPoint()]
         self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(line), None)
def epa2gis(inpname):
    plugin_path = os.path.dirname(__file__)
    file_extension = os.path.dirname(inpname)
    inpname = os.path.basename(inpname)
    inp = file_extension + '/' + inpname
    if len(file_extension) == 0:
        inp = inpname
    newpath = file_extension + '/_shapefiles_'
    if not os.path.exists(newpath):
        os.makedirs(newpath)

    iface = qgis.utils.iface
    d.LoadFile(inp)
    d.BinUpdateClass()
    nlinkCount = d.getBinLinkCount()

    res = newpath + '\\'
    saveFile = res + inpname[:len(inpname) - 4]

    # Get all Sections
    mixing = d.getMixingSection()
    reactions = d.getReactionsSection()
    sources = d.getSourcesSection()
    rules = d.getRulesSection()
    quality = d.getQualitySection()
    curves = d.getCurvesSection()
    patterns = d.getPatternsSection()
    controls = d.getControlsSection()
    emitters = d.getEmittersSection()
    status = d.getStatusSection()
    demands = d.getDemandsSection()
    energy = d.getEnergySection()
    optReactions = d.getReactionsOptionsSection()
    times = d.getTimesSection()
    report = d.getReportSection()
    options = d.getOptionsSection()

    # Get all Section lengths
    allSections = [len(energy), len(optReactions), len(demands), len(status), len(emitters), len(controls),
                   len(patterns),
                   len(curves[0]), len(quality), len(rules), len(sources), len(reactions), len(mixing), len(times),
                   len(report),
                   len(options), d.getBinNodeCount(), d.getBinLinkCount()]
    ss = max(allSections)
    root = QgsProject.instance().layerTreeRoot()
    idx = root.insertGroup(0, inpname[:len(inpname) - 4])

    xy = d.getBinNodeCoordinates()
    x = xy[0]
    y = xy[1]
    vertx = xy[2]
    verty = xy[3]
    vertxyFinal = []
    for i in range(len(vertx)):
        vertxy = []
        for u in range(len(vertx[i])):
            vertxy.append([float(vertx[i][u]), float(verty[i][u])])
        if vertxy:
            vertxyFinal.append(vertxy)

    otherDemads = d.getBinNodeBaseDemandsDemSection()
    ndID = d.getBinNodeNameID()
    ndBaseD = d.getBinNodeBaseDemands()
    ndPatID = d.getBinNodeDemandPatternID()
    otherDemadsIndex = []
    otherDemadsPatterns = []
    for i, p in enumerate(otherDemads[1]):
        otherDemadsIndex.append(ndID.index(p))
        otherDemadsPatterns.append(otherDemads[2][i])

    counter = collections.Counter(otherDemadsIndex)
    maxCategories = 1
    if counter:
        maxCategories = max(counter.values())

    if not ndBaseD:
        ndBaseD = otherDemads[0]

    # Get data of Junctions
    if d.getBinNodeJunctionCount() > 0:
        ndBaseTmp = np.empty((len(ndBaseD), maxCategories,))
        ndPatTmp = []
        for t in range(0, maxCategories):
            for u in range(0, len(ndBaseD)):
                ndBaseTmp[u][t] = 0
                ndPatTmp.append(['None'] * 2)

        for uu in range(0, len(ndBaseD)):
            if d.getBinNodeBaseDemands():
                ndBaseTmp[uu][0] = ndBaseD[uu]
                ndPatTmp[uu][0] = ndPatID[uu]
        t = 0
        for i, p in enumerate(otherDemadsIndex):
            if d.getBinNodeBaseDemands():
                ndBaseTmp[p][t] = ndBaseD[otherDemadsIndex[i]]
                ndPatTmp[p][t] = ndPatID[otherDemadsIndex[i]]
            else:
                ndBaseTmp[p][t] = otherDemads[0][i]
                ndPatTmp[p][t] = otherDemads[2][i]
            t = t + 1
            if t > max(counter.values()) - 1:
                t = max(counter.values()) - 1
            if i > 0:
                if otherDemadsIndex[i - 1] == p:
                    ndBaseTmp[p][t] = otherDemads[0][i]
                    ndPatTmp[p][t] = otherDemads[2][i]
                    t = t - 1
        # Write Junction Shapefile
        fields = ["ID", "Elevation"]  # , "pattern", "demand"]
        fieldsCode = [0, 1]
        for u in range(0, maxCategories):
            fields.append('Demand' + str(u + 1))
            fields.append('Pattern' + str(u + 1))
            fieldsCode.append(1)
            fieldsCode.append(0)
        posJunction = QgsVectorLayer("point?crs=EPSG:4326", "Junctions", "memory")
        prJunction = posJunction.dataProvider()
        ndBaseTmp = ndBaseTmp.tolist()

        createColumnsAttrb(prJunction, fields, fieldsCode)
        posJunction.startEditing()
        ndEle = d.getBinNodeJunctionElevations()

    # Get data of Pipes
    # Write shapefile pipe
    if nlinkCount > 0:
        posPipe = QgsVectorLayer("LineString?crs=EPSG:4326", "Pipes", "memory")
        prPipe = posPipe.dataProvider()
        fields = ["ID", "NodeFrom", "NodeTo", "Status", "Length", "Diameter", "Roughness", "MinorLoss"]
        fieldsCode = [0, 0, 0, 0, 1, 1, 1, 1]
        createColumnsAttrb(prPipe, fields, fieldsCode)
        posPipe.startEditing()

        pIndex = d.getBinLinkPumpIndex()
        vIndex = d.getBinLinkValveIndex()
        ndlConn = d.getBinNodesConnectingLinksID()
        x1 = []
        x2 = []
        y1 = []
        y2 = []
        stat = d.getBinLinkInitialStatus()

        kk = 0
        ch = 0
        linkID = d.getBinLinkNameID()
        linkLengths = d.getBinLinkLength()
        linkDiameters = d.getBinLinkDiameter()
        linkRough = d.getBinLinkRoughnessCoeff()
        linkMinorloss = d.getBinLinkMinorLossCoeff()

    # Write Tank Shapefile and get tank data
    posTank = QgsVectorLayer("point?crs=EPSG:4326", "Tanks", "memory")
    prTank = posTank.dataProvider()

    fields = ["ID", "Elevation", "InitLevel", "MinLevel", "MaxLevel", "Diameter", "MinVolume", "VolumeCurve"]
    fieldsCode = [0, 1, 1, 1, 1, 1, 1, 0]
    createColumnsAttrb(prTank, fields, fieldsCode)
    posTank.startEditing()

    if d.getBinNodeTankCount() > 0:
        ndTankelevation = d.getBinNodeTankElevations()
        initiallev = d.getBinNodeTankInitialLevel()
        minimumlev = d.getBinNodeTankMinimumWaterLevel()
        maximumlev = d.getBinNodeTankMaximumWaterLevel()
        diameter = d.getBinNodeTankDiameter()
        minimumvol = d.getBinNodeTankMinimumWaterVolume()
        volumecurv = d.getBinNodeTankVolumeCurveID()
        ndTankID = d.getBinNodeTankNameID()

    # Write Reservoir Shapefile
    posReservoirs = QgsVectorLayer("point?crs=EPSG:4326", "Reservoirs", "memory")
    prReservoirs = posReservoirs.dataProvider()
    fields = ["ID", "Head"]
    fieldsCode = [0, 1]
    createColumnsAttrb(prReservoirs, fields, fieldsCode)
    head = d.getBinNodeReservoirElevations()
    posReservoirs.startEditing()

    if times:
        posTimes = QgsVectorLayer("point?crs=EPSG:4326", "Times", "memory")
        prTimes = posTimes.dataProvider()
    if energy:
        posE = QgsVectorLayer("point?crs=EPSG:4326", "Energy", "memory")
        prE = posE.dataProvider()
    if report:
        posRep = QgsVectorLayer("point?crs=EPSG:4326", "Report", "memory")
        prRep = posRep.dataProvider()
    if options:
        posOpt = QgsVectorLayer("point?crs=EPSG:4326", "Options", "memory")
        prOpt = posOpt.dataProvider()
    if optReactions:
        posO = QgsVectorLayer("point?crs=EPSG:4326", "Reactions", "memory")
        prO = posO.dataProvider()

    ppE = []
    ppO = []
    ppTimes = []
    ppRep = []
    ppOpt = []
    ppMix = []
    ppReactions = []
    ppSourc = []
    ppRul = []
    ppPat = []
    ppQual = []
    ppDem = []
    ppStat = []
    ppEmit = []
    ppCont = []
    ppCurv = []

    for i in range(ss):
        if i < d.getBinNodeJunctionCount():
            featJ = QgsFeature()
            point = QgsPointXY(float(x[i]), float(y[i]))
            featJ.initAttributes(2 + len(ndBaseTmp[0]) * 2)
            featJ.setGeometry(QgsGeometry.fromPointXY(point))
            featJ.setAttribute(0, ndID[i])
            featJ.setAttribute(1, ndEle[i])
            w = 2
            for j in range(0, len(ndBaseTmp[0])):
                featJ.setAttribute(w, ndBaseTmp[i][j])
                featJ.setAttribute(w + 1, ndPatTmp[i][j])
                w = w + 2
            prJunction.addFeatures([featJ])

        if i < nlinkCount:
            if len(stat) == i:
                ch = 1
            if ch == 1:
                stat.append('OPEN')

            x1.append(x[ndID.index(d.getBinLinkFromNode()[i])])
            y1.append(y[ndID.index(d.getBinLinkFromNode()[i])])
            x2.append(x[ndID.index(d.getBinLinkToNode()[i])])
            y2.append(y[ndID.index(d.getBinLinkToNode()[i])])

            if i in pIndex:
                pass
            elif i in vIndex:
                pass
            else:
                point1 = QgsPointXY(float(x1[i]), float(y1[i]))
                point2 = QgsPointXY(float(x2[i]), float(y2[i]))
                featPipe = QgsFeature()
                if vertx[i]:
                    parts = []
                    parts.append(point1)
                    for mm in range(len(vertxyFinal[kk])):
                        a = vertxyFinal[kk][mm]
                        parts.append(QgsPointXY(a[0], a[1]))
                    parts.append(point2)
                    featPipe.setGeometry((QgsGeometry.fromPolylineXY(parts)))
                    kk = kk + 1
                else:
                    featPipe.setGeometry(QgsGeometry.fromPolylineXY([point1, point2]))

                featPipe.setAttributes(
                    [linkID[i], ndlConn[0][i], ndlConn[1][i], stat[i], linkLengths[i], linkDiameters[i], linkRough[i],
                     linkMinorloss[i]])
                prPipe.addFeatures([featPipe])

        if i < d.getBinNodeTankCount():
            p = d.getBinNodeTankIndex()[i] - 1
            featTank = QgsFeature()
            point = QgsPointXY(float(x[p]), float(y[p]))
            featTank.setGeometry(QgsGeometry.fromPointXY(point))
            featTank.setAttributes(
                [ndTankID[i], ndTankelevation[i], initiallev[i], minimumlev[i], maximumlev[i], diameter[i],
                 minimumvol[i], volumecurv[i]])
            prTank.addFeatures([featTank])

        if i < d.getBinNodeReservoirCount():
            p = d.getBinNodeReservoirIndex()[i] - 1
            feature = QgsFeature()
            point = QgsPointXY(float(x[p]), float(y[p]))
            feature.setGeometry(QgsGeometry.fromPointXY(point))
            feature.setAttributes([ndID[p], head[i]])
            prReservoirs.addFeatures([feature])

        if i < allSections[12]:
            if len(mixing[i]) == 3:
                ppMix.append([mixing[i][0], mixing[i][1], mixing[i][2]])
            else:
                ppMix.append([mixing[i][0], mixing[i][1]])
        if i < allSections[11]:
            ppReactions.append([reactions[i][0], reactions[i][1], reactions[i][2]])
        if i < allSections[10]:
            if len(sources[i]) == 4:
                ppSourc.append([sources[i][0], sources[i][1], sources[i][2], sources[i][3]])
            elif len(sources[i]) == 3:
                ppSourc.append([sources[i][0], sources[i][1], sources[i][2]])
            else:
                ppSourc.append([sources[i][0], sources[i][1]])

        if i < allSections[9]:
            if len(rules[i]) > 2:
                ppRul.append([rules[i][0][1][1], rules[i][1][0] + rules[i][2][0] + rules[i][3][0]])
        if i < allSections[8]:
            ppQual.append([quality[i][0], quality[i][1]])
        if i < allSections[7]:
            ppCurv.append([str(curves[0][i][0]), str(curves[0][i][1]), str(curves[0][i][2]), str(curves[1][i])])
        if i < allSections[6]:
            ppPat.append([patterns[i][0], str(patterns[i][1])])
        if i < allSections[5]:
            ppCont.append([controls[i]])
        if i < allSections[4]:
            ppEmit.append([emitters[i][0], emitters[i][1]])
        if i < allSections[3]:
            ppStat.append([status[i][0], status[i][1]])
        if i < allSections[2]:
            if len(demands[i]) > 2:
                ppDem.append([demands[i][0], demands[i][1], demands[i][2]])
        if i < allSections[0]:
            mm = energy[i][0]
            if mm.upper() == "GLOBAL":
                prE.addAttributes([QgsField("Global" + energy[i][1], QVariant.String)])
                if len(energy[i]) > 2:
                    ppE.append(energy[i][2])
                else:
                    ppE.append('')
            if mm.upper() == "PUMP":
                prE.addAttributes([QgsField("Pump", QVariant.String)])
                if len(energy[i]) > 2:
                    ppE.append(energy[i][1] + ' ' + energy[i][2])
                else:
                    ppE.append(energy[i][1])
            elif mm.upper() == "DEMAND":
                if energy[i][1].upper() == "CHARGE":
                    prE.addAttributes([QgsField("DemCharge", QVariant.String)])
                    if len(energy[i]) > 2:
                        ppE.append(energy[i][2])
        if i < allSections[1]:
            mm = optReactions[i][0]
            if mm.upper() == "ORDER":
                prO.addAttributes([QgsField("Order" + optReactions[i][1], QVariant.String)])
                if len(optReactions[i]) > 2:
                    ppO.append(optReactions[i][2])
                else:
                    ppO.append('')
            elif mm.upper() == "GLOBAL":
                prO.addAttributes([QgsField("Global" + optReactions[i][1], QVariant.String)])
                if len(optReactions[i]) > 2:
                    ppO.append(optReactions[i][2])
                else:
                    ppO.append('')
            elif mm.upper() == "BULK":
                prO.addAttributes([QgsField("Bulk", QVariant.String)])
                if len(optReactions[i]) > 2:
                    ppO.append(optReactions[i][1] + ' ' + optReactions[i][2])
                else:
                    ppO.append(optReactions[i][1])
            elif mm.upper() == "WALL":
                prO.addAttributes([QgsField("Wall", QVariant.String)])
                if len(optReactions[i]) > 2:
                    ppO.append(optReactions[i][1] + ' ' + optReactions[i][2])
                else:
                    ppO.append(optReactions[i][1])
            elif mm.upper() == "TANK":
                prO.addAttributes([QgsField("Tank", QVariant.String)])
                if len(optReactions[i]) > 2:
                    ppO.append(optReactions[i][1] + ' ' + optReactions[i][2])
                else:
                    ppO.append(optReactions[i][1])
            elif mm.upper() == "LIMITING":
                if optReactions[i][1].upper() == "POTENTIAL":
                    prO.addAttributes([QgsField("LimPotent", QVariant.String)])
                    if len(optReactions[i]) > 2:
                        ppO.append(optReactions[i][2])
            elif mm.upper() == "ROUGHNESS":
                if optReactions[i][1].upper() == "CORRELATION":
                    prO.addAttributes([QgsField("RoughCorr", QVariant.String)])
                    if len(optReactions[i]) > 2:
                        ppO.append(optReactions[i][2])
        if i < allSections[13]:
            mm = times[i][0]
            if mm.upper() == "DURATION":
                prTimes.addAttributes([QgsField("Duration", QVariant.String)])
                ppTimes.append(times[i][1])
            if mm.upper() == "HYDRAULIC":
                prTimes.addAttributes([QgsField("HydStep", QVariant.String)])
                ppTimes.append(times[i][2])
            elif mm.upper() == "QUALITY":
                prTimes.addAttributes([QgsField("QualStep", QVariant.String)])
                ppTimes.append(times[i][2])
            elif mm.upper() == "RULE":
                prTimes.addAttributes([QgsField("RuleStep", QVariant.String)])
                ppTimes.append(times[i][2])
            elif mm.upper() == "PATTERN":
                if times[i][1].upper() == "TIMESTEP":
                    prTimes.addAttributes([QgsField("PatStep", QVariant.String)])
                    ppTimes.append(times[i][2])
                if times[i][1].upper() == "START":
                    prTimes.addAttributes([QgsField("PatStart", QVariant.String)])
                    ppTimes.append(times[i][2])
            elif mm.upper() == "REPORT":
                if times[i][1].upper() == "TIMESTEP":
                    prTimes.addAttributes([QgsField("RepStep", QVariant.String)])
                    ppTimes.append(times[i][2])
                if times[i][1].upper() == "START":
                    prTimes.addAttributes([QgsField("RepStart", QVariant.String)])
                    ppTimes.append(times[i][2])
            elif mm.upper() == "START":
                if times[i][1].upper() == "CLOCKTIME":
                    prTimes.addAttributes([QgsField("StartClock", QVariant.String)])
                    if len(times[i]) > 3:
                        ppTimes.append(times[i][2] + ' ' + times[i][3])
                    else:
                        ppTimes.append(times[i][2])
            elif mm.upper() == "STATISTIC":
                prTimes.addAttributes([QgsField("Statistic", QVariant.String)])
                if times[i][1].upper() == 'NONE' or times[i][1].upper() == 'AVERAGE' or times[i][1].upper() \
                        == 'MINIMUM' or times[i][1].upper() == 'MAXIMUM' or times[i][1].upper() == 'RANGE':
                    ppTimes.append(times[i][1])
        if i < allSections[14]:
            mm = report[i][0]
            if mm.upper() == "PAGESIZE":
                prRep.addAttributes([QgsField("PageSize", QVariant.String)])
                ppRep.append(report[i][1])
            if mm.upper() == "FILE":
                prRep.addAttributes([QgsField("FileName", QVariant.String)])
                ppRep.append(report[i][1])
            elif mm.upper() == "STATUS":
                prRep.addAttributes([QgsField("Status", QVariant.String)])
                ppRep.append(report[i][1])
            elif mm.upper() == "SUMMARY":
                prRep.addAttributes([QgsField("Summary", QVariant.String)])
                ppRep.append(report[i][1])
            elif mm.upper() == "ENERGY":
                prRep.addAttributes([QgsField("Energy", QVariant.String)])
                ppRep.append(report[i][1])
            elif mm.upper() == "NODES":
                prRep.addAttributes([QgsField("Nodes", QVariant.String)])
                if len(report[i]) > 2:
                    ppRep.append(report[i][1] + ' ' + report[i][2])
                else:
                    ppRep.append(report[i][1])
            elif mm.upper() == "LINKS":
                prRep.addAttributes([QgsField("Links", QVariant.String)])
                if len(report[i]) > 2:
                    ppRep.append(report[i][1] + ' ' + report[i][2])
                else:
                    ppRep.append(report[i][1])
            else:
                prRep.addAttributes([QgsField(mm, QVariant.String)])
                if len(report[i]) > 2:
                    ppRep.append(report[i][1] + ' ' + report[i][2])
                else:
                    ppRep.append(report[i][1])
        if i < allSections[15]:
            mm = options[i][0]
            if mm.upper() == "UNITS":
                prOpt.addAttributes([QgsField("Units", QVariant.String)])
                ppOpt.append(options[i][1])
            if mm.upper() == "HYDRAULICS":
                prOpt.addAttributes([QgsField("Hydraulics", QVariant.String)])
                if len(options[i]) > 2:
                    ppOpt.append(options[i][1] + ' ' + options[i][2])
                else:
                    ppOpt.append(options[i][1])
            elif mm.upper() == "QUALITY":
                prOpt.addAttributes([QgsField("Quality", QVariant.String)])
                if len(options[i]) > 2:
                    ppOpt.append(options[i][1] + ' ' + options[i][2])
                elif len(options[i]) > 3:
                    ppOpt.append(options[i][1] + ' ' + options[i][2] + ' ' + options[i][3])
                else:
                    ppOpt.append(options[i][1])
            elif mm.upper() == "VISCOSITY":
                prOpt.addAttributes([QgsField("Viscosity", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "DIFFUSIVITY":
                prOpt.addAttributes([QgsField("Diffusivity", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "SPECIFIC":
                if options[i][1].upper() == "GRAVITY":
                    prOpt.addAttributes([QgsField("SpecGrav", QVariant.String)])
                    ppOpt.append(options[i][2])
            elif mm.upper() == "TRIALS":
                prOpt.addAttributes([QgsField("Trials", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "HEADLOSS":
                prOpt.addAttributes([QgsField("Headloss", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "ACCURACY":
                prOpt.addAttributes([QgsField("Accuracy", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "UNBALANCED":
                prOpt.addAttributes([QgsField("Unbalanced", QVariant.String)])
                if len(options[i]) > 2:
                    ppOpt.append(options[i][1] + ' ' + options[i][2])
                else:
                    ppOpt.append(options[i][1])
            elif mm.upper() == "PATTERN":
                prOpt.addAttributes([QgsField("PatID", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "TOLERANCE":
                prOpt.addAttributes([QgsField("Tolerance", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "MAP":
                prOpt.addAttributes([QgsField("Map", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "DEMAND":
                if options[i][1].upper() == "MULTIPLIER":
                    prOpt.addAttributes([QgsField("DemMult", QVariant.String)])
                    ppOpt.append(options[i][2])
            elif mm.upper() == "EMITTER":
                if options[i][1].upper() == "EXPONENT":
                    prOpt.addAttributes([QgsField("EmitExp", QVariant.String)])
                    ppOpt.append(options[i][2])
            elif mm.upper() == "CHECKFREQ":
                prOpt.addAttributes([QgsField("CheckFreq", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "MAXCHECK":
                prOpt.addAttributes([QgsField("MaxCheck", QVariant.String)])
                ppOpt.append(options[i][1])
            elif mm.upper() == "DAMPLIMIT":
                prOpt.addAttributes([QgsField("DampLimit", QVariant.String)])
                ppOpt.append(options[i][1])

    writeDBF(posOpt, [ppOpt], prOpt, saveFile, inpname, "_OPTIONS", idx)

    writeDBF(posRep, [ppRep], prRep, saveFile, inpname, "_REPORT", idx)

    #if times:
    writeDBF(posTimes, [ppTimes], prTimes, saveFile, inpname, "_TIMES", idx)

    #if energy:
    writeDBF(posE, [ppE], prE, saveFile, inpname, "_ENERGY", idx)

    #if optReactions:
    writeDBF(posO, [ppO], prO, saveFile, inpname, "_REACTIONS", idx)

    posMix = QgsVectorLayer("point?crs=EPSG:4326", "Mixing", "memory")
    prMix = posMix.dataProvider()
    fields = ["Tank_ID", "Model", "Fraction"]
    fieldsCode = [0, 0, 1]  # 0 String, 1 Double
    createColumnsAttrb(prMix, fields, fieldsCode)
    writeDBF(posMix, ppMix, prMix, saveFile, inpname, "_MIXING", idx)

    posReact = QgsVectorLayer("point?crs=EPSG:4326", "ReactionsI", "memory")
    prReact = posReact.dataProvider()
    fields = ["Type", "Pipe/Tank", "Coeff."]
    fieldsCode = [0, 0, 1]
    createColumnsAttrb(prReact, fields, fieldsCode)
    writeDBF(posReact, ppReactions, prReact, saveFile, inpname, "_REACTIONS_I", idx)

    posSourc = QgsVectorLayer("point?crs=EPSG:4326", "Sources", "memory")
    prSourc = posSourc.dataProvider()
    fields = ["Node_ID", "Type", "Strength", "Pattern"]
    fieldsCode = [0, 0, 1, 0]
    createColumnsAttrb(prSourc, fields, fieldsCode)
    writeDBF(posSourc, ppSourc, prSourc, saveFile, inpname, "_SOURCES", idx)

    posRul = QgsVectorLayer("point?crs=EPSG:4326", "Rules", "memory")
    prRul = posRul.dataProvider()
    fields = ["Rule_ID", "Rule"]
    fieldsCode = [0, 0]
    createColumnsAttrb(prRul, fields, fieldsCode)
    writeDBF(posRul, ppRul, prRul, saveFile, inpname, "_RULES", idx)

    posQual = QgsVectorLayer("point?crs=EPSG:4326", "Sources", "memory")
    prQual = posQual.dataProvider()
    fields = ["Node_ID", "Init_Qual"]
    fieldsCode = [0, 1]
    createColumnsAttrb(prQual, fields, fieldsCode)
    writeDBF(posQual, ppQual, prQual, saveFile, inpname, "_QUALITY", idx)

    posStat = QgsVectorLayer("point?crs=EPSG:4326", "Status", "memory")
    prStat = posStat.dataProvider()
    fields = ["Link_ID", "Status/Setting"]
    fieldsCode = [0, 0]
    createColumnsAttrb(prStat, fields, fieldsCode)
    writeDBF(posStat, ppStat, prStat, saveFile, inpname, "_STATUS", idx)

    posEmit = QgsVectorLayer("point?crs=EPSG:4326", "Emitters", "memory")
    prEmit = posEmit.dataProvider()
    fields = ["Junc_ID", "Coeff."]
    fieldsCode = [0, 1]
    createColumnsAttrb(prEmit, fields, fieldsCode)
    writeDBF(posEmit, ppEmit, prEmit, saveFile, inpname, "_EMITTERS", idx)

    posCont = QgsVectorLayer("point?crs=EPSG:4326", "Controls", "memory")
    prCont = posCont.dataProvider()
    fields = ["Controls"]
    fieldsCode = [0]
    createColumnsAttrb(prCont, fields, fieldsCode)
    writeDBF(posCont, ppCont, prCont, saveFile, inpname, "_CONTROLS", idx)

    posPat = QgsVectorLayer("point?crs=EPSG:4326", "Patterns", "memory")
    prPat = posPat.dataProvider()
    fields = ["Pattern_ID", "Multipliers"]
    fieldsCode = [0, 0]
    createColumnsAttrb(prPat, fields, fieldsCode)
    writeDBF(posPat, ppPat, prPat, saveFile, inpname, "_PATTERNS", idx)

    posCurv = QgsVectorLayer("point?crs=EPSG:4326", "Curves", "memory")
    prCurv = posCurv.dataProvider()
    fields = ["Curve_ID", "X-Value", "Y-Value", "Type"]
    fieldsCode = [0, 0, 0, 0]
    createColumnsAttrb(prCurv, fields, fieldsCode)
    writeDBF(posCurv, ppCurv, prCurv, saveFile, inpname, "_CURVES", idx)

    # Write Valve Shapefile
    posValve = QgsVectorLayer("LineString?crs=EPSG:4326", "Valve", "memory")
    prValve = posValve.dataProvider()

    fields = ["ID", "NodeFrom", "NodeTo", "Diameter", "Type", "Setting", "MinorLoss"]
    fieldsCode = [0, 0, 0, 1, 0, 1, 1]
    createColumnsAttrb(prValve, fields, fieldsCode)
    posValve.startEditing()

    if d.getBinLinkValveCount() > 0:

        linkID = d.getBinLinkValveNameID()
        linkType = d.getBinLinkValveType()  # valve type
        linkDiameter = d.getBinLinkValveDiameters()
        linkInitSett = d.getBinLinkValveSetting()  # BinLinkValveSetting
        linkMinorloss = d.getBinLinkValveMinorLoss()

        for i, p in enumerate(d.getBinLinkValveIndex()):
            point1 = QgsPointXY(float(x[ndID.index(d.getBinLinkFromNode()[p])]), float(y[ndID.index(d.getBinLinkFromNode()[p])]))
            point2 = QgsPointXY(float(x[ndID.index(d.getBinLinkToNode()[p])]), float(y[ndID.index(d.getBinLinkToNode()[p])]))
            feature = QgsFeature()
            feature.setGeometry(QgsGeometry.fromPolylineXY([point1, point2]))

            feature.setAttributes(
                [linkID[i], ndlConn[0][p], ndlConn[1][p], linkDiameter[i], linkType[i], linkInitSett[i],
                 linkMinorloss[i]])
            prValve.addFeatures([feature])

    QgsVectorFileWriter.writeAsVectorFormat(posValve, saveFile + "_valves" + '.shp', "utf-8",
                                            QgsCoordinateReferenceSystem(posValve.crs().authid()), "ESRI Shapefile")
    ll = QgsVectorLayer(saveFile + "_valves" + '.shp', inpname[:len(inpname) - 4] + "_valves", "ogr")
    QgsProject.instance().addMapLayer(ll, False)
    nvalves = QgsLayerTreeLayer(ll)
    idx.insertChildNode(0, nvalves)
    nvalves.setCustomProperty("showFeatureCount", True)
    ll.loadNamedStyle(plugin_path + "/qmls/" + 'valvesline' + ".qml")
    ll.triggerRepaint()

    # Write Pump Shapefile
    posPump = QgsVectorLayer("LineString?crs=EPSG:4326", "Pump", "memory")
    prPump = posPump.dataProvider()
    fields = ["ID", "NodeFrom", "NodeTo", "Power", "Pattern", "Curve"]
    fieldsCode = [0, 0, 0, 0, 0, 0]
    createColumnsAttrb(prPump, fields, fieldsCode)
    posPump.startEditing()

    if d.getBinLinkPumpCount() > 0:
        curveXY = d.getBinCurvesXY()
        curvesID = d.getBinCurvesNameID()

        a = curvesID
        b = []
        for l in a:
            if l not in b:
                b.append(l)
        curvesIDunique = b
        CurvesTmpIndices = []
        for p in range(0, len(curvesIDunique)):
            CurvesTmpIndices.append(curvesID.count(curvesIDunique[p]))

        curveIndices = []
        Curve = d.getBinLinkPumpCurveNameID()
        for i in range(len(Curve)):
            curveIndices.append(curvesIDunique.index(Curve[i]))
        if d.getBinCurveCount():
            CurvesTmpIndicesFinal = []
            CurvesTmpIndicesFinal.append([CurvesTmpIndices[index] for index in curveIndices])

            CurvesTmp = []
            i = 0
            for u in range(max(CurvesTmpIndicesFinal[0])):
                fields.append('Head' + str(u + 1))
                fields.append('Flow' + str(u + 1))
                fieldsCode.append(1)
                fieldsCode.append(1)
                if u < d.getBinCurveCount():
                    tmp1 = []
                    for p in range(CurvesTmpIndices[u]):
                        tmp1.append([curveXY[i][0], curveXY[i][1]])
                        i = i + 1
                    CurvesTmp.append(tmp1)

        createColumnsAttrb(prPump, fields, fieldsCode)

        chPowerPump = d.getBinLinkPumpPower()
        pumpID = d.getBinLinkPumpNameID()
        patternsIDs = d.getBinLinkPumpPatterns()
        ppatt = d.getBinLinkPumpPatternsPumpID()
        linkID = d.getBinLinkNameID()

        for i, p in enumerate(d.getBinLinkPumpIndex()):

            Curve = []
            power = []
            pattern = []
            pumpNameIDPower = d.getBinLinkPumpNameIDPower()
            if len(pumpNameIDPower) > 0:
                for uu in range(0, len(pumpNameIDPower)):
                    if pumpNameIDPower[uu] == pumpID[i]:
                        power = chPowerPump[uu]
            if len(patternsIDs) > 0:
                for uu in range(0, len(ppatt)):
                    if ppatt[uu] == pumpID[i]:
                        pattern = patternsIDs[uu]

            point1 = QgsPointXY(float(x[ndID.index(d.getBinLinkFromNode()[p])]), float(y[ndID.index(d.getBinLinkFromNode()[p])]))
            point2 = QgsPointXY(float(x[ndID.index(d.getBinLinkToNode()[p])]), float(y[ndID.index(d.getBinLinkToNode()[p])]))
            feature = QgsFeature()
            feature.setGeometry(QgsGeometry.fromPolylineXY([point1, point2]))

            if not Curve:
                Curve = 'NULL'
            if not power:
                power = 'NULL'
            if not pattern:
                pattern = 'NULL'

            if d.getBinCurveCount() > 0 and len(pumpNameIDPower) == 0:
                Curve = d.getBinLinkPumpCurveNameID()[i]
                curveIndex = curvesIDunique.index(Curve)

            feature.initAttributes(6 + sum(CurvesTmpIndices) * 2 + 1)
            feature.setAttribute(0, linkID[p])
            feature.setAttribute(1, ndlConn[0][p])
            feature.setAttribute(2, ndlConn[1][p])
            feature.setAttribute(3, power)
            feature.setAttribute(4, pattern)
            feature.setAttribute(5, Curve)

            if d.getBinCurveCount() == 1:
                w = 6
                for p in range(CurvesTmpIndices[curveIndex]):
                    feature.setAttribute(w, CurvesTmp[curveIndex][p][0])
                    feature.setAttribute(w + 1, CurvesTmp[curveIndex][p][1])
                    w = w + 2

            for j in range(d.getBinCurveCount() - 1):
                w = 6
                for p in range(CurvesTmpIndices[curveIndex]):
                    feature.setAttribute(w, CurvesTmp[curveIndex][p][0])
                    feature.setAttribute(w + 1, CurvesTmp[curveIndex][p][1])
                    w = w + 2

            prPump.addFeatures([feature])

    QgsVectorFileWriter.writeAsVectorFormat(posPump,saveFile+"_pumps"+'.shp', "utf-8",
                                            QgsCoordinateReferenceSystem(posPump.crs().authid()), "ESRI Shapefile")
    ll = QgsVectorLayer(saveFile + "_pumps" + '.shp', inpname[:len(inpname) - 4] + "_pumps", "ogr")
    QgsProject.instance().addMapLayer(ll, False)
    npump = QgsLayerTreeLayer(ll)
    idx.insertChildNode(0, npump)
    npump.setCustomProperty("showFeatureCount", True)
    ll.loadNamedStyle(plugin_path + "/qmls/" + 'pumpsline' + ".qml")
    ll.triggerRepaint()

    QgsVectorFileWriter.writeAsVectorFormat(posPipe,saveFile+"_pipes"+'.shp', "utf-8",
                                            QgsCoordinateReferenceSystem(posPipe.crs().authid()), "ESRI Shapefile")
    ll = QgsVectorLayer(saveFile + "_pipes" + '.shp', inpname[:len(inpname) - 4] + "_pipes", "ogr")
    QgsProject.instance().addMapLayer(ll, False)
    npipe = QgsLayerTreeLayer(ll)
    idx.insertChildNode(0, npipe)
    npipe.setCustomProperty("showFeatureCount", True)
    ll.loadNamedStyle(plugin_path + "/qmls/" + 'pipes' + ".qml")
    ll.triggerRepaint()
    iface.mapCanvas().setExtent(ll.extent())

    QgsVectorFileWriter.writeAsVectorFormat(posJunction,saveFile+"_junctions"+'.shp', "utf-8",
                                            QgsCoordinateReferenceSystem(posJunction.crs().authid()), "ESRI Shapefile")
    ll = QgsVectorLayer(saveFile + "_junctions" + '.shp', inpname[:len(inpname) - 4] + "_junctions", "ogr")
    QgsProject.instance().addMapLayer(ll, False)
    njunc = QgsLayerTreeLayer(ll)
    idx.insertChildNode(0, njunc)
    njunc.setCustomProperty("showFeatureCount", True)
    ll.loadNamedStyle(plugin_path + "/qmls/" + 'junctions' + ".qml")
    ll.triggerRepaint()

    QgsVectorFileWriter.writeAsVectorFormat(posTank, saveFile + "_tanks" + '.shp', "utf-8",
                                            QgsCoordinateReferenceSystem(posTank.crs().authid()), "ESRI Shapefile")
    ll = QgsVectorLayer(saveFile + "_tanks" + '.shp', inpname[:len(inpname) - 4] + "_tanks", "ogr")
    QgsProject.instance().addMapLayer(ll, False)
    ntanks = QgsLayerTreeLayer(ll)
    idx.insertChildNode(0, ntanks)
    ntanks.setCustomProperty("showFeatureCount", True)
    ll.loadNamedStyle(plugin_path + "/qmls/" + 'tanks' + ".qml")
    ll.triggerRepaint()

    QgsVectorFileWriter.writeAsVectorFormat(posReservoirs, saveFile + "_reservoirs" + '.shp', "utf-8",
                                            QgsCoordinateReferenceSystem(posReservoirs.crs().authid()), "ESRI Shapefile")
    ll = QgsVectorLayer(saveFile + "_reservoirs" + '.shp', inpname[:len(inpname) - 4] + "_reservoirs", "ogr")
    QgsProject.instance().addMapLayer(ll, False)
    nres = QgsLayerTreeLayer(ll)
    idx.insertChildNode(0, nres)
    nres.setCustomProperty("showFeatureCount", True)
    ll.loadNamedStyle(plugin_path + "/qmls/" + 'reservoirs' + ".qml")
    ll.triggerRepaint()
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        sidescol = self.parameterAsString(parameters,
                                          self.PrmNumberOfSidesField, context)
        anglecol = self.parameterAsString(parameters,
                                          self.PrmStartingAngleField, context)
        distcol = self.parameterAsString(parameters, self.PrmRadiusField,
                                         context)
        sides = self.parameterAsInt(parameters, self.PrmDefaultNumberOfSides,
                                    context)
        angle = self.parameterAsDouble(parameters,
                                       self.PrmDefaultStartingAngle, context)
        defaultDist = self.parameterAsInt(parameters, self.PrmDefaultRadius,
                                          context)
        unitOfDist = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                         context)
        export_geom = self.parameterAsBool(parameters,
                                           self.PrmExportInputGeometry,
                                           context)

        measureFactor = conversionToMeters(unitOfDist)

        defaultDist *= measureFactor

        srcCRS = source.sourceCrs()
        fields = source.fields()
        if export_geom:
            names = fields.names()
            name_x, name_y = settings.getGeomNames(names)
            fields.append(QgsField(name_x, QVariant.Double))
            fields.append(QgsField(name_y, QVariant.Double))
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                                                   self.PrmOutputLayer,
                                                   context, fields,
                                                   QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, fields,
                                             QgsWkbTypes.LineString, srcCRS)

        if srcCRS != epsg4326:
            geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326,
                                                QgsProject.instance())
            toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS,
                                               QgsProject.instance())

        featureCount = source.featureCount()
        total = 100.0 / featureCount if featureCount else 0

        iterator = source.getFeatures()
        numbad = 0
        for cnt, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                pt = feature.geometry().asPoint()
                pt_orig_x = pt.x()
                pt_orig_y = pt.y()
                if srcCRS != epsg4326:
                    pt = geomTo4326.transform(pt.x(), pt.y())
                if sidescol:
                    s = int(feature[sidescol])
                else:
                    s = sides
                if anglecol:
                    startangle = float(feature[anglecol])
                else:
                    startangle = angle
                if distcol:
                    d = float(feature[distcol]) * measureFactor
                else:
                    d = defaultDist
                pts = []
                i = s
                while i >= 0:
                    a = (i * 360.0 / s) + startangle
                    i -= 1
                    g = geod.Direct(pt.y(), pt.x(), a, d,
                                    Geodesic.LATITUDE | Geodesic.LONGITUDE)
                    pts.append(QgsPointXY(g['lon2'], g['lat2']))

                # If the Output crs is not 4326 transform the points to the proper crs
                if srcCRS != epsg4326:
                    for x, ptout in enumerate(pts):
                        pts[x] = toSinkCrs.transform(ptout)

                f = QgsFeature()
                if shapetype == 0:
                    f.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                else:
                    f.setGeometry(QgsGeometry.fromPolylineXY(pts))
                attr = feature.attributes()
                if export_geom:
                    attr.append(pt_orig_x)
                    attr.append(pt_orig_y)
                f.setAttributes(attr)
                sink.addFeature(f)
            except:
                numbad += 1

            if cnt % 100 == 0:
                feedback.setProgress(int(cnt * total))

        if numbad > 0:
            feedback.pushInfo(
                tr("{} out of {} features had invalid parameters and were ignored."
                   .format(numbad, featureCount)))

        return {self.PrmOutputLayer: dest_id}
Example #21
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        rep_GTFS = self.parameterAsFile(parameters, self.REP_GTFS, context)
        debut_periode=self.parameterAsString(parameters,self.DEBUT_PERIODE,context)
        fin_periode=self.parameterAsString(parameters,self.FIN_PERIODE,context)
        t1=self.parameterAsString(parameters,self.T1,context)
        t2=self.parameterAsString(parameters,self.T2,context)
        prefixe=self.parameterAsString(parameters,self.PREFIXE,context)
        proj=self.parameterAsCrs(parameters,self.PROJ,context)
        rep_sortie = self.parameterAsFile(parameters, self.REP_SORTIE, context)
        encodage = self.parameterAsString(parameters, self.ENCODAGE, context)


        debut_periode=QDate.fromString(debut_periode, "d/M/yyyy").toPyDate()
        fin_periode=QDate.fromString(fin_periode, "d/M/yyyy").toPyDate()


        t1=QTime.fromString(t1,"h:m:s")
        t2=QTime.fromString(t2,"h:m:s")
        nom_rep=rep_GTFS
        lname=prefixe
        isnodes=True
        islines=True


        if "stops.txt" in os.listdir(nom_rep) :
            fich_noeuds=io.open(nom_rep+"/stops.txt","r",encoding=encodage)
            t_noeuds=QgsFields()
            t_noeuds.append(QgsField(self.tr("ident"),QVariant.String,len=15))
            t_noeuds.append(QgsField(self.tr("name"),QVariant.String,len=40))
            t_noeuds.append(QgsField(self.tr("arrivals"),QVariant.Double))
            t_noeuds.append(QgsField(self.tr("departures"),QVariant.Double))
            
            t_links=QgsFields()
            t_links.append(QgsField(self.tr("line_num"),QVariant.String,len=15))
            t_links.append(QgsField(self.tr("ligne_name"),QVariant.String,len=50))
            t_links.append(QgsField("i",QVariant.String,len=15))
            t_links.append(QgsField("j",QVariant.String,len=15))
            t_links.append(QgsField(self.tr("lines_count"),QVariant.Int))
            t_links.append(QgsField(self.tr("services_count"),QVariant.Int))
            t_links.append(QgsField("delta1",QVariant.Int))
            t_links.append(QgsField("delta2",QVariant.Int))
            
            src=QgsCoordinateReferenceSystem("EPSG:4326")
            dest=QgsCoordinateReferenceSystem(proj)
            xtr=QgsCoordinateTransform(src,dest,QgsProject.instance())
                
            t_arcs=QgsFields()
            t_arcs.append(QgsField("i",QVariant.String,len=15))
            t_arcs.append(QgsField("j",QVariant.String,len=15))
            t_arcs.append(QgsField("ij",QVariant.String,len=40))
            l_noeuds=QgsVectorFileWriter(rep_sortie+"/"+lname+"_stops.shp","UTF-8",t_noeuds,QgsWkbTypes.Point,dest,"ESRI Shapefile")
            l_arcs=QgsVectorFileWriter(rep_sortie+"/"+lname+"_arcs.shp","UTF-8",t_arcs,QgsWkbTypes.MultiLineString,dest,"ESRI Shapefile")
            l_links=QgsVectorFileWriter(rep_sortie+"/"+lname+"_lines.shp","UTF-8",t_links,QgsWkbTypes.MultiLineString,dest,"ESRI Shapefile")
            
            
            arrets={}
            feedback.setProgressText("Lecture des stops")
            for i,ligne in enumerate(fich_noeuds):
                if i==0:
                    entete=re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",ligne[:-1])
                    for e1,e in enumerate(entete):
                        entete[e1]=entete[e1].strip("\"")
                    idx=entete.index('stop_lon')
                    idy=entete.index('stop_lat')
                    iid=entete.index('stop_id')
                    iname=entete.index('stop_name')
                else:

                    elements=re.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)",ligne[:-1])
                    arrets[elements[iid]]=[elements[iid],elements[iname].strip("\""),elements[idx].strip("\""),elements[idy].strip("\""),0.0,0.0]


        calendar={}
        if ("calendar.txt" in  os.listdir(nom_rep)):
            fich_calendar=io.open(nom_rep+"/calendar.txt","r",encoding=encodage)
            feedback.setProgressText(self.tr("Reading calendars..."))
            for i,cal in enumerate(fich_calendar):
                if i==0:
                    entete=cal.strip().split(',')
                    iid=entete.index('service_id')
                    idato=entete.index('start_date')
                    idatd=entete.index('end_date')
                    i1=entete.index('monday')
                    i2=entete.index('tuesday')
                    i3=entete.index('wednesday')
                    i4=entete.index('thursday')
                    i5=entete.index('friday')
                    i6=entete.index('saturday')
                    i7=entete.index('sunday')
                else:

                    elements=cal.strip().split(",")
                    dato=elements[idato]
                    dato=datetime.date(int(dato[0:4]),int(dato[4:6]),int(dato[6:8]))
                    datd=elements[idatd]
                    datd=datetime.date(int(datd[0:4]),int(datd[4:6]),int(datd[6:8]))
                    calendar[elements[iid]]=[elements[iid],dato,datd,elements[i1],elements[i2],elements [i3],elements[i4],elements[i5],elements[i6],elements[i7]]
                    

        calendar_dates={}
        calendar_dates2={}
        if ("calendar_dates.txt" in  os.listdir(nom_rep)):
            fich_calendar_dates=io.open(nom_rep+"/calendar_dates.txt","r",encoding=encodage)
            feedback.setProgressText(self.tr("reading calendar dates..."))
            for i,calendar_date in enumerate(fich_calendar_dates):
                if i==0:

                    entete=calendar_date.strip().split(',')
                    for i1,i2 in enumerate(entete):
                        entete[i1]=i2.strip('"')
                    iid=entete.index('service_id')
                    idate=entete.index('date')
                    iex=entete.index('exception_type')
                else:

                    elements=calendar_date.strip().split(",")
                    vdate=elements[idate].strip('"')
                    vdate=datetime.date(int(vdate[0:4]),int(vdate[4:6]),int(vdate[6:8]))
                    calendar_dates[(elements[iid],vdate,elements[iex])]=[elements[iid],vdate,elements[iex]]
                    if elements[iex]=="1":
                        if elements[iid] not in calendar_dates2:
                            calendar_dates2[elements[iid]]=[]
                        calendar_dates2[elements[iid]].append([elements[iid],vdate])


        routes={}
        test_l=int(("routes.txt" in os.listdir(nom_rep))*("trips.txt" in os.listdir(nom_rep))* ("stop_times.txt" in os.listdir(nom_rep)))
        if test_l==1 and islines:
            fich_routes=io.open(nom_rep+"/routes.txt","r",encoding=encodage)
            feedback.setProgressText(self.tr("Reading routes..."))
            for i,route in enumerate(fich_routes):
                if i==0:
                    entete=route.strip().split(',')
                    for i1,i2 in enumerate(entete):
                        entete[i1]=i2.strip('"')
                    iid=entete.index('route_id')
                    if 'route_short_name' not in entete:
                        iname=entete.index('route_long_name')
                    else:
                        iname=entete.index('route_short_name')
                    if 'route_long_name' not in entete:
                        ilong=entete.index('route_desc')
                    else:
                        ilong=entete.index('route_long_name')
                else:

                    elements=route.strip().split(",")
                    if elements[iname]=="":
                        elements[iname]=u' '
                    if elements[ilong]=="":
                        elements[ilong]=u' '
                    routes[elements[iid]]=[elements[iid],elements[iname],elements[ilong]]
            trips={}
            fich_trips=io.open(nom_rep+"/trips.txt","r",encoding=encodage)
            feedback.setProgressText(self.tr("Reading trips..."))
            for i,trip in enumerate(fich_trips):
                if i==0:
                    entete=trip.strip(" ").split(',')
                    for i1,i2 in enumerate(entete):
                        entete[i1]=i2.strip('"')
                        entete[i1]=i2.strip('\n').strip('\r')
                    iid=entete.index('route_id')
                    itrip=entete.index('trip_id')
                    iservice=entete.index('service_id')
                    if 'shape_id' in entete:
                        ishape=entete.index('shape_id')
                else:

                    elements=trip.strip(" ").strip('\n').strip('\r').split(",")

                    trips[elements[itrip]]=[elements[itrip],elements[iid],elements[iservice]]
            stop_times={}
            fich_stop_times=io.open(nom_rep+"/stop_times.txt","r",encoding=encodage)
            id_trip=None
            id_stop=None
            hi2=None
            segments={}
            links={}
            feedback.setProgressText(self.tr("Reading stop times..."))
            nb=float(os.stat(nom_rep+"/stop_times.txt").st_size)
            for i,stop_time in enumerate(fich_stop_times):
                if i==0:
                    entete=stop_time.strip().split(",")
                    iid=entete.index('trip_id')
                    iharr=entete.index('arrival_time')
                    ihdep=entete.index('departure_time')
                    istop=entete.index('stop_id')
                    iseq=entete.index('stop_sequence')
                else:
                    #progress.setPercentage(float(fich_stop_times.tell())*100/nb)
                    elements=stop_time.strip().split(',')
                    
                    #print((istop,iid,elements[istop],elements[iid]))
                    if elements[istop] in arrets and trips[elements[iid]][1] in routes:
                        id_stop2=elements[istop]
                        id_trip2=elements[iid]
                        ligne=trips[elements[iid]][1]
                        num_ligne=routes[ligne][1].strip()
                        descr=routes[ligne][2].strip()
                        hi1=QTime(int(elements[ihdep][0:2]),int(elements[ihdep][3:5]),int(elements[ihdep][6:8]))
                        hj=QTime(int(elements[iharr][0:2]),int(elements[iharr][3:5]),int(elements[iharr][6:8]))
                        if (id_trip2==id_trip):
                            nbservices=0
                            nbs1=0
                            nbs2=0
                            if ("calendar.txt" in  os.listdir(nom_rep)):
                                if trips[elements[iid]][2] in calendar:
                                    dp=calendar[trips[elements[iid]][2]][1]
                                    fp=calendar[trips[elements[iid]][2]][2]
                                    nb_jours=(fin_periode-debut_periode).days
                                    for k in range(nb_jours+1):
                                        date_offre=debut_periode+datetime.timedelta(days=k)
                                        if dp<=date_offre<=fp:
                                            jour=date_offre.isoweekday()
                                            if int(calendar[trips[id_trip][2]][2+jour])==1:
                                                nbservices+=1
                                            if (trips[id_trip][2],date_offre,'1') in calendar_dates:
                                                    nbservices+=1
                                            if (trips[id_trip][2],date_offre,'2') in calendar_dates:
                                                    nbservices+=-1
                                    
                            elif trips[elements[iid]][2] in calendar_dates2:
                                for k in calendar_dates2[trips[elements[iid]][2]]:
                                    nbservices+=1
                            segment_id=(num_ligne, id_stop,id_stop2)
                            if (t1<=hi2<=t2):
                                nbs1=nbservices
                            if (t1<=hj<=t2):
                                nbs2=nbservices
                            if (id_stop,id_stop2) not in links:
                                links[(id_stop,id_stop2)]={}
                            if num_ligne not in links[(id_stop,id_stop2)]:
                                links[(id_stop,id_stop2)][num_ligne]=(1,nbs1,descr)
                            else:
                                seg= links[(id_stop,id_stop2)][num_ligne]
                                links[(id_stop,id_stop2)][num_ligne]=(1,seg[1]+nbs1,descr)
                                
                            arrets[id_stop][5]+=nbs1
                            arrets[id_stop2][4]+=nbs2
                        hi2=hi1
                        id_stop=id_stop2
                        id_trip=id_trip2
            feedback.setProgressText(self.tr("Generating arcs and lines..."))
            for i,s in enumerate(links):
                i1=0
                i2=0
                g_links=QgsFeature()
                g_arcs=QgsFeature()
                #print([unicode(s[0]),unicode(s[1]),unicode(s[0])+"-"+unicode(s[1])])
                g_links.setGeometry(QgsGeometry.fromPolylineXY([(xtr.transform(QgsPointXY(float(arrets[s[0]][2]),float(arrets[s[0]][3])))),xtr.transform(QgsPointXY(float(arrets[s[1]][2]),float(arrets[s[1]][3])))]))
                g_arcs.setAttributes([unicode(s[0]),unicode(s[1]),unicode(s[0])+"-"+unicode(s[1])])
                g_arcs.setGeometry(g_links.geometry())
                
                if g_arcs.geometry().length()<1600000:
                    l_arcs.addFeature(g_arcs)
                for t in links[s]:

                    if t=="" or t==None:
                        tt= " "
                    else:
                        tt=t
                    #print([tt.decode("cp1252"),links[s][t][2].decode("cp1252"),unicode(s[0]),unicode(s[1]),links[s][t][0],links[s][t][1],i1,i2])
                    try:
                        g_links.setAttributes([unicode(t),unicode(links[s][t][2]),unicode(s[0]),unicode(s[1]),links[s][t][0],links[s][t][1],i1,i2])
                    except:
                        print(t,links[s][t][2])
                    
                    i1+=1
                    i2+=links[s][t][1]
                    if g_links.geometry().length()<1600000:
                        l_links.addFeature(g_links)
            del(stop_times)
            del(trips)
            del(routes)
            del(calendar)
            del(calendar_dates)

        if (isnodes):

            for s in arrets:
                g_noeuds=QgsFeature()
                g_noeuds.setGeometry(QgsGeometry.fromPointXY(xtr.transform(QgsPointXY(float(arrets[s][2]),float(arrets[s][3])))))
                #print([unicode(arrets[s][0]),arrets[s][1].decode('cp1252'),arrets[s][4],arrets[s][5]])
                try:
                    g_noeuds.setAttributes([unicode(arrets[s][0]),unicode(arrets[s][1]),arrets[s][4],arrets[s][5]])
                except:
                    print(arrets[s][1])
                l_noeuds.addFeature(g_noeuds)
        del(arrets)
        del(l_noeuds)
        del(l_links)
        del(l_arcs)
        return {self.REP_GTFS: self.REP_GTFS}
Example #22
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        reseau = self.parameterAsVectorLayer(parameters, self.RESEAU, context)
        fenetre=self.parameterAsExtent(parameters,self.FENETRE,context)
        cout_i=QgsExpression(self.parameterAsExpression(parameters,self.COUT_I,context))
        cout_j=QgsExpression(self.parameterAsExpression(parameters,self.COUT_J,context))
        sens=QgsExpression(self.parameterAsExpression(parameters,self.SENS,context))
        diffusion=QgsExpression(self.parameterAsExpression(parameters,self.DIFFUSION,context))
        traversabilite=QgsExpression(self.parameterAsExpression(parameters,self.TRAVERSABILITE,context))
        nb_pixels_x=self.parameterAsInt(parameters,self.NB_PIXELS_X,context)
        nb_pixels_y=self.parameterAsInt(parameters,self.NB_PIXELS_Y,context)
        taille_pixel_x=self.parameterAsDouble(parameters,self.TAILLE_PIXEL_X,context)
        taille_pixel_y=self.parameterAsDouble(parameters,self.TAILLE_PIXEL_Y,context)
        decimales=self.parameterAsInt(parameters,self.DECIMALES,context)
        rayon=self.parameterAsDouble(parameters,self.RAYON,context)
        vitesse_diffusion=QgsExpression(self.parameterAsExpression(parameters,self.VITESSE_DIFFUSION,context))
        intraversable = self.parameterAsBool(parameters, self.INTRAVERSABLE, context)

        resultat = self.parameterAsFileOutput(parameters, self.RESULTAT,context)        # Compute the number of steps to display within the progress bar and
        
        formule_cout_i=self.createExpressionContext(parameters,context)
        cout_i.prepare(formule_cout_i)
        formule_cout_j=self.createExpressionContext(parameters,context)
        cout_j.prepare(formule_cout_j)
        formule_sens=self.createExpressionContext(parameters,context)
        sens.prepare(formule_sens)
        formule_diffusion=self.createExpressionContext(parameters,context)
        diffusion.prepare(formule_diffusion)
        formule_traversabilite=self.createExpressionContext(parameters,context)
        traversabilite.prepare(formule_traversabilite)
        formule_vitesse_diffusion=self.createExpressionContext(parameters,context)
        vitesse_diffusion.prepare(formule_vitesse_diffusion)
        
        grille=numpy.array([[-9999.0]*nb_pixels_y]*nb_pixels_x)
        grille_distance=numpy.array([[1e38]*nb_pixels_y]*nb_pixels_x)
        rep=os.path.dirname(resultat)
        a=fenetre.asWktCoordinates().split(',')
        fenetre2=fenetre#QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3]))
        p1=a[0].split()
        p2=a[1].split()
        ll=(float(p1[0]),float(p1[1]))
        hauteur=float(p2[1])-float(p1[1])
        largeur=float(p2[0])-float(p1[0])
        if not(taille_pixel_x<=0):
            nb_pixels_x=int(largeur/taille_pixel_x)
        else:
            taille_pixel_x=float(largeur/nb_pixels_x)
        if not(taille_pixel_y<=0):
            nb_pixels_y=int(hauteur/taille_pixel_y)
        else:
            taille_pixel_y=float(hauteur/nb_pixels_y)
        layer=reseau
        if layer.type()==QgsMapLayer.VectorLayer:
            if not layer==None:
                if layer.geometryType()==1:
                    simple=QgsSimplifyMethod()
                    simple.setMethodType(QgsSimplifyMethod.PreserveTopology)
                    simple.setTolerance(min(taille_pixel_x,taille_pixel_y)/2)
                    texte=diffusion.dump()+' in (\'1\',\'2\',\'3\') and ('+cout_j.dump()+' IS NOT NULL and '+sens.dump()+' in (\'1\',\'3\')) '
                    
                    request=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(texte).setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect)
                    req_intra=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(traversabilite.dump()+' in (\'1\',\'2\',\'3\')').setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect)
                    features=[f for f in layer.getFeatures(request)]

                    if intraversable:
                        features_intra=[f for f in layer.getFeatures(req_intra)]
                    else:
                        features_intra=[]
                    for k,i in enumerate(features):
                        formule_sens.setFeature(i)
                        formule_cout_i.setFeature(i)
                        formule_cout_j.setFeature(i)
                        formule_vitesse_diffusion.setFeature(i)
                        formule_diffusion.setFeature(i)
                        formule_traversabilite.setFeature(i)
                        var_diffusion=diffusion.evaluate(formule_diffusion)
                        var_sens=sens.evaluate(formule_sens)
                        var_traversabilite=traversabilite.evaluate(formule_traversabilite)
                        ti=cout_i.evaluate(formule_cout_i)
                        tj=cout_j.evaluate(formule_cout_j)

                        var_vitesse_diffusion=vitesse_diffusion.evaluate(formule_vitesse_diffusion)
                        speed=60/(1000*var_vitesse_diffusion)

                        if var_sens in ['1','2','3'] :
                            
                            geom=i.geometry()
                            zone=geom.buffer(rayon,12).boundingBox()
                            deltax=int((zone.xMinimum()-ll[0])/taille_pixel_x)
                            deltay=int((zone.yMinimum()-ll[1])/taille_pixel_y)
                            dx=int(zone.width()/taille_pixel_x)
                            dy=int(zone.height()/taille_pixel_y)
                            l1=geom.length()
                            if geom.wkbType()==QgsWkbTypes.MultiLineString:
                                geom_l=geom.asMultiPolyline()
                            else:
                                geom_l=geom.asPolyline()
                            
                            for p in range(dx):
                                d2x=deltax+p
                                for q in range(dy):
                                    d2y=deltay+q
                                    if 0<=d2x<nb_pixels_x and 0<=d2y<nb_pixels_y:
                                        pt1=QgsGeometry.fromPointXY(QgsPointXY(ll[0]+(d2x+0.5)*taille_pixel_x,ll[1]+(d2y+0.5)*taille_pixel_y))
                                        res=geom.closestSegmentWithContext(pt1.asPoint())
                                        d=round(res[0],decimales)
                                        if d<=grille_distance[d2x,d2y] and d<rayon*rayon:
                                            if d>0 and l1>0:
                                                pt2=res[1]
                                                #feedback.setProgressText(geom.asWkt())
                                                if geom.wkbType()==QgsWkbTypes.MultiLineString:
                                                    num_poly=-1
                                                    npts=0
                                                    for k,id_poly in enumerate(geom_l):
                                                        if res[2]<npts+len(id_poly):
                                                            infos_poly=(k,res[2])
                                                        else:
                                                            npts+=len(id_poly)
                                                    #feedback.setProgressText(str(infos_poly[0])+"-"+str(infos_poly[1])+"-"+str(npts))
                                                    geoma=geom_l[infos_poly[0]][:(infos_poly[1]-npts)]+[pt2]
                                                else:
                                                    geoma=geom_l[:res[2]]+[pt2]
                                                #geoma=QgsGeometry(geom)
                                                #geoma.insertVertex(pt2[0],pt2[1],res[2])
                                                l2=QgsGeometry.fromPolylineXY(geoma).length()
                                                if res[2]==0:
                                                    pt3=geom.vertexAt(res[2])
                                                    pt4=geom.vertexAt(res[2]+1)
                                                else:
                                                    try:
                                                        pt3=geom.vertexAt(res[2]-1)
                                                        pt4=geom.vertexAt(res[2])
                                                    except:
                                                        print(res,geom_l)
                                                        pt3=geom_l[res[2]-1]
                                                        pt4=geom_l[res[2]]
                                                p1=pt1.asPoint()
                                                test_sens=(pt4.x()-pt3.x())*(p1.y()-pt2.y())-(p1.x()-pt2.x())*(pt4.y()-pt3.y())
                                                if var_sens in ['1','3'] and not tj==None:
                                                    if (var_diffusion in ['1','3'] and test_sens<=0) or (var_diffusion in ['2','3'] and test_sens>=0):
                                                       
                                                        
                                                        if not tj==None:
                                                            
                                                            if not ti==None:
                                                                t=tj*(l2/l1)+ti*(1-(l2/l1))+math.sqrt(d)*speed
                                                                l3=QgsGeometry.fromPolylineXY([pt1.asPoint(),QgsPointXY(pt2)])
                                                        result_test=False
                                                        if l3!=None:
                                                            if len(features_intra)>0:
                                                                for intra in features_intra:
                                                                    if intra.geometry().intersects(l3):
                                                                        result_test=True
                                                                        break
                                                        if result_test==False:
                                                            if (t<grille[d2x,d2y] and d==grille_distance[d2x,d2y]) or d<grille_distance[d2x,d2y]:
                                                                grille_distance[d2x,d2y] =d
                                                                grille[d2x,d2y] =t

                    sortie=os.path.splitext(resultat)
                    fichier_grille=open(sortie[0]+sortie[1],'w')
                    fichier_grille.write("NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n".format(nb_pixels_x,nb_pixels_y,ll[0],ll[1],taille_pixel_x,taille_pixel_y))
                    fichier_grille2=open(sortie[0]+"_dist"+sortie[1],'w')
                    fichier_grille2.write("NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n".format(nb_pixels_x,nb_pixels_y,ll[0],ll[1],taille_pixel_x,taille_pixel_y))
                    g1=numpy.rot90(grille,1)
                    #g1=numpy.flipud(g1)
                    g2=numpy.rot90(grille_distance,1)
                    #g2=numpy.flipud(g2)
                    for i in g1:
                        fichier_grille.write(" ".join([str(ii) for ii in i])+"\n")
                    fichier_grille.close()
                    for i in g2:
                        fichier_grille2.write(" ".join([str(math.sqrt(ii)) for ii in i])+"\n")
                    fichier_grille2.close()

                    fichier_prj=open(sortie[0]+".prj",'w')
                    fichier2_prj=open(sortie[0]+"_dist.prj",'w')
                    fichier_prj.write(layer.crs().toWkt())
                    fichier2_prj.write(layer.crs().toWkt())
                    fichier_prj.close()
                    fichier2_prj.close()
                    nom_sortie=os.path.basename(sortie[0])
                    rlayer=QgsRasterLayer(resultat,nom_sortie)

        return {self.RESULTAT: fichier_grille}
Example #23
0
    def processFeature(self, feature, feedback):
        if feature.hasGeometry():
            geom = feature.geometry()
            geomType = QgsWkbTypes.flatType(geom.wkbType())
            newGeom = None

            if geomType == QgsWkbTypes.Point:
                points = self._gridify([geom.asPoint()], self.h_spacing, self.v_spacing)
                newGeom = QgsGeometry.fromPoint(points[0])
            elif geomType == QgsWkbTypes.MultiPoint:
                points = self._gridify(geom.asMultiPoint(), self.h_spacing, self.v_spacing)
                newGeom = QgsGeometry.fromMultiPoint(points)
            elif geomType == QgsWkbTypes.LineString:
                points = self._gridify(geom.asPolyline(), self.h_spacing, self.v_spacing)
                if len(points) < 2:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromPolylineXY(points)
            elif geomType == QgsWkbTypes.MultiLineString:
                polyline = []
                for line in geom.asMultiPolyline():
                    points = self._gridify(line, self.h_spacing, self.v_spacing)
                    if len(points) > 1:
                        polyline.append(points)
                if len(polyline) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromMultiPolyline(polyline)

            elif geomType == QgsWkbTypes.Polygon:
                polygon = []
                for line in geom.asPolygon():
                    points = self._gridify(line, self.h_spacing, self.v_spacing)
                    if len(points) > 1:
                        polygon.append(points)
                if len(polygon) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromPolygon(polygon)
            elif geomType == QgsWkbTypes.MultiPolygon:
                multipolygon = []
                for polygon in geom.asMultiPolygon():
                    newPolygon = []
                    for line in polygon:
                        points = self._gridify(line, self.h_spacing, self.v_spacing)
                        if len(points) > 2:
                            newPolygon.append(points)

                    if len(newPolygon) > 0:
                        multipolygon.append(newPolygon)

                if len(multipolygon) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromMultiPolygon(multipolygon)

            if newGeom is not None:
                feature.setGeometry(newGeom)
            else:
                feature.clearGeometry()
        return feature
Example #24
0
 def createQgLineFeature(self, vertices):
     line = QgsGeometry.fromPolylineXY(vertices)
     qgFeat = QgsFeature()
     qgFeat.setGeometry(line)
     return qgFeat
Example #25
0
 def updateLine(self, points):
     self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(points), None)
     self.drawnLine = self.createDigiFeature(points)
     self.drawStueMarker(points[0])
     self.drawStueMarker(points[1])
Example #26
0
    def getShape(self, shpExtent=None, AzimuthToCentreLine=None, offset=None):

        TOMsMessageLog.logMessage("In getShape ... ", level=Qgis.Info)

        feature = self.currFeature
        restGeomType = self.currRestGeomType
        orientation = self.currBayOrientation

        if shpExtent is None:
            shpExtent = self.BayWidth
        if AzimuthToCentreLine is None:
            AzimuthToCentreLine = self.currAzimuthToCentreLine
        if offset is None:
            offset = self.BayOffsetFromKerb
        """
        Logic is :

        For vertex 0,
            Move for defined distance (typically 0.25m) in direction "AzimuthToCentreLine" and create point 1
            Move for bay width (typically 2.0m) in direction "AzimuthToCentreLine and create point 2
            Calculate Azimuth for line between vertex 0 and vertex 1
            Calc difference in Azimuths and decide < or > 180 (to indicate which side of kerb line to generate bay)

        For each vertex (starting at 1)
            Calculate Azimuth for current vertex and previous
            Calculate perpendicular to centre of road (using knowledge of which side of kerb line generated above)
            Move for bay width (typically 2.0m) along perpendicular and create point

        For last vertex
                Move for defined distance (typically 0.25m) along perpendicular and create last point
        """

        line = generateGeometryUtils.getLineForAz(feature)

        # TOMsMessageLog.logMessage("In getDisplayGeometry:  nr of pts = " + str(len(line)), level=Qgis.Info)

        if len(line) == 0:
            return 0

        # Now have a valid set of points

        ptsList = []
        parallelPtsList = []
        nextAz = 0
        diffEchelonAz = 0

        # now loop through each of the vertices and process as required. New geometry points are added to ptsList

        for i in range(len(line) - 1):

            # TOMsMessageLog.logMessage("In getDisplayGeometry: i = " + str(i), level=Qgis.Info)

            Az = generateGeometryUtils.checkDegrees(line[i].azimuth(line[i + 1]))

            # TOMsMessageLog.logMessage("In getShape: geometry: " + str(line[i].x()) + ":" + str(line[i].y()) + " " + str(line[i+1].x()) + ":" + str(line[i+1].y()) + " " + str(Az), level=Qgis.Info)

            # if this is the first point

            if i == 0:
                # determine which way to turn towards CL
                # TOMsMessageLog.logMessage("In generate_display_geometry: considering first point", level=Qgis.Info)

                Turn = generateGeometryUtils.turnToCL(Az, AzimuthToCentreLine)

                newAz = generateGeometryUtils.checkDegrees(Az + Turn)
                # TOMsMessageLog.logMessage("In getShape: newAz: " + str(newAz) + "; turn is " + str(Turn), level=Qgis.Info)
                cosa, cosb = generateGeometryUtils.cosdir_azim(newAz)

                # TOMsMessageLog.logMessage("In generate_display_geometry: cosa : " + str(cosa) + " " + str(cosb), level=Qgis.Info)

                # dx = float(offset) * cosa
                # dy = float(offset) * cosb

                # TOMsMessageLog.logMessage("In generate_display_geometry: dx: " + str(dx) + " dy: " + str(dy), level=Qgis.Info)

                ptsList.append(
                    QgsPointXY(line[i].x() + (float(offset) * cosa), line[i].y() + (float(offset) * cosb)))

                parallelPtsList.append(
                    QgsPointXY(line[i].x() + (float(offset) * cosa), line[i].y() + (float(offset) * cosb)))
                # TOMsMessageLog.logMessage("In geomType: added point 1 ", level=Qgis.Info)

                # Now add the point at the extent. If it is an echelon bay:
                #   a. calculate the difference between the first Az and the echelon Az (??), and
                #   b. adjust the angle
                #   c. *** also need to adjust the length *** Not yet implemented

                # if restGeomType == 5 or restGeomType == 25:  # echelon
                if restGeomType in [5, 25]:  # echelon
                    # TOMsMessageLog.logMessage("In getShape: orientation: " + str(orientation), level=Qgis.Info)
                    if self.is_float(orientation) == False:
                        orientation = AzimuthToCentreLine

                    # TOMsMessageLog.logMessage("In getShape: orientation: " + str(float(orientation)), level=Qgis.Info)

                    diffEchelonAz1 = float(orientation) - newAz
                    # TOMsMessageLog.logMessage("In getShape: diffEchelonAz1: " + str(diffEchelonAz1), level=Qgis.Info)

                    diffEchelonAz = generateGeometryUtils.checkDegrees(diffEchelonAz1)
                    #TOMsMessageLog.logMessage("In getShape: newAz: " + str(newAz) + " diffEchelonAz1: " + str(diffEchelonAz1) + " diffEchelonAz: " + str(diffEchelonAz),
                    #                         level=Qgis.Info)

                    newAz = generateGeometryUtils.checkDegrees(newAz + diffEchelonAz)
                    #TOMsMessageLog.logMessage("In getShape: newAz: " + str(newAz) + " diffEchelonAz: " + str(diffEchelonAz),
                    #                         level=Qgis.Info)
                    cosa, cosb = generateGeometryUtils.cosdir_azim(newAz)

                ptsList.append(
                    QgsPointXY(line[i].x() + (float(shpExtent) * cosa),
                             line[i].y() + (float(shpExtent) * cosb)))
                # TOMsMessageLog.logMessage("In geomType: added point 2 ", level=Qgis.Info)

                # ptsList.append(newPoint)
                # TOMsMessageLog.logMessage("In geomType: after append ", level=Qgis.Info)

                # ptsList.append(QgsPoint(line[i].x()+(float(bayWidth)*cosa), line[i].y()+(float(bayWidth)*cosb)))

            else:

                # now pass along the feature

                # TOMsMessageLog.logMessage("In generate_display_geometry: considering point: " + str(i), level=Qgis.Info)

                # need to work out half of bisected angle

                # TOMsMessageLog.logMessage("In generate_display_geometry: prevAz: " + str(prevAz) + " currAz: " + str(Az), level=Qgis.Info)

                newAz, distWidth = generateGeometryUtils.calcBisector(prevAz, Az, Turn, shpExtent)

                # TOMsMessageLog.logMessage("In generate_display_geometry: newAz: " + str(newAz), level=Qgis.Info)

                cosa, cosb = generateGeometryUtils.cosdir_azim(newAz + diffEchelonAz)
                ptsList.append(
                    QgsPointXY(line[i].x() + (float(distWidth) * cosa), line[i].y() + (float(distWidth) * cosb)))

                parallelPtsList.append(
                    QgsPointXY(line[i].x() + (float(offset) * cosa), line[i].y() + (float(offset) * cosb)))
            # TOMsMessageLog.logMessage("In generate_display_geometry: point appended", level=Qgis.Info)

            prevAz = Az

            # TOMsMessageLog.logMessage("In generate_display_geometry: newPoint 1: " + str(ptsList[1].x()) + " " + str(ptsList[1].y()), level=Qgis.Info)

            # have reached the end of the feature. Now need to deal with last point.
            # Use Azimuth from last segment but change the points

            # TOMsMessageLog.logMessage("In generate_display_geometry: feature processed. Now at last point ", level=Qgis.Info)

            # standard bay
        newAz = generateGeometryUtils.checkDegrees(Az + Turn + diffEchelonAz)
        # TOMsMessageLog.logMessage("In generate_display_geometry: newAz: " + str(newAz), level=Qgis.Info)
        cosa, cosb = generateGeometryUtils.cosdir_azim(newAz)

        ptsList.append(QgsPointXY(line[len(line) - 1].x() + (float(shpExtent) * cosa),
                                line[len(line) - 1].y() + (float(shpExtent) * cosb)))

        # add end point (without any consideration of Echelon)

        newAz = Az + Turn
        cosa, cosb = generateGeometryUtils.cosdir_azim(newAz)

        ptsList.append(QgsPointXY(line[len(line) - 1].x() + (float(offset) * cosa),
                                line[len(line) - 1].y() + (float(offset) * cosb)))
        parallelPtsList.append(QgsPointXY(line[len(line) - 1].x() + (float(offset) * cosa),
                                line[len(line) - 1].y() + (float(offset) * cosb)))

        newLine = QgsGeometry.fromPolylineXY(ptsList)
        #parallelPtsList.reverse()
        parallelLine = QgsGeometry.fromPolylineXY(parallelPtsList)

        # TOMsMessageLog.logMessage("In getDisplayGeometry:  newLine ********: " + newLine.asWkt(), level=Qgis.Info)
        # TOMsMessageLog.logMessage("In getDisplayGeometry:  parallelLine ********: " + parallelLine.asWkt(), level=Qgis.Info)

        return newLine, parallelLine
Example #27
0
    def computeOnePath(self, point, index, start, baseRaster, destinations,
                       lcps, logMessageFile):
        # compute cost map for the entire area
        startCost = timeit.default_timer()

        logMessage = "%.2f" % (timeit.default_timer(
        ) - start) + " - id " + self._id + " thread: " + current_thread(
        ).name + " computing cost map from source point: " + str(
            index + 1) + " at position: " + format(
                point.x(), ".2f") + "/" + format(point.y(), ".2f")
        QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info)
        logMessageFile.write(logMessage + "\n")

        distances = self.computeCost(point, baseRaster, logMessageFile)

        logMessage = "\t%.2f" % (timeit.default_timer(
        ) - start) + " - Done! seconds to compute cost map: " + str(
            "%.2f" % (timeit.default_timer() - startCost))
        QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info)
        logMessageFile.write(logMessage + "\n")

        if distances is None:
            QMessageBox.information(
                None,
                "ERROR!",
                "Cost map could not be computed for point: " + str(index),
                tag="LCPNetwork",
                level=Qgis.Warning)
            return "error"

        self.storeCostMap(distances, baseRaster, index)
        name = os.path.dirname(__file__) + "/distances" + self._id + "_" + str(
            index) + ".tif"
        distanceBase = gdal.Open(name)

        distances = np.array(distanceBase.GetRasterBand(1).ReadAsArray())

        logMessage = "\t%.2f" % (
            timeit.default_timer() - start) + " thread: " + current_thread(
            ).name + " - cost map stored; estimating least-cost paths..."
        QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info)
        logMessageFile.write(logMessage + "\n")

        destIndex = 1
        for destination in destinations:
            if destination == point:
                continue

            logMessage = "\t\t%.2f" % (
                timeit.default_timer() - start
            ) + " - estimating path to dest: " + str(destIndex) + "/" + str(
                len(destinations)) + " at pos:" + format(
                    destination.x(), ".2f") + "/" + format(
                        destination.y(), ".2f")
            QgsMessageLog.logMessage(logMessage,
                                     tag="LCPNetwork",
                                     level=Qgis.Info)
            logMessageFile.write(logMessage + "\n")
            pathLine = self.getGlobalPath(point, destination, baseRaster,
                                          distances, logMessageFile)
            if pathLine is None:
                QMessageBox.information(
                    None,
                    "ERROR!",
                    "Route could not be found for destination: " +
                    str(destIndex),
                    tag="LCPNetwork",
                    level=Qgis.Warning)
                return

            lcp = QgsFeature()
            ## set geometry from the list of QgsPointXY's to the feature
            lcp.setGeometry(QgsGeometry.fromPolylineXY(pathLine))
            lcps.append(lcp)
            destIndex = destIndex + 1

        logMessage = "%.2f" % (
            timeit.default_timer() - start) + " thread: " + current_thread(
            ).name + " - computation finished for source point: " + str(index +
                                                                        1)
        QgsMessageLog.logMessage(logMessage, tag="LCPNetwork", level=Qgis.Info)
        logMessageFile.write(logMessage + "\n")

        return "%.2f" % (timeit.default_timer(
        ) - start) + " - id " + self._id + " thread: " + current_thread(
        ).name + " finished for index: " + str(index)
Example #28
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        arrets = self.parameterAsSource(parameters, self.STOPS, context)
        stop_id=self.parameterAsFields(parameters,self.STOP_ID,context)[0]
        noeuds = self.parameterAsSource(parameters, self.NOEUDS, context)
        node_id=self.parameterAsFields(parameters,self.NODE_ID,context)[0]
        mode_i=self.parameterAsString(parameters,self.MODE_ORI,context)
        mode_j=self.parameterAsString(parameters,self.MODE_DES,context)
        texte_i=self.parameterAsString(parameters,self.TEXTE_ORI,context)
        texte_j=self.parameterAsString(parameters,self.TEXTE_DES,context)
        rayon=self.parameterAsDouble(parameters,self.RAYON,context)
        vitesse=self.parameterAsDouble(parameters,self.VITESSE,context)
        nb_max=self.parameterAsInt(parameters,self.MAX_NB,context)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        ##a=fenetre.split(",")
        ##fenetre2=QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3]))
        arr=[a for a in arrets.getFeatures()]
        nb=len(arr)
        
        index=QgsSpatialIndex(noeuds.getFeatures())
        champs=QgsFields()
        champs.append(QgsField('i',QVariant.String,len=15))
        champs.append(QgsField('j',QVariant.String,len=15))
        champs.append(QgsField(self.tr('length'),QVariant.Double))
        champs.append(QgsField(self.tr('time'),QVariant.Double))
        champs.append(QgsField(self.tr('mode'),QVariant.String,len=10))

        (table_connecteurs,dest_id) = self.parameterAsSink(parameters, self.CONNECTEURS,context,champs, QgsWkbTypes.LineString, noeuds.sourceCrs())
        nom_fichier=dest_id
        fichier_connecteurs=os.path.splitext(nom_fichier)[0]+".txt"
        sortie=codecs.open(fichier_connecteurs,"w",encoding="utf-8")
        nbc=0
        for i,n in enumerate(arr):
            near=index.nearestNeighbor(n.geometry().centroid().asPoint(),nb_max)
            feedback.setProgress(i*100/nb)
            if len(near)>0:
                for k,nearest in enumerate(near):
                    if k<nb_max:
                        f=noeuds.getFeatures(request=QgsFeatureRequest(nearest))
                        for j, g in enumerate(f):
                            if j==0:
                                l=n.geometry().distance(g.geometry())
                                id_node=unicode(g.attribute(node_id))
                                id_stop=unicode(n.attribute(stop_id))
                                if l<rayon:
                                    nbc+=1
                                    gline=QgsGeometry.fromPolylineXY([QgsPointXY(n.geometry().centroid().asPoint()),QgsPointXY(g.geometry().centroid().asPoint())])
                                    hline=QgsGeometry.fromPolylineXY([QgsPointXY(g.geometry().centroid().asPoint()),QgsPointXY(n.geometry().centroid().asPoint())])

                                    fline=QgsFeature()
                                    fline.setGeometry(gline)
                                    ll=gline.length()
                                    moda=unicode(mode_i)+unicode(mode_j)
                                    if vitesse<=0:
                                        fline.setAttributes([id_stop,id_node, ll/1000,0.0,moda])
                                    else:
                                        fline.setAttributes([id_stop,id_node, ll/1000,ll*60/(vitesse*1000),moda])
                                    fline2=QgsFeature()
                                    fline2.setGeometry(hline)
                                    modb=unicode(mode_j)+unicode(mode_i)
                                    if vitesse<=0:
                                        fline2.setAttributes([id_node,id_stop, ll/1000,0,modb])
                                    else:
                                        fline2.setAttributes([id_node,id_stop, ll/1000,ll*60/(vitesse*1000),modb])
                                    table_connecteurs.addFeature(fline)
                                    table_connecteurs.addFeature(fline2)
                                    if vitesse>0:
                                        sortie.write(id_node+';'+id_stop+';'+str((60/vitesse)*(ll/1000.0))+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+modb+';'+modb+'\n')
                                        sortie.write(id_stop+';'+id_node+';'+str((60/vitesse)*(ll/1000.0))+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+moda+';'+moda+'\n')
                                    else:
                                        sortie.write(id_node+';'+id_stop+';'+str(0.0)+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+modb +';'+modb+'\n')
                                        sortie.write(id_stop+';'+id_node+';'+str(0.0)+';'+str(ll/1000.0)+';-1;-1;-1;-1;-1;'+moda+';'+moda+'\n')
        feedback.setProgressText(unicode(nbc)+"/"+unicode(nb)+self.tr(" connected nodes"))
        sortie.close()
        return {self.OUTPUT: dest_id}
Example #29
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        couche_lines = self.parameterAsVectorLayer(parameters, self.LINES, context)
        couche_points = self.parameterAsVectorLayer(parameters, self.NODES, context)
        radius=self.parameterAsDouble(parameters,self.RAYON,context)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        delta=float(radius)
        index=QgsSpatialIndex()
        lines=couche_lines.getFeatures()
        for i in lines:
            if i.geometry().isMultipart():
                i.setGeometry(QgsGeometry.fromPolylineXY(i.geometry().asMultiPolyline()[0]))
            index.insertFeature(i)

        couche_lines.startEditing()
        couche_lines.beginEditCommand(self.tr("Split polylines at connections"))
        points=couche_points.getFeatures()
        nb=couche_points.featureCount()
        feedback.setProgressText(self.tr("Connecting points to lines..."))
        for pos,pt in enumerate(points):
            feedback.setProgress(pos*100.0/nb)
            ptg=pt.geometry()
            if ptg.isMultipart():
                ptg=QgsGeometry.fromPoint(ptg.asMultiPoint()[0])
            coor=ptg.asPoint()
            nearest=index.intersects(QgsRectangle(coor.x()-delta,coor.y()-delta,coor.x()+delta,coor.y()+delta))
            dmin=1e38
            if len(nearest)>0:
                for n in nearest:
                    f=couche_lines.getFeatures(request=QgsFeatureRequest(n))
                    for g in f:
                        d=g.geometry().distance(pt.geometry())
                        if d<=dmin:
                            dmin=d
                            gmin=g
                            gid=g.id()
                g=gmin
                if g.geometry().distance(pt.geometry())<delta:
                    a=g.geometry().closestSegmentWithContext(ptg.asPoint())
                    if not(a[2]==0):
                        geom=g.geometry()
                        geom.convertToSingleType()
                        geom_id=g.id()
                        att=g.attributes()
                        connexion=QgsFeature()
                        connexion.setGeometry(QgsGeometry.fromPolylineXY([ptg.asPoint(),a[1]]))
                        connexion.setAttributes(att)
                        couche_lines.addFeature(connexion)
                        geom.insertVertex(a[1][0],a[1][1],a[2])
                        geoma=geom.asPolyline()[:a[2]+1]
                        geomb=geom.asPolyline()[a[2]:]
                        feedback.setProgressText(unicode(geomb))
                        fa=QgsFeature()
                        fa.setGeometry(QgsGeometry.fromPolylineXY(geoma))
                        fa.setAttributes(att)
                        couche_lines.addFeature(fa)
                        index.insertFeature(fa)
                        fb=QgsFeature()
                        fb.setGeometry(QgsGeometry.fromPolylineXY(geomb))
                        fb.setAttributes(att)
                        couche_lines.addFeature(fb)
                        index.insertFeature(fb)
                        couche_lines.deleteFeature(g.id())
                        index.deleteFeature(g)
        couche_lines.endEditCommand()
        return {self.LINES: 'OK'}
    def run(self):
        try:
            inputlayer = self.inputvectorlayer
            if inputlayer is None:
                self.error.emit(self.tr('No input layer defined'))
                self.finished.emit(False, None)
                return
            # Get and check the geometry type of the input layer
            geometryType = self.inputvectorlayer.geometryType()
            if not (geometryType == QgsWkbTypes.LineGeometry or
                    geometryType == QgsWkbTypes.PolygonGeometry):
                self.error.emit('Only line and polygon layers are supported!')
                self.finished.emit(False, None)
                return
            self.processed = 0
            self.percentage = 0
            if self.selectedfeaturesonly:
                self.feature_count = inputlayer.selectedFeatureCount()
            else:
                self.feature_count = inputlayer.featureCount()
            if self.feature_count == 0:
                self.error.emit("No features in layer")
                self.finished.emit(False, None)
                return
            self.increment = self.feature_count // 1000
            # Initialise the result list
            statistics = []
            # Initialise the bins for the over all result
            mybins = []
            for i in range(self.bins):
                mybins.append([0.0, 0])
            # Add the over all bins
            statistics.append(mybins)
            # Get the features (iterator)
            if self.selectedfeaturesonly:
                features = inputlayer.getSelectedFeatures()
#                features = inputlayer.selectedFeaturesIterator()
            else:
                features = inputlayer.getFeatures()
            # Create a list for the (possible) tile (Polygon)
            # geometries
            tilegeoms = []
            if self.tilelayer is not None:
                self.status.emit("Using tiles!")
                for tilefeat in self.tilelayer.getFeatures():
                    tilegeoms.append(tilefeat.geometry())
                # Initialise and add bins for all the tiles
                for i in range(len(tilegeoms)):
                    mybins = []
                    for j in range(self.bins):
                        mybins.append([0.0, 0])
                    statistics.append(mybins)
            # Go through the features
            for feat in features:
                # Allow user abort
                if self.abort is True:
                    break
                # Prepare for the histogram creation by extracting
                # line geometries (QgsGeometry) from the input layer

                # First we do all the lines of the layer.  Later we
                # will do the lines per tile
                # We use a list of line geometries to be able to
                # handle MultiPolylines and Polygons
                inputlines = []
                geom = feat.geometry()  # QgsGeometry
                if geometryType == QgsWkbTypes.LineGeometry:
                    # Lines!
                    if geom.isMultipart():
                        theparts = geom.constParts()
                        # QgsGeometryConstPartIterator
                        # Go through the parts of the multigeometry
                        for part in theparts:
                            # QgsAbstractGeometry - QgsLineString
                            partgeom = QgsGeometry.fromPolyline(part)
                            inputlines.append(partgeom)  # QgsGeometry
                    else:
                        inputlines.append(geom)
                # There are only two possibilites for geometry type, so
                # this elif: could be replaced with an else:
                elif geometryType == QgsWkbTypes.PolygonGeometry:
                    # Polygons!
                    # We use a list of polygon geometries to be able to
                    # handle MultiPolygons
                    inputpolygons = []
                    if geom.isMultipart():
                        # Multi polygon
                        multipoly = geom.asMultiPolygon()
                        for geompoly in multipoly:
                            # list of list of QgsPointXY
                            # abstract geometry -> QgsGeometry polygon
                            polygeometry = QgsGeometry.fromPolygonXY(geompoly)
                            inputpolygons.append(polygeometry)
                    else:
                        # Non-multi polygon
                        # Make sure it is a QgsGeometry polygon
                        singlegeom = geom.asPolygon()
                        polygeometry = QgsGeometry.fromPolygonXY(singlegeom)
                        inputpolygons.append(polygeometry)  # QgsGeometry
                    # Add the polygon rings
                    for polygon in inputpolygons:
                        # create a list of list of QgsPointXY
                        poly = polygon.asPolygon()
                        for ring in poly:
                            # list of QgsPointXY
                            # Create a QgsGeometry line
                            geometryring = QgsGeometry.fromPolylineXY(ring)
                            inputlines.append(geometryring)  # QgsGeometry
                else:
                    # We should never end up here
                    self.status.emit("Unexpected geometry type!")
                # We introduce a list of line geometries for the tiling
                tilelinecoll = [None] * (len(tilegeoms) + 1)
                # Use the first element to store all the input lines
                # (for the over all histogram)
                tilelinecoll[0] = inputlines
                # Clip the lines based on the tile layer
                if self.tilelayer is not None:
                    i = 1  # The first one is used for the complete dataset
                    for tile in tilegeoms:  # Go through the tiles
                        # Create a list for the lines in the tile
                        newlines = []
                        for linegeom in inputlines:
                            # QgsGeometry
                            # Clip
                            clipres = linegeom.intersection(tile)
                            if clipres.isEmpty():
                                continue
                            if clipres.isMultipart():
                                # MultiLineString
                                clipresparts = clipres.constParts()
                                for clipline in clipresparts:
                                  # Create a QgsGeometry line
                                  linegeom = QgsGeometry.fromPolyline(clipline)
                                  newlines.append(linegeom)  # QgsGeometry
                            else:
                                # ?
                                newlines.append(clipres)
                        tilelinecoll[i] = newlines
                        i = i + 1
                # Do calculations (line length and directions)
                j = 0  # Counter for the tiles
                for tilelines in tilelinecoll:  # Handling the tiles
                  for inputlinegeom in tilelines:  # Handling the lines
                    # QgsGeometry line - wkbType 2
                    if inputlinegeom is None:
                        continue
                    numvert = 0
                    for v in inputlinegeom.vertices():
                       numvert = numvert + 1
                    if numvert == 0:
                        continue
                    if numvert < 2:
                        self.status.emit("Less than two vertices!")
                        continue
                    # Go through all the segments of this line
                    thispoint = inputlinegeom.vertexAt(0)  # QgsPoint
                    first = True
                    for v in inputlinegeom.vertices():
                        if first:
                            first = False
                            continue
                        nextpoint = v
                        linelength = sqrt(thispoint.distanceSquared(nextpoint))
                        # Find the angle of the line segment
                        lineangle = thispoint.azimuth(nextpoint)
                        if lineangle < 0:
                            lineangle = 360 + lineangle
                        if self.directionneutral:
                            if lineangle >= 180.0:
                                lineangle = lineangle - 180
                        # Find the bin
                        if lineangle > self.offsetangle:
                            fitbin = (int((lineangle - self.offsetangle) /
                                      self.binsize) % self.bins)
                        else:
                            fitbin = (int((360 + lineangle -
                                           self.offsetangle) / self.binsize) %
                                      self.bins)
                        # Have to handle special case to keep index in range?
                        if fitbin == self.bins:
                            self.status.emit("fitbin == self.bins")
                            fitbin = 0
                        # Add to the length of the bin of this tile (j)
                        statistics[j][fitbin][0] = (statistics[j][fitbin][0] +
                                                    linelength)
                        # Add to the number of line segments in the bin
                        statistics[j][fitbin][1] = (statistics[j][fitbin][1] +
                                                    1)
                        thispoint = nextpoint  # advance to the next point
                  j = j + 1  # Next tile
                self.calculate_progress()
        except Exception as e:
            self.status.emit("Exception occurred - " + str())
            self.error.emit(str(e))
            self.finished.emit(False, None)
        else:
            if self.abort:
                self.status.emit("Aborted")
                self.finished.emit(False, None)
            else:
                self.status.emit("Completed")
                self.finished.emit(True, statistics)
Example #31
0
    def test_isThisTOMsLayer(self):

        #self.testData()
        testLayerA = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'),
                                    'test1', 'memory')
        testProviderA = testLayerA.dataProvider()

        testLineString1 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(1, 0)])
        testLineString2 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(1, 0), QgsPointXY(1, 1)])
        testLineString3 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(0, 0), QgsPointXY(-1, 1)])
        testLineString4 = QgsGeometry.fromPolylineXY(
            [QgsPointXY(1, 1), QgsPointXY(2, 1)])

        testProviderA.addAttributes([
            QgsField("GeometryID", QVariant.String),
            QgsField("age", QVariant.Int),
            QgsField("size", QVariant.Double),
            QgsField("size2", QVariant.Double)
        ])
        testFieldsA = testProviderA.fields()
        """for field in testFields:
            print ('** {}'.format(field.name()))"""

        testFeature1 = QgsFeature(testFieldsA)
        testFeature1.setGeometry(testLineString1)
        testFeature1.setAttributes(["Smith", 20, 0.3])
        testProviderA.addFeatures([testFeature1])

        testFeature2 = QgsFeature(testFieldsA)
        testFeature2.setGeometry(testLineString2)
        testFeature2.setAttributes(["Blogs", 20, 0.3])
        testProviderA.addFeatures([testFeature2])

        # check field called "OpenDate" does not exist
        result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerA)
        self.assertFalse(result)

        # check field called "OpenDate" does exist but is NULL

        testLayerB = QgsVectorLayer(('LineString?crs=epsg:27700&index=yes'),
                                    'test2', 'memory')
        testProviderB = testLayerB.dataProvider()
        testProviderB.addAttributes([QgsField("OpenDate", QVariant.String)])
        testFieldsB = testProviderB.fields()
        testFeature3 = QgsFeature(testFieldsB)
        testFeature3.setGeometry(testLineString2)
        testProviderB.addFeatures([testFeature3])

        result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerB)
        self.assertFalse(result)

        # check field called "OpenDate" does exist but is not NULL
        testFeature3.setAttribute("OpenDate", 'Test')
        testProviderB.addFeatures([testFeature3])

        #print ('*************************** Count: {}'.format(testLayerB.featureCount()))
        testLayerB.reload()
        for field in testLayerB.fields():
            print('+++ field: {}'.format(field.name()))

        result = self.testClass.isThisTOMsLayerUsingCurrentFeatures(testLayerB)
        self.assertTrue(result)
Example #32
0
    def processAlgorithm(self, parameters, context, feedback):
        # get input variables
        source = self.parameterAsSource(parameters, self.INPUT_LINE, context)
        swath_angle_field = self.parameterAsString(parameters,
                                                   self.SWATH_ANGLE_FIELD,
                                                   context)
        swath_angle_fallback = self.parameterAsInt(parameters,
                                                   self.SWATH_ANGLE, context)
        raster_layer = self.parameterAsRasterLayer(parameters,
                                                   self.INPUT_RASTER, context)
        band_number = self.parameterAsInt(parameters, self.BAND, context)

        # copy of the field name for later
        swath_angle_field_name = swath_angle_field

        # set new default values in config
        feedback.pushConsoleInfo(
            self.tr(f'Storing new default settings in config...'))
        self.config.set(self.module, 'swath_angle', swath_angle_fallback)

        # get crs's
        crs_line = source.sourceCrs()
        crs_raster = raster_layer.crs()

        # get project transform_context
        transform_context = context.transformContext()

        # CRS transformation to "WGS84/World Mercator" for MBES coverage operations
        crs_mercator = QgsCoordinateReferenceSystem('EPSG:3395')
        trans_line2merc = QgsCoordinateTransform(crs_line, crs_mercator,
                                                 transform_context)

        # CRS transformation to raster layer CRS for depth sampling
        trans_merc2raster = QgsCoordinateTransform(crs_mercator, crs_raster,
                                                   transform_context)
        trans_line2raster = QgsCoordinateTransform(crs_line, crs_raster,
                                                   transform_context)
        crs_geo = QgsCoordinateReferenceSystem('EPSG:4326')
        trans_line2geo = QgsCoordinateTransform(crs_line, crs_geo,
                                                transform_context)

        # initialize distance tool
        da = QgsDistanceArea()
        da.setSourceCrs(crs_mercator, transform_context)
        da.setEllipsoid(crs_mercator.ellipsoidAcronym())

        # empty lists for unioned buffers
        buffer_union_list = []

        # get (selected) features
        features = source.getFeatures()

        # feedback
        total = 100.0 / source.featureCount() if source.featureCount() else 0

        # loop through features
        feedback.pushConsoleInfo(self.tr(f'Densifying line features...'))
        feedback.pushConsoleInfo(self.tr(f'Extracting vertices...'))
        feedback.pushConsoleInfo(self.tr(f'Sampling values...'))
        feedback.pushConsoleInfo(
            self.tr(f'Computing depth dependent buffers...'))
        feedback.pushConsoleInfo(self.tr(f'Unionizing output features...'))
        for feature_id, feature in enumerate(features):
            # get feature geometry
            feature_geom = feature.geometry()

            # check for LineString geometry
            if QgsWkbTypes.isSingleType(feature_geom.wkbType()):
                # get list of vertices
                vertices_list = feature_geom.asPolyline()
                vertices_list = [vertices_list]

            # check for MultiLineString geometry
            elif QgsWkbTypes.isMultiType(feature_geom.wkbType()):
                # get list of list of vertices per multiline part
                vertices_list = feature_geom.asMultiPolyline()

            for part_id, vertices in enumerate(vertices_list):
                # transform vertices CRS to "WGS 84 / World Mercator"
                vertices_t = []
                for vertex in vertices:
                    vertex_trans = trans_line2merc.transform(vertex)
                    vertices_t.append(vertex_trans)

                # get centroid as point for UTM zone selection
                centroid = feature_geom.centroid()
                centroid_point = centroid.asPoint()

                # check if centroid needs to be transformed to get x/y in lon/lat
                if not crs_line.isGeographic():
                    centroid_point = trans_line2geo.transform(centroid_point)

                # get UTM zone of feature for buffering
                lat, lon = centroid_point.y(), centroid_point.x()
                crs_utm = self.get_UTM_zone(lat, lon)

                # create back and forth transformations for later
                trans_merc2utm = QgsCoordinateTransform(
                    crs_mercator, crs_utm, transform_context)
                trans_utm2line = QgsCoordinateTransform(
                    crs_utm, crs_line, transform_context)

                # split line into segments
                for segment_id in range(len(vertices_t) - 1):
                    # ===== (1) DENSIFY LINE VERTICES =====
                    # create new Polyline geometry for line segment
                    segment_geom = QgsGeometry.fromPolylineXY(
                        [vertices_t[segment_id], vertices_t[segment_id + 1]])

                    # measure ellipsoidal distance between start and end vertex
                    segment_length = da.measureLength(segment_geom)

                    # calculate number of extra vertices to insert
                    extra_vertices = int(segment_length //
                                         self.vertex_distance)

                    # create additional vertices along line segment
                    segment_geom_dense = segment_geom.densifyByCount(
                        extra_vertices - 1)

                    # initialize additional fields
                    feature_id_field = QgsField('feature_id',
                                                QVariant.Int,
                                                'Integer',
                                                len=5,
                                                prec=0)
                    part_id_field = QgsField('part_id',
                                             QVariant.Int,
                                             'Integer',
                                             len=5,
                                             prec=0)
                    segment_id_field = QgsField('segment_id',
                                                QVariant.Int,
                                                'Integer',
                                                len=5,
                                                prec=0)

                    # list for segment buffers
                    buffer_list = []

                    # loop over all vertices of line segment
                    for i, vertex in enumerate(segment_geom_dense.vertices()):
                        # === CREATE POINT FEATURE ===
                        # initialize feature and set geometry
                        fpoint = QgsFeature()
                        fpoint.setGeometry(vertex)

                        # sample bathymetry grid
                        # get point geometry (as QgsPointXY)
                        fpoint_geom = fpoint.geometry()
                        pointXY = fpoint_geom.asPoint()

                        # transform point to raster CRS
                        pointXY_raster = trans_merc2raster.transform(
                            pointXY)  #trans_line2raster.transform(pointXY)

                        # sample raster at point location
                        pointXY_depth, error_check = raster_layer.dataProvider(
                        ).sample(pointXY_raster, 1)

                        # check if valid depth was sampled, otherwise skip point
                        if error_check == False:
                            continue

                        # create depth-dependant buffer:
                        # check if swath_angle field is selected
                        if swath_angle_field != '':
                            # get value from field
                            swath_angle_field_value = feature.attribute(
                                swath_angle_field)
                            # check if value is set (not NOLL)
                            if swath_angle_field_value == None:
                                # if NULL, set fallback
                                swath_angle = swath_angle_fallback
                            else:
                                # othervise take value from field
                                swath_angle = swath_angle_field_value
                        # or if no field was selected use fallback value right away
                        else:
                            swath_angle = swath_angle_fallback

                        # calculate buffer radius (swath width from depth and swath angle)
                        buffer_radius = round(
                            tan(radians(swath_angle / 2)) * abs(pointXY_depth),
                            0)

                        # transform point from mercator zu UTM
                        fpoint_geom.transform(trans_merc2utm)

                        # create buffer
                        buffer = fpoint_geom.buffer(buffer_radius, 10)

                        # transform buffer back to initial input CRS
                        buffer.transform(trans_utm2line)

                        # store buffer in list
                        buffer_list.append(buffer)

                    # check if any points in this segment have been sampled
                    if buffer_list == []:
                        continue

                    # dissolve point buffers of line segment:
                    # dissolve all polygons based on line vertices into single feature
                    buffer_union = QgsGeometry().unaryUnion(buffer_list)

                    # set fields and attributes:
                    # empty fields
                    buffer_fields = QgsFields()

                    # loop through line feature fields
                    for field in feature.fields():
                        # and append all but the 'fid' field (if it exists)
                        if field.name() != 'fid':
                            buffer_fields.append(field)

                    # append extra buffer fields (intial feature id, part id and segment id
                    for buffer_field in [
                            feature_id_field, part_id_field, segment_id_field
                    ]:
                        buffer_fields.append(buffer_field)

                    # if no input swath_angle field was selected on input, create one
                    if swath_angle_field == '':
                        swath_angle_field_name = 'mbes_swath_angle'
                        buffer_fields.append(
                            QgsField(swath_angle_field_name,
                                     QVariant.Int,
                                     'Integer',
                                     len=5,
                                     prec=0))

                    # initialize polygon feature
                    fpoly = QgsFeature(buffer_fields)

                    # set attributes for polygon feature
                    for field in feature.fields():
                        # ignore 'fid' again
                        if field.name() != 'fid':
                            # set attribute from feature to buffer
                            fpoly.setAttribute(field.name(),
                                               feature.attribute(field.name()))

                    # set addtional buffer fields
                    fpoly.setAttribute('feature_id', feature_id)
                    fpoly.setAttribute('part_id', part_id)
                    fpoly.setAttribute('segment_id', segment_id)
                    fpoly.setAttribute(swath_angle_field_name, swath_angle)

                    # set geometry
                    fpoly.setGeometry(buffer_union)

                    # store segment coverage polygon
                    if fpoly.hasGeometry() and fpoly.isValid():
                        buffer_union_list.append(fpoly)

            # set progess
            feedback.setProgress(int(feature_id * total))

        # if buffer_union_list is empty, no buffer features where created
        if buffer_union_list == []:
            raise Exception(
                'No depth values could be sampled from the input raster!')

        # creating feature sink
        feedback.pushConsoleInfo(self.tr(f'Creating feature sink...'))
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, buffer_fields,
                                               QgsWkbTypes.MultiPolygon,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        # write coverage features to sink
        feedback.pushConsoleInfo(self.tr(f'Writing features...'))
        sink.addFeatures(buffer_union_list, QgsFeatureSink.FastInsert)

        # make variables accessible for post processing
        self.output = dest_id

        result = {self.OUTPUT: self.output}

        return result
Example #33
0
            def densify_poly(in_layer, pr):
                bad_geom = 0
                iterator = in_layer.getFeatures()
                # create empty feature to write to
                for feature in iterator:
                    try:
                        if feature.geometry().wkbType(
                        ) == QgsWkbTypes.LineString:
                            line_geom = feature.geometry().asPolyline()
                            geom_type = "LineString"
                        elif feature.geometry().wkbType(
                        ) == QgsWkbTypes.MultiLineString:
                            multiline_geom = feature.geometry(
                            ).asMultiPolyline()
                            geom_type = "MultiLineString"
                        elif feature.geometry().wkbType(
                        ) == QgsWkbTypes.Polygon:
                            poly_geom = feature.geometry().asPolygon()
                            geom_type = "Polygon"
                        elif feature.geometry().wkbType(
                        ) == QgsWkbTypes.MultiPolygon:
                            multipoly_geom = feature.geometry().asMultiPolygon(
                            )
                            geom_type = "MultiPolygon"
                        else:
                            bad_geom += 1
                    except:
                        bad_geom += 1

                    if geom_type == "LineString":
                        dense_points = []
                        point_count = len(line_geom)
                        start_pt = QgsPointXY(line_geom[0][0], line_geom[0][1])
                        dense_points.append(start_pt)
                        if self.inLayer.crs() != wgs84crs:
                            start_pt = transtowgs84.transform(start_pt)
                        for j in range(1, point_count):
                            end_pt = QgsPointXY(line_geom[j][0],
                                                line_geom[j][1])
                            if self.inLayer.crs() != wgs84crs:
                                end_pt = transtowgs84.transform(end_pt)
                            # create a geographiclib line object
                            line_object = self.geod.InverseLine(
                                start_pt.y(), start_pt.x(), end_pt.y(),
                                end_pt.x())
                            # determine how many densified segments there will be
                            if self.segmentMethod == 'count':
                                n = self.segmentCount
                            else:
                                n = int(
                                    math.ceil(line_object.s13 / self.spacing))
                            if line_object.s13 > self.spacing:
                                seglen = line_object.s13 / n
                                for k in range(1, n):
                                    s = seglen * k
                                    g = line_object.Position(
                                        s,
                                        Geodesic.LATITUDE | Geodesic.LONGITUDE
                                        | Geodesic.LONG_UNROLL)
                                    waypoint = QgsPointXY(g['lon2'], g['lat2'])
                                    if self.inLayer.crs() != wgs84crs:
                                        waypoint = transfromwgs84.transform(
                                            waypoint)
                                    dense_points.append(waypoint)
                                if self.inLayer.crs() != wgs84crs:
                                    end_pt = transfromwgs84.transform(end_pt)
                                dense_points.append(end_pt)
                            start_pt = end_pt

                    elif geom_type == "MultiLineString":
                        dense_features = []
                        for i in range(len(multiline_geom)):
                            dense_points = []
                            line = multiline_geom[i]
                            point_count = len(line)
                            start_pt = QgsPointXY(line[0][0], line[0][1])
                            dense_points.append(start_pt)
                            for j in range(1, point_count):
                                end_pt = QgsPointXY(line[j][0], line[j][1])
                                if self.inLayer.crs() != wgs84crs:
                                    start_pt = transtowgs84.transform(start_pt)
                                    end_pt = transtowgs84.transform(end_pt)
                                # create a geographiclib line object
                                line_object = self.geod.InverseLine(
                                    start_pt.y(), start_pt.x(), end_pt.y(),
                                    end_pt.x())
                                # determine how many densified segments there will be
                                if self.segmentMethod == 'count':
                                    n = self.segmentCount
                                else:
                                    n = int(
                                        math.ceil(line_object.s13 /
                                                  self.spacing))
                                if line_object.s13 > self.spacing:
                                    seglen = line_object.s13 / n
                                    for k in range(1, n):
                                        s = seglen * k
                                        g = line_object.Position(
                                            s, Geodesic.LATITUDE
                                            | Geodesic.LONGITUDE
                                            | Geodesic.LONG_UNROLL)
                                        waypoint = QgsPointXY(
                                            g['lon2'], g['lat2'])
                                        if self.inLayer.crs() != wgs84crs:
                                            waypoint = transfromwgs84.transform(
                                                waypoint)
                                        dense_points.append(waypoint)
                                    if self.inLayer.crs() != wgs84crs:
                                        end_pt = transfromwgs84.transform(
                                            end_pt)
                                    dense_points.append(end_pt)
                                start_pt = end_pt
                            dense_features.append(dense_points)

                    elif geom_type == "Polygon":
                        for poly in poly_geom:
                            dense_points = []
                            point_count = len(poly)
                            start_pt = QgsPointXY(poly[0][0], poly[0][1])
                            dense_points.append(start_pt)
                            for j in range(1, point_count):
                                end_pt = QgsPointXY(poly[j][0], poly[j][1])
                                if self.inLayer.crs() != wgs84crs:
                                    end_pt = transtowgs84.transform(end_pt)
                                    start_pt = transtowgs84.transform(start_pt)
                                # create a geographiclib line object
                                line_object = self.geod.InverseLine(
                                    start_pt.y(), start_pt.x(), end_pt.y(),
                                    end_pt.x())
                                # determine how many densified segments there will be
                                if self.segmentMethod == 'count':
                                    n = self.segmentCount
                                else:
                                    n = int(
                                        math.ceil(line_object.s13 /
                                                  self.spacing))
                                if line_object.s13 > self.spacing:
                                    seglen = line_object.s13 / n
                                    for k in range(1, n):
                                        s = seglen * k
                                        g = line_object.Position(
                                            s, Geodesic.LATITUDE
                                            | Geodesic.LONGITUDE
                                            | Geodesic.LONG_UNROLL)
                                        waypoint = QgsPointXY(
                                            g['lon2'], g['lat2'])
                                        if self.inLayer.crs() != wgs84crs:
                                            waypoint = transfromwgs84.transform(
                                                waypoint)
                                        dense_points.append(waypoint)
                                    if self.inLayer.crs() != wgs84crs:
                                        end_pt = transfromwgs84.transform(
                                            end_pt)
                                    dense_points.append(end_pt)
                                start_pt = end_pt

                    if geom_type == "MultiPolygon":
                        dense_features = []
                        for i in range(len(multipoly_geom)):
                            dense_points = []
                            poly = multipoly_geom[i][0]
                            point_count = len(poly)
                            start_pt = QgsPointXY(poly[0][0], poly[0][1])
                            dense_points.append(start_pt)
                            for j in range(1, point_count):
                                end_pt = QgsPointXY(poly[j][0], poly[j][1])
                                if self.inLayer.crs() != wgs84crs:
                                    start_pt = transtowgs84.transform(start_pt)
                                    end_pt = transtowgs84.transform(end_pt)
                                # create a geographiclib line object
                                line_object = self.geod.InverseLine(
                                    start_pt.y(), start_pt.x(), end_pt.y(),
                                    end_pt.x())
                                # determine how many densified segments there will be
                                if self.segmentMethod == 'count':
                                    n = self.segmentCount
                                else:
                                    n = int(
                                        math.ceil(line_object.s13 /
                                                  self.spacing))
                                if line_object.s13 > self.spacing:
                                    seglen = line_object.s13 / n
                                    for k in range(1, n):
                                        s = seglen * k
                                        g = line_object.Position(
                                            s, Geodesic.LATITUDE
                                            | Geodesic.LONGITUDE
                                            | Geodesic.LONG_UNROLL)
                                        waypoint = QgsPointXY(
                                            g['lon2'], g['lat2'])
                                        if self.inLayer.crs() != wgs84crs:
                                            waypoint = transfromwgs84.transform(
                                                waypoint)
                                        dense_points.append(waypoint)
                                    if self.inLayer.crs() != wgs84crs:
                                        end_pt = transfromwgs84.transform(
                                            end_pt)
                                    dense_points.append(end_pt)
                                start_pt = end_pt
                            dense_features.append(dense_points)

                    new_poly = QgsFeature()
                    if geom_type == "LineString":
                        new_poly.setGeometry(
                            QgsGeometry.fromPolylineXY(dense_points))
                    elif geom_type == "MultiLineString":
                        new_poly.setGeometry(
                            QgsGeometry.fromMultiPolylineXY(dense_features))
                    elif geom_type == "Polygon":
                        new_poly.setGeometry(
                            QgsGeometry.fromPolygonXY([dense_points]))
                    elif geom_type == "MultiPolygon":
                        new_poly.setGeometry(
                            QgsGeometry.fromMultiPolygonXY([dense_features]))
                    new_poly.setAttributes(feature.attributes())
                    pr.addFeatures([new_poly])
                if bad_geom > 0:
                    self.iface.messageBar().pushWarning(
                        "", "{} features failed".format(bad_geom))
Example #34
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        arrets = self.parameterAsSource(parameters, self.STOPS, context)
        stop_id = self.parameterAsFields(parameters, self.STOP_ID, context)[0]
        noeuds = self.parameterAsSource(parameters, self.NOEUDS, context)
        node_id = self.parameterAsFields(parameters, self.NODE_ID, context)[0]
        mode_i = self.parameterAsString(parameters, self.MODE_ORI, context)
        mode_j = self.parameterAsString(parameters, self.MODE_DES, context)
        texte_i = self.parameterAsString(parameters, self.TEXTE_ORI, context)
        texte_j = self.parameterAsString(parameters, self.TEXTE_DES, context)
        rayon = self.parameterAsDouble(parameters, self.RAYON, context)
        vitesse = self.parameterAsDouble(parameters, self.VITESSE, context)
        nb_max = self.parameterAsInt(parameters, self.MAX_NB, context)
        l0 = self.parameterAsBool(parameters, self.LONG_0, context)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        ##a=fenetre.split(",")
        ##fenetre2=QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3]))
        arr = [a for a in arrets.getFeatures()]
        nb = len(arr)

        index = QgsSpatialIndex(noeuds.getFeatures())
        champs = QgsFields()
        champs.append(QgsField('i', QVariant.String, len=15))
        champs.append(QgsField('j', QVariant.String, len=15))
        champs.append(QgsField(self.tr('length'), QVariant.Double))
        champs.append(QgsField(self.tr('time'), QVariant.Double))
        champs.append(QgsField(self.tr('mode'), QVariant.String, len=10))

        (table_connecteurs,
         dest_id) = self.parameterAsSink(parameters, self.CONNECTEURS, context,
                                         champs, QgsWkbTypes.LineString,
                                         noeuds.sourceCrs())
        nom_fichier = dest_id
        fichier_connecteurs = os.path.splitext(nom_fichier)[0] + ".txt"
        sortie = codecs.open(fichier_connecteurs, "w", encoding="utf-8")
        nbc = 0
        for i, n in enumerate(arr):
            near = index.nearestNeighbor(n.geometry().centroid().asPoint(),
                                         nb_max)
            feedback.setProgress(i * 100 / nb)
            if len(near) > 0:
                for k, nearest in enumerate(near):
                    if k < nb_max:
                        f = noeuds.getFeatures(
                            request=QgsFeatureRequest(nearest))
                        for j, g in enumerate(f):
                            if j == 0:
                                l = n.geometry().distance(g.geometry())
                                id_node = unicode(g.attribute(node_id))
                                id_stop = unicode(n.attribute(stop_id))
                                if l < rayon:
                                    nbc += 1
                                    gline = QgsGeometry.fromPolylineXY([
                                        QgsPointXY(
                                            n.geometry().centroid().asPoint()),
                                        QgsPointXY(
                                            g.geometry().centroid().asPoint())
                                    ])
                                    hline = QgsGeometry.fromPolylineXY([
                                        QgsPointXY(
                                            g.geometry().centroid().asPoint()),
                                        QgsPointXY(
                                            n.geometry().centroid().asPoint())
                                    ])

                                    fline = QgsFeature()
                                    fline.setGeometry(gline)
                                    if l0 == 0:
                                        ll = 0
                                    else:
                                        ll = gline.length()
                                    moda = unicode(mode_i) + unicode(mode_j)
                                    if vitesse <= 0:
                                        fline.setAttributes([
                                            id_stop, id_node, ll / 1000, 0.0,
                                            moda
                                        ])
                                    else:
                                        fline.setAttributes([
                                            id_stop, id_node, ll / 1000,
                                            ll * 60 / (vitesse * 1000), moda
                                        ])
                                    fline2 = QgsFeature()
                                    fline2.setGeometry(hline)
                                    modb = unicode(mode_j) + unicode(mode_i)
                                    if vitesse <= 0:
                                        fline2.setAttributes([
                                            id_node, id_stop, ll / 1000, 0,
                                            modb
                                        ])
                                    else:
                                        fline2.setAttributes([
                                            id_node, id_stop, ll / 1000,
                                            ll * 60 / (vitesse * 1000), modb
                                        ])
                                    table_connecteurs.addFeature(fline)
                                    table_connecteurs.addFeature(fline2)
                                    if vitesse > 0:
                                        sortie.write(id_node + ';' + id_stop +
                                                     ';' + str((60 / vitesse) *
                                                               (ll / 1000.0)) +
                                                     ';' + str(ll / 1000.0) +
                                                     ';-1;-1;-1;-1;-1;' +
                                                     modb + ';' + modb + '\n')
                                        sortie.write(id_stop + ';' + id_node +
                                                     ';' + str((60 / vitesse) *
                                                               (ll / 1000.0)) +
                                                     ';' + str(ll / 1000.0) +
                                                     ';-1;-1;-1;-1;-1;' +
                                                     moda + ';' + moda + '\n')
                                    else:
                                        sortie.write(id_node + ';' + id_stop +
                                                     ';' + str(0.0) + ';' +
                                                     str(ll / 1000.0) +
                                                     ';-1;-1;-1;-1;-1;' +
                                                     modb + ';' + modb + '\n')
                                        sortie.write(id_stop + ';' + id_node +
                                                     ';' + str(0.0) + ';' +
                                                     str(ll / 1000.0) +
                                                     ';-1;-1;-1;-1;-1;' +
                                                     moda + ';' + moda + '\n')
        feedback.setProgressText(
            unicode(nbc) + "/" + unicode(nb) + self.tr(" connected nodes"))
        sortie.close()
        return {self.OUTPUT: dest_id}
Example #35
0
    def getZigZag(self, wavelength=None, shpExtent=None):

        TOMsMessageLog.logMessage("In getZigZag ... ", level=Qgis.Info)

        if not wavelength:
            wavelength = 3.0
        if not shpExtent:
            shpExtent = self.BayWidth / 2
        offset = self.BayOffsetFromKerb

        line = generateGeometryUtils.getLineForAz(self.currFeature)
        if len(line) == 0:
            return 0

        ptsList = []

        length = self.currFeature.geometry().length()

        NrSegments = int(length / wavelength)    # e.g., length = 33, wavelength = 4
        interval = int(length/float(NrSegments) * 10000) / 10000

        TOMsMessageLog.logMessage("In getZigZag. LengthLine: " + str(length) + " NrSegments = " + str(NrSegments) + "; interval: " + str(interval), level=Qgis.Info)

        Az = line[0].azimuth(line[1])

        # TOMsMessageLog.logMessage("In getZigZag. Az = " + str(Az) + "; AzCL = " + str(self.currAzimuthToCentreLine) + "; line[0]: " + line[0].asWkt() + "; line[1]: " + line[1].asWkt(), level=Qgis.Info)

        Turn = generateGeometryUtils.turnToCL(Az, self.currAzimuthToCentreLine)

        newAz = Az + Turn
        # TOMsMessageLog.logMessage("In generate_display_geometry: newAz: " + str(newAz), level=Qgis.Info)
        cosa, cosb = generateGeometryUtils.cosdir_azim(newAz)

        # deal with two points
        ptsList.append(
            QgsPointXY(line[0].x() + (float(offset) * cosa), line[0].y() + (float(offset) * cosb)))

        ptsList.append(
            QgsPointXY(line[0].x() + (float(shpExtent) * cosa),
                     line[0].y() + (float(shpExtent) * cosb)))

        distanceAlongLine = 0.0
        countSegments = 0
        while countSegments < (NrSegments):

            countSegments = countSegments + 1

            distanceAlongLine = distanceAlongLine + interval / 2

            interpolatedPointC = self.currFeature.geometry().interpolate(distanceAlongLine).asPoint()

            TOMsMessageLog.logMessage("In getZigZag. PtC = " + str(interpolatedPointC.x()) + ": " + str(interpolatedPointC.y()) + "; distanceAlongLine = " + str(distanceAlongLine), level=Qgis.Info)
            # TOMsMessageLog.logMessage("In getZigZag. offset = " + str(float(offset)) + "; cosa = " + str(cosa) + "; cosb = " + str(cosb), level=Qgis.Info)

            TOMsMessageLog.logMessage("In getZigZag. newC x = " + str(interpolatedPointC.x() + (float(offset) * cosa)) + "; y = " + str(interpolatedPointC.y() + (float(offset) * cosb)), level=Qgis.Info)

            ptsList.append(QgsPointXY(interpolatedPointC.x() + (float(offset) * cosa), interpolatedPointC.y() + (float(offset) * cosb)))

            distanceAlongLine = distanceAlongLine+interval/2

            interpolatedPointD = self.currFeature.geometry().interpolate(distanceAlongLine).asPoint()

            # TOMsMessageLog.logMessage("In getZigZag. PtD = " + interpolatedPointD.asWkt() + "; distanceAlongLine = " + str(distanceAlongLine), level=Qgis.Info)

            ptsList.append(QgsPointXY(interpolatedPointD.x() + (float(shpExtent) * cosa),
                     interpolatedPointD.y() + (float(shpExtent) * cosb)))

        # deal with last point
        ptsList.append(
            QgsPointXY(line[len(line) - 1].x() + (float(offset) * cosa),
                     line[len(line) - 1].y() + (float(offset) * cosb)))

        newLine = QgsGeometry.fromPolylineXY(ptsList)

        return newLine
    def accept(self):
        try:
            distance = float(self.distLineEdit.text())
            azimuth = float(self.azimuthLineEdit.text())
            units = self.unitsComboBox.currentIndex(
            )  # 0 km, 1 m, 2 nm, 3 miles, 4 yards, 5 ft, 6 inches, 7 cm
            start = self.checkBox.isChecked()
        except Exception:
            self.iface.messageBar().pushMessage(
                "",
                tr("Either distance or azimuth were invalid"),
                level=Qgis.Warning,
                duration=4)
            return
        layer = self.iface.activeLayer()
        if layer is None:
            self.iface.messageBar().pushMessage(
                "",
                tr("No point or line layer selected"),
                level=Qgis.Warning,
                duration=4)
            return

        measureFactor = conversionToMeters(units)

        distance = distance * measureFactor
        pt = self.pt
        destCRS = layer.crs()
        transform = QgsCoordinateTransform(epsg4326, destCRS,
                                           QgsProject.instance())
        if layer.wkbType() == QgsWkbTypes.Point:
            g = geod.Direct(pt.y(), pt.x(), azimuth, distance,
                            Geodesic.LATITUDE | Geodesic.LONGITUDE)
            if start:
                ptStart = transform.transform(self.pt.x(), self.pt.y())
                feat = QgsFeature(layer.fields())
                feat.setGeometry(QgsGeometry.fromPointXY(ptStart))
                layer.addFeature(feat)
            pt = transform.transform(g['lon2'], g['lat2'])
            feat = QgsFeature(layer.fields())
            feat.setGeometry(QgsGeometry.fromPointXY(pt))
            layer.addFeature(feat)
        else:  # It will either be a LineString or MultiLineString
            maxseglen = settings.maxSegLength * 1000.0  # Needs to be in meters
            maxSegments = settings.maxSegments
            gline = geod.Line(pt.y(), pt.x(), azimuth)
            n = int(math.ceil(distance / maxseglen))
            if n > maxSegments:
                n = maxSegments
            seglen = distance / n
            pts = []
            for i in range(0, n + 1):
                s = seglen * i
                g = gline.Position(
                    s, Geodesic.LATITUDE | Geodesic.LONGITUDE
                    | Geodesic.LONG_UNROLL)
                ptc = transform.transform(g['lon2'], g['lat2'])
                pts.append(ptc)
            feat = QgsFeature(layer.fields())
            if layer.wkbType() == QgsWkbTypes.LineString:
                feat.setGeometry(QgsGeometry.fromPolylineXY(pts))
            else:
                feat.setGeometry(QgsGeometry.fromMultiPolylineXY([pts]))
            layer.addFeatures([feat])

        layer.updateExtents()
        self.iface.mapCanvas().refresh()
        self.close()
Example #37
0
    def processAlgorithm(self, parameters, context, feedback):

        t_regard = self.parameterAsSource(parameters, self.MANHOLES_TABLE,
                                          context)
        g_regard = self.parameterAsSource(parameters, self.GEOM_MANHOLES,
                                          context)
        t_troncon = self.parameterAsVectorLayer(parameters,
                                                self.SEGMENTS_TABLE, context)
        g_troncon = self.parameterAsVectorLayer(parameters, self.GEOM_SEGMENTS,
                                                context)

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(
            QgsExpressionContextUtils.projectScope(context.project()))
        exp_context.appendScope(
            QgsExpressionContextUtils.layerScope(t_troncon))

        exp_str = '"id_geom_troncon" IS NULL'
        exp = QgsExpression(exp_str)

        exp.prepare(exp_context)
        if exp.hasEvalError():
            raise QgsProcessingException(
                tr('* ERROR: Expression {} has eval error: {}').format(
                    exp.expression(), exp.evalErrorString()))

        request = QgsFeatureRequest(exp, exp_context)
        r_ids = []  # identifiant des regards
        l_t_f = {}  # lien troncon fichier
        l_f_t = {}  # lien fichier troncons
        troncons = {}
        sorties = {}
        entrees = {}
        for tro in t_troncon.getFeatures(request):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                return {self.SEGMENT_CREATED: None}

            segment_number = tro['id']
            r1 = tro['id_regard1']
            r2 = tro['id_regard2']

            if r1 not in r_ids:
                r_ids.append(r1)
            if r2 not in r_ids:
                r_ids.append(r2)

            fid = tro['id_file']
            l_t_f[segment_number] = fid
            if fid in l_f_t:
                l_f_t[fid] = l_f_t[fid] + [segment_number]
            else:
                l_f_t[fid] = [segment_number]

            troncons[segment_number] = (r1, r2)
            if r1 in sorties:
                sorties[r1] = sorties[r1] + [segment_number]
            else:
                sorties[r1] = [segment_number]
            if r2 in entrees:
                entrees[r2] = entrees[r2] + [segment_number]
            else:
                entrees[r2] = [segment_number]

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(
            QgsExpressionContextUtils.projectScope(context.project()))
        exp_context.appendScope(t_regard.createExpressionContextScope())

        exp_str = ('"id_geom_regard" IS NOT NULL '
                   'AND '
                   '"id" IN ({})').format(','.join([str(i)
                                                    for i in r_ids] + ['-1']))
        exp = QgsExpression(exp_str)

        exp.prepare(exp_context)
        if exp.hasEvalError():
            raise QgsProcessingException(
                tr('* ERROR: Expression {} has eval error: {}').format(
                    exp.expression(), exp.evalErrorString()))

        request = QgsFeatureRequest(exp, exp_context)
        g_ids = []  # identifiants des géométrie de regards
        l_r_g = {}  # lien regard geometrie
        l_g_r = {}  # lien geometrie regards
        for reg in t_regard.getFeatures(request):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                return {self.SEGMENT_CREATED: None}

            segment_number = reg['id']
            fid = reg['id_file']

            if segment_number in sorties:
                sorties[segment_number] = [
                    trid for trid in sorties[segment_number]
                    if l_t_f[trid] == fid
                ]
            if segment_number in entrees:
                entrees[segment_number] = [
                    trid for trid in entrees[segment_number]
                    if l_t_f[trid] == fid
                ]

            gid = reg['id_geom_regard']
            l_r_g[segment_number] = gid
            if gid not in g_ids:
                g_ids.append(gid)
            if gid in l_g_r:
                l_g_r[gid] = l_g_r[gid] + [segment_number]
            else:
                l_g_r[gid] = [segment_number]

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(
            QgsExpressionContextUtils.projectScope(context.project()))
        exp_context.appendScope(g_regard.createExpressionContextScope())

        exp_str = '"id" IN ({})'.format(','.join([str(i)
                                                  for i in g_ids] + ['-1']))
        exp = QgsExpression(exp_str)

        exp.prepare(exp_context)
        if exp.hasEvalError():
            raise QgsProcessingException(
                tr('* ERROR: Expression {} has eval error: {}').format(
                    exp.expression(), exp.evalErrorString()))

        request = QgsFeatureRequest(exp, exp_context)
        points = {}
        pt_labels = {}
        for reg in g_regard.getFeatures(request):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                return {self.SEGMENT_CREATED: None}

            segment_number = reg['id']
            points[segment_number] = reg.geometry().asPoint()
            pt_labels[segment_number] = reg['label']

        lines = {}
        for gid in points:
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                return {self.SEGMENT_CREATED: None}

            if gid not in l_g_r:
                continue

            for rid in l_g_r[gid]:
                # Stop the algorithm if cancel button has been clicked
                if feedback.isCanceled():
                    return {self.SEGMENT_CREATED: None}

                if rid in sorties:
                    for tid in sorties[rid]:
                        # Stop the algorithm if cancel button has been clicked
                        if feedback.isCanceled():
                            return {self.SEGMENT_CREATED: None}

                        if tid in lines:
                            continue
                        if tid not in troncons:
                            continue
                        r2 = troncons[tid][1]
                        if r2 not in l_r_g:
                            continue
                        g2 = l_r_g[r2]
                        if g2 not in points:
                            continue
                        lines[tid] = (gid, g2)

                if rid in entrees:
                    for tid in entrees[rid]:
                        # Stop the algorithm if cancel button has been clicked
                        if feedback.isCanceled():
                            return {self.SEGMENT_CREATED: None}

                        if tid in lines:
                            continue
                        if tid not in troncons:
                            continue
                        r1 = troncons[tid][0]
                        if r1 not in l_r_g:
                            continue
                        g1 = l_r_g[r1]
                        if g1 not in points:
                            continue
                        lines[tid] = (g1, gid)

        # Creation des troncons
        l_t_g = {}  # lien troncon et geometrie troncon
        l_pts_t = {}  # lien points troncons
        features = []  # les objets de geometrie de troncon
        geom_point_keys = []  # liste des clés des points troncons
        for tid, pts in lines.items():
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                return {self.SEGMENT_CREATED: None}

            exp_context = QgsExpressionContext()
            exp_context.appendScope(QgsExpressionContextUtils.globalScope())
            exp_context.appendScope(
                QgsExpressionContextUtils.projectScope(context.project()))
            exp_context.appendScope(
                QgsExpressionContextUtils.layerScope(g_troncon))

            exp_str = ('"id_geom_regard_amont" = {} AND '
                       '"id_geom_regard_aval" = {}').format(pts[0], pts[1])
            exp = QgsExpression(exp_str)

            exp.prepare(exp_context)
            if exp.hasEvalError():
                raise QgsProcessingException(
                    tr('* ERROR: Expression {} has eval error: {}').format(
                        exp.expression(), exp.evalErrorString()))

            request = QgsFeatureRequest(exp, exp_context)
            request.setLimit(1)
            for tro in g_troncon.getFeatures(request):
                l_t_g[tid] = tro['id']
                continue

            if (pts[0], pts[1]) in geom_point_keys:
                l_pts_t[(pts[0], pts[1])].append(tid)
                continue
            else:
                l_pts_t[(pts[0], pts[1])] = [tid]
                geom_point_keys.append((pts[0], pts[1]))

            feat_t = QgsVectorLayerUtils.createFeature(g_troncon)
            feat_t.setAttribute(
                'label', '{}-{}'.format(pt_labels[pts[0]], pt_labels[pts[1]]))
            feat_t.setAttribute('id_geom_regard_amont', pts[0])
            feat_t.setAttribute('id_geom_regard_aval', pts[1])
            feat_t.setGeometry(
                QgsGeometry.fromPolylineXY([points[pts[0]], points[pts[1]]]))
            features.append(feat_t)

        # Ajout des objets troncons
        if features:
            g_troncon.startEditing()
            (res, outFeats) = g_troncon.dataProvider().addFeatures(features)
            if not res or not outFeats:
                raise QgsProcessingException(
                    tr('* ERREUR: lors de l\'enregistrement '
                       'des regards {}').format(', '.join(
                           g_troncon.dataProvider().errors())))
            if not g_troncon.commitChanges():
                raise QgsProcessingException(
                    tr('* ERROR: Commit {}.').format(g_troncon.commitErrors()))

            for tro in outFeats:
                # Stop the algorithm if cancel button has been clicked
                if feedback.isCanceled():
                    return {self.SEGMENT_CREATED: None}

                if not tro['id']:
                    continue
                key = (tro['id_geom_regard_amont'], tro['id_geom_regard_aval'])
                if key not in geom_point_keys:
                    continue
                for tid in l_pts_t[(pts[0], pts[1])]:
                    l_t_g[tid] = tro['id']
                    # Stop the algorithm if cancel button has been clicked
                    if feedback.isCanceled():
                        return {self.SEGMENT_CREATED: None}

        for tid, pts in lines.items():
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                return {self.SEGMENT_CREATED: None}

            if tid in l_t_g:
                continue
            exp_context = QgsExpressionContext()
            exp_context.appendScope(QgsExpressionContextUtils.globalScope())
            exp_context.appendScope(
                QgsExpressionContextUtils.projectScope(context.project()))
            exp_context.appendScope(
                QgsExpressionContextUtils.layerScope(g_troncon))

            exp_str = ('"id_geom_regard_amont" = {} AND '
                       '"id_geom_regard_aval" = {}').format(pts[0], pts[1])
            exp = QgsExpression(exp_str)

            exp.prepare(exp_context)
            if exp.hasEvalError():
                raise QgsProcessingException(
                    tr('* ERROR: Expression {} has eval error: {}').format(
                        exp.expression(), exp.evalErrorString()))

            request = QgsFeatureRequest(exp, exp_context)
            request.setLimit(1)
            for tro in g_troncon.getFeatures(request):
                l_t_g[tid] = tro['id']
                # Stop the algorithm if cancel button has been clicked
                if feedback.isCanceled():
                    return {self.SEGMENT_CREATED: None}

        if not l_t_g.keys():
            raise QgsProcessingException(
                tr('* ERREUR: Aucune géométrie de tronçon'))

        # Mise a jour de la table troncon
        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(
            QgsExpressionContextUtils.projectScope(context.project()))
        exp_context.appendScope(
            QgsExpressionContextUtils.layerScope(t_troncon))

        exp_str = ('"id_geom_troncon" IS NULL AND '
                   'id IN ({})').format(','.join(
                       [str(i) for i in l_t_g.keys()]))
        exp = QgsExpression(exp_str)

        exp.prepare(exp_context)
        if exp.hasEvalError():
            raise QgsProcessingException(
                tr('* ERROR: Expression %s has eval error: %s').format(
                    exp.expression(), exp.evalErrorString()))

        # Mise a jour de la table de tronçon
        request = QgsFeatureRequest(exp, exp_context)
        t_troncon.startEditing()
        segment_number = 0
        for tro in t_troncon.getFeatures(request):
            tro.setAttribute('id_geom_troncon', l_t_g[tro['id']])
            t_troncon.updateFeature(tro)
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                return {self.SEGMENT_CREATED: None}
            segment_number += 1

        if not t_troncon.commitChanges():
            raise QgsProcessingException(
                tr('* ERROR: Commit %s.') % t_troncon.commitErrors())

        # Returns empty dict if no outputs
        return {self.SEGMENT_CREATED: segment_number}
Example #38
0
    def processAlgorithm(self, parameters, context, feedback):
        feedback.pushInfo(
            self.tr(
                "[QNEAT3Algorithm] This is a QNEAT3 Algorithm: '{}'".format(
                    self.displayName())))
        network = self.parameterAsSource(parameters, self.INPUT,
                                         context)  #QgsProcessingFeatureSource
        points = self.parameterAsSource(parameters, self.POINTS,
                                        context)  #QgsProcessingFeatureSource
        id_field = self.parameterAsString(parameters, self.ID_FIELD,
                                          context)  #str
        strategy = self.parameterAsEnum(parameters, self.STRATEGY,
                                        context)  #int

        directionFieldName = self.parameterAsString(
            parameters, self.DIRECTION_FIELD,
            context)  #str (empty if no field given)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD,
                                              context)  #str
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD,
                                               context)  #str
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH,
                                           context)  #str
        defaultDirection = self.parameterAsEnum(parameters,
                                                self.DEFAULT_DIRECTION,
                                                context)  #int
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD,
                                                context)  #str
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED,
                                              context)  #float
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE,
                                           context)  #float

        analysisCrs = network.sourceCrs()

        if analysisCrs.isGeographic():
            raise QgsProcessingException(
                'QNEAT3 algorithms are designed to work with projected coordinate systems. Please use a projected coordinate system (eg. UTM zones) instead of geographic coordinate systems (eg. WGS84)!'
            )

        if analysisCrs != points.sourceCrs():
            raise QgsProcessingException(
                'QNEAT3 algorithms require that all inputs to be the same projected coordinate reference system (including project coordinate system).'
            )

        feedback.pushInfo("[QNEAT3Algorithm] Building Graph...")
        net = Qneat3Network(network, points, strategy, directionFieldName,
                            forwardValue, backwardValue, bothValue,
                            defaultDirection, analysisCrs, speedFieldName,
                            defaultSpeed, tolerance, feedback)

        list_analysis_points = [
            Qneat3AnalysisPoint("point", feature, id_field, net,
                                net.list_tiedPoints[i], feedback)
            for i, feature in enumerate(
                getFeaturesFromQgsIterable(net.input_points))
        ]

        feat = QgsFeature()
        fields = QgsFields()
        output_id_field_data_type = getFieldDatatype(points, id_field)
        fields.append(
            QgsField('InputID', output_id_field_data_type, '', 254, 0))
        fields.append(
            QgsField('TargetID', output_id_field_data_type, '', 254, 0))
        fields.append(QgsField('entry_cost', QVariant.Double, '', 20, 7))
        fields.append(QgsField('network_cost', QVariant.Double, '', 20, 7))
        fields.append(QgsField('exit_cost', QVariant.Double, '', 20, 7))
        fields.append(QgsField('total_cost', QVariant.Double, '', 20, 7))
        feat.setFields(fields)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.LineString,
                                               network.sourceCrs())

        total_workload = float(pow(len(list_analysis_points), 2))
        feedback.pushInfo(
            "[QNEAT3Algorithm] Expecting total workload of {} iterations".
            format(int(total_workload)))

        current_workstep_number = 0

        for start_point in list_analysis_points:
            #optimize in case of undirected (not necessary to call calcDijkstra as it has already been calculated - can be replaced by reading from list)
            dijkstra_query = net.calcDijkstra(start_point.network_vertex_id, 0)
            for query_point in list_analysis_points:
                if (current_workstep_number % 1000) == 0:
                    feedback.pushInfo(
                        "[QNEAT3Algorithm] {} OD-pairs processed...".format(
                            current_workstep_number))
                if query_point.point_id == start_point.point_id:
                    feat['InputID'] = start_point.point_id
                    feat['TargetID'] = query_point.point_id
                    feat['entry_cost'] = 0.0
                    feat['network_cost'] = 0.0
                    feat['exit_cost'] = 0.0
                    feat['total_cost'] = 0.0
                    sink.addFeature(feat, QgsFeatureSink.FastInsert)
                elif dijkstra_query[0][query_point.network_vertex_id] == -1:
                    feat['InputID'] = start_point.point_id
                    feat['TargetID'] = query_point.point_id
                    #do not populate cost field so that it defaults to null
                    sink.addFeature(feat, QgsFeatureSink.FastInsert)
                else:
                    network_cost = dijkstra_query[1][
                        query_point.network_vertex_id]
                    feat.setGeometry(
                        QgsGeometry.fromPolylineXY(
                            [start_point.point_geom, query_point.point_geom]))
                    feat['InputID'] = start_point.point_id
                    feat['TargetID'] = query_point.point_id
                    feat['entry_cost'] = start_point.entry_cost
                    feat['network_cost'] = network_cost
                    feat['exit_cost'] = query_point.entry_cost
                    feat[
                        'total_cost'] = network_cost + start_point.entry_cost + query_point.entry_cost
                    sink.addFeature(feat, QgsFeatureSink.FastInsert)
                current_workstep_number = current_workstep_number + 1
                feedback.setProgress(
                    (current_workstep_number / total_workload) * 100)

        feedback.pushInfo(
            "[QNEAT3Algorithm] Total number of OD-pairs processed: {}".format(
                current_workstep_number))

        feedback.pushInfo("[QNEAT3Algorithm] Ending Algorithm")
        results = {}
        results[self.OUTPUT] = dest_id
        return results
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer,
                                        context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        anglecol = self.parameterAsString(parameters,
                                          self.PrmStartingAngleField, context)
        radiuscol = self.parameterAsString(parameters, self.PrmRadiusField,
                                           context)
        radius = self.parameterAsDouble(parameters, self.PrmRadius, context)
        startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle,
                                            context)
        segments = self.parameterAsInt(parameters, self.PrmDrawingSegments,
                                       context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure,
                                    context)
        export_geom = self.parameterAsBool(parameters,
                                           self.PrmExportInputGeometry,
                                           context)

        # The algorithm creates the heart on its side so this rotates
        # it so that it is upright.
        startAngle -= 90.0

        measureFactor = conversionToMeters(units)
        radius *= measureFactor

        srcCRS = source.sourceCrs()
        fields = source.fields()
        if export_geom:
            names = fields.names()
            name_x, name_y = settings.getGeomNames(names)
            fields.append(QgsField(name_x, QVariant.Double))
            fields.append(QgsField(name_y, QVariant.Double))
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                                                   self.PrmOutputLayer,
                                                   context, fields,
                                                   QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink,
             dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer,
                                             context, fields,
                                             QgsWkbTypes.LineString, srcCRS)

        if srcCRS != epsg4326:
            geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326,
                                                QgsProject.instance())
            toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS,
                                               QgsProject.instance())

        featureCount = source.featureCount()
        total = 100.0 / featureCount if featureCount else 0

        step = 360.0 / segments
        numbad = 0
        iterator = source.getFeatures()
        for index, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                if anglecol:
                    sangle = float(feature[anglecol]) - 90
                else:
                    sangle = startAngle
                if radiuscol:
                    radius2 = float(feature[radiuscol]) * measureFactor
                else:
                    radius2 = radius
            except Exception:
                numbad += 1
                continue
            pts = []
            pt = feature.geometry().asPoint()
            pt_orig_x = pt.x()
            pt_orig_y = pt.y()
            # make sure the coordinates are in EPSG:4326
            if srcCRS != epsg4326:
                pt = geomTo4326.transform(pt.x(), pt.y())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle)
                sina = math.sin(a)
                x = 16 * sina * sina * sina
                y = 13 * math.cos(a) - 5 * math.cos(2 * a) - 2 * math.cos(
                    3 * a) - math.cos(4 * a)
                dist = math.sqrt(x * x + y * y) * radius2 / 17.0
                a2 = math.degrees(math.atan2(y, x)) + sangle
                g = geod.Direct(pt.y(), pt.x(), a2, dist,
                                Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += step

            # If the Output crs is not 4326 transform the points to the proper crs
            if srcCRS != epsg4326:
                for x, ptout in enumerate(pts):
                    pts[x] = toSinkCrs.transform(ptout)

            f = QgsFeature()
            if shapetype == 0:
                f.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            else:
                f.setGeometry(QgsGeometry.fromPolylineXY(pts))
            attr = feature.attributes()
            if export_geom:
                attr.append(pt_orig_x)
                attr.append(pt_orig_y)
            f.setAttributes(attr)
            sink.addFeature(f)

            if index % 100 == 0:
                feedback.setProgress(int(index * total))

        if numbad > 0:
            feedback.pushInfo(
                tr("{} out of {} features had invalid parameters and were ignored."
                   .format(numbad, featureCount)))

        return {self.PrmOutputLayer: dest_id}
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        grib_layerfile = self.parameterAsFile(parameters, self.GRIB, context)
        grib_layer = self.parameterAsLayer(parameters, self.GRIB, context)
        wind_ds = self.parameterAsInt(parameters, self.WIND_DATASET_INDEX,
                                      context)
        polar_filename = self.polar_names[self.parameterAsEnum(
            parameters, self.POLAR, context)]
        polar = Polar(
            os.path.join(self.polars_dir, self.polars[polar_filename]))
        start = self.parameterAsDateTime(parameters, self.START_TIME, context)
        start_point = self.parameterAsPoint(parameters,
                                            self.START_POINT,
                                            context,
                                            crs=grib_layer.crs())
        end_point = self.parameterAsPoint(parameters,
                                          self.END_POINT,
                                          context,
                                          crs=grib_layer.crs())

        print("grib_layerfile", grib_layerfile)
        print("grib_layer", grib_layer)
        print("wind_ds", wind_ds)
        print("polar", polar)

        track = ((start_point.y(), start_point.x()), (end_point.y(),
                                                      end_point.x()))
        geo_context = QgsRectangle(start_point.x(), start_point.y(),
                                   end_point.x(), end_point.y())
        track_dist = QgsPointXY(start_point.x(), start_point.y()).sqrDist(
            end_point.x(), end_point.y())
        geo_context.grow(
            (track_dist /
             2) if track_dist < 1 else 0.5)  #limit grow to 0.5 degree
        checkValidity = in_sea_checker(geo_context)
        grib_reader = grib_sampler(grib_layer, wind_ds)

        #test
        #print ("TESTGRIB",grib_reader.getWindAt(datetime.strptime("02/02/21 18:00", "%d/%m/%y %H:%M"),39.31064,5.06086))

        print("track", track)

        route_process = Routing(
            LinearBestIsoRouter,
            polar,
            track,
            grib_reader,
            start.toPyDateTime(),
            lineValidity=checkValidity.path_in_sea_xy,
        )
        step = 1
        execution = "ok"
        while not route_process.end:
            if feedback.isCanceled():
                break
            try:
                res = route_process.step()
                step += 1
                feedback.pushInfo("step %d: %s" % (step, str(res.time)))
                if feedback.isCanceled():
                    return {"result": "terminated by user"}
                if res.time > grib_reader.end_time:
                    execution = "terminated: out of grib temporal scope"
            except Exception as e:
                feedback.pushInfo("Error: %s" % e.message)

        if res.path:
            waypfields = QgsFields()
            waypfields.append(QgsField("wayp_id", QVariant.Int))
            waypfields.append(QgsField("timestamp", QVariant.String, len=25))
            waypfields.append(QgsField("time", QVariant.DateTime))
            waypfields.append(QgsField("twd", QVariant.Double, len=10, prec=3))
            waypfields.append(QgsField("tws", QVariant.Double, len=10, prec=3))
            waypfields.append(
                QgsField("knots", QVariant.Double, len=10, prec=3))
            waypfields.append(
                QgsField("heading", QVariant.Double, len=10, prec=3))
            routefields = QgsFields()
            routefields.append(
                QgsField("start_tracking", QVariant.String, len=25))
            routefields.append(
                QgsField("end_tracking", QVariant.String, len=25))

            (sink_waypoints, dest_waypoints_id) = self.parameterAsSink(
                parameters, self.OUTPUT_WAYPOINTS, context, waypfields,
                QgsWkbTypes.Point, QgsCoordinateReferenceSystem(4326))
            (sink_route, dest_route_id) = self.parameterAsSink(
                parameters, self.OUTPUT_ROUTE, context, routefields,
                QgsWkbTypes.LineString, QgsCoordinateReferenceSystem(4326))

            # Compute the number of steps to display within the progress bar and
            # get features from source
            tr = []
            for wp in res.path:
                if len(wp) == 3:
                    tr.append((wp[0], wp[1], str(wp[2]), 0, 0, 0, 0))
                else:
                    tr.append(
                        (wp[0], wp[1], str(wp[4]), wp[5], wp[6], wp[7], wp[8]))
            if execution == "ok":
                tr.append((*track[-1], dateutil.parser.parse(tr[-1][2]) +
                           timedelta(hours=1), 0, 0, 0, 0))

            print(tr)
            route_polyline = []

            for order, wayp in enumerate(tr):
                # Stop the algorithm if cancel button has been clicked
                print(wayp[1], wayp[0], wayp[2])
                if feedback.isCanceled():
                    break
                print(wayp[2], type(wayp[2]))
                new_feat = QgsFeature(waypfields)
                new_feat.setAttribute('wayp_id', order)
                new_feat.setAttribute(
                    'timestamp',
                    str(wayp[2])[:25])  #.isoformat(timespec='minutes')
                new_feat.setAttribute('time', str(wayp[2]))
                new_feat.setAttribute('twd', math.degrees(wayp[3]))
                new_feat.setAttribute('tws', wayp[4])
                new_feat.setAttribute('knots', wayp[5])
                new_feat.setAttribute('heading', wayp[6])
                waypoint = QgsPointXY(wayp[1], wayp[0])
                route_polyline.append(waypoint)
                new_geom = QgsGeometry.fromPointXY(waypoint)
                new_feat.setGeometry(new_geom)
                sink_waypoints.addFeature(new_feat, QgsFeatureSink.FastInsert)

            new_route_feat = QgsFeature(routefields)
            new_route_feat.setAttribute('start_tracking', tr[0][2][:25])
            new_route_feat.setAttribute('end_tracking', tr[-2][2][:25])
            new_route_feat.setGeometry(
                QgsGeometry.fromPolylineXY(route_polyline))
            sink_route.addFeature(new_route_feat, QgsFeatureSink.FastInsert)

            return {
                self.OUTPUT_WAYPOINTS: dest_waypoints_id,
                self.OUTPUT_ROUTE: dest_route_id,
                "result": execution
            }
        else:
            return {"result", "no_path"}
Example #41
0
 def calcEntryLinestring(self):
     return QgsGeometry.fromPolylineXY(
         [self.point_geom, self.network_vertex.point()])
 def path_in_sea_xy(self, y1, x1, y2, x2):
     return self.in_sea(
         QgsGeometry.fromPolylineXY(
             [QgsPointXY(x1, y1), QgsPointXY(x2, y2)]))
Example #43
0
    def on_btnSave_released(self):
        layer = QgsVectorLayer(
            "MultiLineString?crs={}".format(
                QgsProject.instance().crs().authid()),
            "Lines",
            "memory",
        )

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

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

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

        layer.dataProvider().addFeatures(feats)

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

        # Generate index lines

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        for line in lin.asGeometryCollection():
            poly = line.densifyByCount(self.rowCount.value() * 2).asPolyline()
            for part in poly:
                feature = QgsFeature(fid)
                feature.setAttributes([str(fid)])
                feature.setGeometry(QgsPoint(part))
                feats.append(feature)
                fid += 1
        # ptLayer.dataProvider().addFeatures(sorted(feats, key=lambda f: f['num']))
        ptLayer.dataProvider().addFeatures(feats)
        ptLayer.commitChanges()
Example #44
0
def algorithm_wrapper(start_point,
                      end_point,
                      node_layer,
                      input_data_path,
                      output_file,
                      algorithm,
                      node_id_attribute='nodeID'):
    """
        `start_point` : the starting point as QgsPointXY
        `end_point` : the end point as QgsPointXY
        `node_layer` : a point vector layer that contains the node. Naturally it's located in input_data_path
        `input_data_path` : a path to directory with nodes and edges layer.
        `output_file` : a path to the output shape file.
    """
    # Get the nearest node from start and end
    start_node = get_nearest_feature(node_layer, start_point)
    print('start nodeID:', start_node['nodeID'])
    end_node = get_nearest_feature(node_layer, end_point)
    print('end nodeID:', end_node['nodeID'])

    # generate path with the `algorithm`
    start_node_id = (node_id_attribute, start_node['nodeID'])
    end_node_id = (node_id_attribute, end_node['nodeID'])
    path = algorithm(start_node_id, end_node_id, input_data_path, output_file)

    # Sort the path
    coordinates = [start_point]
    G = nx.Graph(nx.read_shp(input_data_path, strict=False,
                             geom_attrs=True))  # Read and convert to Graph
    for i in range(len(path) - 1):
        node1 = path[i]
        node2 = path[i + 1]
        edge_key = [node1, node2]
        # print('edge key: ', edge_key)
        points = get_points(G, edge_key)
        # print(points)
        if i == 0:
            for p in points:
                coordinates.append(QgsPointXY(p[0], p[1]))
        else:
            start_point_path = QgsPointXY(points[0][0], points[0][1])
            if start_point_path == coordinates[-1]:
                # Same end point, add a usual
                for p in points[1:]:
                    coordinates.append(QgsPointXY(p[0], p[1]))
            else:
                # Different endpoint, reverse
                for p in points[::-1][1:]:
                    coordinates.append(QgsPointXY(p[0], p[1]))
    # Append end point
    coordinates.append(end_point)

    # Spatial reference
    spatial_reference = get_spatial_reference(input_data_path)

    # Write result to a shapefile (TODO: put it in a function)
    # Create geometry for the whole line
    line_geometry = QgsGeometry.fromPolylineXY(coordinates)
    # Convert to Wkt for ogr
    line_wkt = line_geometry.asWkt()
    # set up the shapefile driver
    driver = ogr.GetDriverByName("ESRI Shapefile")
    # create the data source
    data_source = driver.CreateDataSource(output_file)
    # create the layer
    layer = data_source.CreateLayer("A Star Shortest Path", spatial_reference,
                                    ogr.wkbLineString)
    feature = ogr.Feature(layer.GetLayerDefn())
    geom = ogr.CreateGeometryFromWkt(line_wkt)
    # Set the feature geometry using the geom
    feature.SetGeometry(geom)
    # Create the feature in the layer (shapefile)
    layer.CreateFeature(feature)
    # Dereference the feature
    feature = None
    data_source = None

    print(output_file)
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context, network.sourceCrs())
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context,
                                         network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters,
                                                    self.DIRECTION_FIELD,
                                                    context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD,
                                              context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD,
                                               context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH,
                                           context)
        defaultDirection = self.parameterAsEnum(parameters,
                                                self.DEFAULT_DIRECTION,
                                                context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD,
                                                context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED,
                                              context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = QgsFields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

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

        directionField = -1
        if directionField:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network, directionField,
                                          forwardValue, backwardValue,
                                          bothValue, defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance)
        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathPointToPoint',
                                       'Building graph…'))
        snappedPoints = director.makeGraph(builder, [startPoint, endPoint],
                                           feedback)

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathPointToPoint',
                                       'Calculating shortest path…'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])
        idxEnd = graph.findVertex(snappedPoints[1])

        tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        if tree[idxEnd] == -1:
            raise QgsProcessingException(
                self.tr('There is no route from start point to end point.'))

        route = [graph.vertex(idxEnd).point()]
        cost = costs[idxEnd]
        current = idxEnd
        while current != idxStart:
            current = graph.edge(tree[current]).fromVertex()
            route.append(graph.vertex(current).point())

        route.reverse()

        feedback.pushInfo(
            QCoreApplication.translate('ShortestPathPointToPoint',
                                       'Writing results…'))
        geom = QgsGeometry.fromPolylineXY(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        results = {}
        results[self.TRAVEL_COST] = cost / multiplier
        results[self.OUTPUT] = dest_id
        return results
 def setBBOXInQuery(self):
     sourceCrs = None
     if self.layerExtentOrBBOX:
         xMax = self.mts_layer.extent().xMaximum()
         xMin = self.mts_layer.extent().xMinimum()
         yMin = self.mts_layer.extent().yMinimum()
         yMax = self.mts_layer.extent().yMaximum()
         pointt1 = QgsGeometry.fromPointXY(QgsPointXY(xMax, yMin))
         pointt2 = QgsGeometry.fromPointXY(QgsPointXY(xMin, yMin))
         pointt3 = QgsGeometry.fromPointXY(QgsPointXY(xMin, yMax))
         pointt4 = QgsGeometry.fromPointXY(QgsPointXY(xMax, yMax))
         sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.crs())
     else:
         sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.crs())
         destCrs = self.crsdialog.crs()
         if self.polygon:
             polygon = self.poly_tool.rb.asGeometry()
             tr = QgsCoordinateTransform(sourceCrs, destCrs,
                                         QgsProject.instance())
             polygon.transform(tr)
         elif self.circle:
             pointt1 = QgsGeometry.fromWkt(self.circ_tool.point1.asWkt())
             pointt2 = QgsGeometry.fromWkt(self.circ_tool.point2.asWkt())
             pointt3 = QgsGeometry.fromWkt(self.circ_tool.point3.asWkt())
             pointt4 = QgsGeometry.fromWkt(self.circ_tool.point4.asWkt())
         else:
             pointt1 = QgsGeometry.fromWkt(self.rect_tool.point1.asWkt())
             pointt2 = QgsGeometry.fromWkt(self.rect_tool.point2.asWkt())
             pointt3 = QgsGeometry.fromWkt(self.rect_tool.point3.asWkt())
             pointt4 = QgsGeometry.fromWkt(self.rect_tool.point4.asWkt())
             if sourceCrs != None:
                 tr = QgsCoordinateTransform(sourceCrs, destCrs,
                                             QgsProject.instance())
                 pointt1.transform(tr)
                 pointt2.transform(tr)
                 pointt3.transform(tr)
                 pointt4.transform(tr)
             polygon = QgsGeometry.fromPolylineXY([
                 pointt1.asPoint(),
                 pointt2.asPoint(),
                 pointt3.asPoint(),
                 pointt4.asPoint()
             ])
     center = polygon.centroid()
     #distance = QgsDistanceArea()
     #distance.setSourceCrs(destCrs)
     #distance.setEllipsoidalMode(True)
     #distance.setEllipsoid('WGS84')
     curquery = self.inp_sparql.toPlainText()
     if self.rectangle or self.circle:
         widthm = 100  #distance.measureLine(pointt1, pointt2)
         self.curbbox = []
         self.curbbox.append(pointt1)
         self.curbbox.append(pointt2)
         self.curbbox.append(pointt3)
         self.curbbox.append(pointt4)
         self.close()
         if "bboxquery" in self.triplestoreconf[
                 self.endpointIndex] and self.triplestoreconf[
                     self.
                     endpointIndex]["bboxquery"]["type"] == "geosparql":
             curquery = curquery[
                 0:curquery.rfind('}')] + self.triplestoreconf[
                     self.endpointIndex]["bboxquery"]["query"].replace(
                         "%%x1%%", str(pointt1.asPoint().x())).replace(
                             "%%x2%%", str(pointt3.asPoint().x())).replace(
                                 "%%y1%%",
                                 str(pointt1.asPoint().y())).replace(
                                     "%%y2%%", str(pointt3.asPoint().y())
                                 ) + "}\n" + curquery[curquery.rfind('}') +
                                                      1:]
         elif "bboxquery" in self.triplestoreconf[
                 self.endpointIndex] and self.triplestoreconf[
                     self.endpointIndex]["bboxquery"]["type"] == "minmax":
             curquery = curquery[
                 0:curquery.rfind('}')] + self.triplestoreconf[
                     self.endpointIndex]["bboxquery"]["query"].replace(
                         "%%minPoint%%", pointt2.asWkt()).replace(
                             "%%maxPoint%%", pointt4.asWkt()
                         ) + curquery[curquery.rfind('}') + 1:]
         elif "bboxquery" in self.triplestoreconf[
                 self.endpointIndex] and self.triplestoreconf[
                     self.
                     endpointIndex]["bboxquery"]["type"] == "pointdistance":
             curquery = curquery[
                 0:curquery.rfind('}')] + self.triplestoreconf[
                     self.endpointIndex]["bboxquery"]["query"].replace(
                         "%%lat%%", str(center.asPoint().y())).replace(
                             "%%lon%%", str(center.asPoint().x())).replace(
                                 "%%distance%%", str(widthm / 1000)
                             ) + curquery[curquery.rfind('}') + 1:]
     elif polygon:
         widthm = 100
         if "bboxquery" in self.triplestoreconf[
                 self.endpointIndex] and self.triplestoreconf[
                     self.
                     endpointIndex]["bboxquery"]["type"] == "geosparql":
             curquery = curquery[0:curquery.rfind(
                 '}')] + "FILTER(geof:sfIntersects(?geo,\"" + polygon.asWkt(
                 ) + "\"^^geo:wktLiteral))"
         elif "bboxquery" in self.triplestoreconf[
                 self.endpointIndex] and self.triplestoreconf[
                     self.endpointIndex]["bboxquery"]["type"] == "minmax":
             curquery = curquery[
                 0:curquery.rfind('}')] + self.triplestoreconf[
                     self.endpointIndex]["bboxquery"]["query"].replace(
                         "%%minPoint%%",
                         "POINT(" + str(polygon.boundingBox().yMinimum()) +
                         " " + str(polygon.boundingBox().xMinimum()) +
                         ")").replace(
                             "%%maxPoint%%", "POINT(" +
                             str(polygon.boundingBox().yMaximum()) + " " +
                             str(polygon.boundingBox().xMaximum()) +
                             ")") + curquery[curquery.rfind('}') + 1:]
         elif "bboxquery" in self.triplestoreconf[
                 self.endpointIndex] and self.triplestoreconf[
                     self.
                     endpointIndex]["bboxquery"]["type"] == "pointdistance":
             curquery = curquery[
                 0:curquery.rfind('}')] + self.triplestoreconf[
                     self.endpointIndex]["bboxquery"]["query"].replace(
                         "%%lat%%",
                         str(polygon.boundingBox().center().asPoint().y(
                         ))).replace(
                             "%%lon%%",
                             str(polygon.boundingBox().center().asPoint().x(
                             ))).replace("%%distance%%", str(
                                 widthm /
                                 1000)) + curquery[curquery.rfind('}') + 1:]
     self.inp_sparql.setPlainText(curquery)
     self.close()
Example #47
0
 def getRecordGeometry(self, record):
     polylineXY = polylineXYSegmentXY(self.polyline, record.partFrom,
                                      record.partTo)
     geo = QgsGeometry.fromPolylineXY(polylineXY)
     return geo
Example #48
0
def run(bar, layer1_path, layer2_path, obstacles_path, research_ray):

    output = {}
    #layer1 receiver
    layer1 = QgsVectorLayer(layer1_path, "layer1", "ogr")
    #layer 2 source
    layer2 = QgsVectorLayer(layer2_path, "layer2", "ogr")
    layer2_feat_all_dict = {}
    layer2_feat_all = layer2.dataProvider().getFeatures()
    layer2_spIndex = QgsSpatialIndex()
    for layer2_feat in layer2_feat_all:
        layer2_spIndex.insertFeature(layer2_feat)
        layer2_feat_all_dict[layer2_feat.id()] = layer2_feat

    if obstacles_path is not None:
        obstacles_layer = QgsVectorLayer(obstacles_path, "obstacles", "ogr")
        obstacles_feat_all = obstacles_layer.dataProvider().getFeatures()
        obstacles_spIndex = QgsSpatialIndex()
        obstacles_feat_all_dict = {}
        for obstacles_feat in obstacles_feat_all:
            obstacles_spIndex.insertFeature(obstacles_feat)
            obstacles_feat_all_dict[obstacles_feat.id()] = obstacles_feat

    layer1_feat_all = layer1.dataProvider().getFeatures()
    layer1_feat_total = layer1.dataProvider().featureCount()
    layer1_feat_number = 0

    for layer1_feat in layer1_feat_all:

        layer1_feat_number = layer1_feat_number + 1
        barValue = layer1_feat_number / float(layer1_feat_total) * 100
        bar.setValue(barValue)

        # researches the layer2 points in a rectangle created by the research_ray
        # creates the search rectangle
        rect = QgsRectangle()
        rect.setXMinimum(layer1_feat.geometry().asPoint().x() - research_ray)
        rect.setXMaximum(layer1_feat.geometry().asPoint().x() + research_ray)
        rect.setYMinimum(layer1_feat.geometry().asPoint().y() - research_ray)
        rect.setYMaximum(layer1_feat.geometry().asPoint().y() + research_ray)

        layer2_request = layer2_spIndex.intersects(rect)

        layer2_points = []

        for layer2_id in layer2_request:

            layer2_feat = layer2_feat_all_dict[layer2_id]

            ray_to_test_length = compute_distance(
                layer1_feat.geometry().asPoint(),
                layer2_feat.geometry().asPoint())

            if ray_to_test_length <= research_ray:

                ray_to_test = QgsGeometry.fromPolylineXY([
                    layer1_feat.geometry().asPoint(),
                    layer2_feat.geometry().asPoint()
                ])

                intersect = 0

                if obstacles_path is not None:
                    obstacles_request = obstacles_spIndex.intersects(
                        ray_to_test.boundingBox())
                    for obstacles_id in obstacles_request:
                        if obstacles_feat_all_dict[obstacles_id].geometry(
                        ).crosses(ray_to_test) == 1:
                            intersect = 1
                            break

                if intersect == 0:

                    layer2_points.append(layer2_feat.id())

                    output[layer1_feat.id()] = layer2_points

    return output
Example #49
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context)
        defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = QgsFields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

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

        directionField = -1
        if directionField:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network,
                                          directionField,
                                          forwardValue,
                                          backwardValue,
                                          bothValue,
                                          defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField,
                                               defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(),
                                  True,
                                  tolerance)
        feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Building graph…'))
        snappedPoints = director.makeGraph(builder, [startPoint, endPoint], feedback)

        feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Calculating shortest path…'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])
        idxEnd = graph.findVertex(snappedPoints[1])

        tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        if tree[idxEnd] == -1:
            raise QgsProcessingException(
                self.tr('There is no route from start point to end point.'))

        route = [graph.vertex(idxEnd).point()]
        cost = costs[idxEnd]
        current = idxEnd
        while current != idxStart:
            current = graph.edge(tree[current]).fromVertex()
            route.append(graph.vertex(current).point())

        route.reverse()

        feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Writing results…'))
        geom = QgsGeometry.fromPolylineXY(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        results = {}
        results[self.TRAVEL_COST] = cost / multiplier
        results[self.OUTPUT] = dest_id
        return results
Example #50
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))

        use_ring_count = False
        fields_or_rings = self.parameterAsString(parameters,
                                                 self.FIELDS_OR_RINGS, context)
        if (self.is_number(fields_or_rings)):
            ring_num = int(fields_or_rings)
            use_ring_count = True
        else:
            input_fields = fields_or_rings.strip().split(',')
            ring_num = len(input_fields)
            for idx in range(ring_num):
                input_fields[idx] = input_fields[idx].strip()
        if (ring_num == 0):
            raise QgsProcessingException(
                'The count of Rings must be greater than zero')

        ring_value_field = self.parameterAsString(parameters,
                                                  self.RING_VALUE_FIELD,
                                                  context)

        self.GAPS = self.parameterAsInt(parameters, self.RING_GAP, context)
        if self.GAPS < 0 or self.GAPS > 10:
            raise QgsProcessingException(
                'The Gap value must be between 0 and 10.')

        # calculate layer's extent & feature count
        feature_count = source.featureCount()
        extent = self.calculate_layer_extent(source)

        # create spatial index & convert to points
        (spatial_index, centroid_features) = self.create_spatial_index(source)

        center_point = extent.center()
        # QgsPoint

        minx = extent.xMinimum()
        miny = extent.yMinimum()
        maxx = extent.xMaximum()
        maxy = extent.yMaximum()

        radius = (((maxx - minx)**2 + (maxy - miny)**2)**0.5) / 2.0
        radius_interval = radius / ring_num

        ring_fields = source.fields()
        ring_fields.append(QgsField("ring_num", QVariant.Int))
        ring_fields.append(QgsField(ring_value_field, QVariant.Double))

        idx_fields = []
        for idx in range(ring_num):
            if (use_ring_count):
                idx_fields.append(-1)
            else:
                idx_fields.append(ring_fields.lookupField(input_fields[idx]))

        (sink_ring,
         ring_id) = self.parameterAsSink(parameters, self.OUTPUT_RING, context,
                                         ring_fields, QgsWkbTypes.Polygon,
                                         source.sourceCrs())
        (sink_anchor,
         anchor_id) = self.parameterAsSink(parameters, self.OUTPUT_ANCHOR,
                                           context, source.fields(),
                                           QgsWkbTypes.LineString,
                                           source.sourceCrs())

        if sink_ring is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT_RING))
        if sink_anchor is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT_ANCHOR))

        step_angle = 360.0 / feature_count
        half_step = step_angle / 2.0
        total = 100.0 / feature_count if feature_count else 0

        for idx_side in range(feature_count):
            if feedback.isCanceled():
                break

            from_deg = half_step + (idx_side * step_angle)
            to_deg = half_step + ((idx_side + 1) * step_angle)
            default_radius = radius

            for idx_radius in range(ring_num):
                cell = self.create_ring_cell(center_point, from_deg, to_deg,
                                             default_radius,
                                             default_radius + radius_interval)
                cell_centroid_point = cell.centroid().asPoint()

                # find nearest feature & create anchor line
                if (idx_radius == 0):
                    fids = spatial_index.nearestNeighbor(
                        cell_centroid_point, 1)
                    for fid in fids:
                        nearest_feature = centroid_features[fid]
                        nearest_point = nearest_feature.geometry().asPoint()

                        anchor_feature = QgsFeature()
                        anchor_feature.setGeometry(
                            QgsGeometry.fromPolylineXY(
                                [nearest_point, cell_centroid_point]))
                        anchor_feature.setAttributes(
                            nearest_feature.attributes())

                        # Add a new feature in the sink
                        sink_anchor.addFeature(anchor_feature,
                                               QgsFeatureSink.FastInsert)

                        spatial_index.deleteFeature(nearest_feature)

                # create and write ring feature
                ring_feature = QgsFeature(ring_fields)
                ring_feature.setGeometry(cell)

                ring_attributes = nearest_feature.attributes()
                ring_attributes.append(idx_radius + 1)  # ring_num
                if (idx_fields[idx_radius] == -1):
                    ring_attributes.append(0)  # default value = 0
                else:
                    ring_attributes.append(
                        ring_attributes[idx_fields[idx_radius]])  # ring_val
                ring_feature.setAttributes(ring_attributes)

                # Add a new feature in the sink
                sink_ring.addFeature(ring_feature, QgsFeatureSink.FastInsert)

                default_radius += radius_interval

            # Update the progress bar
            feedback.setProgress(int(idx_side * total))

        # cleanup
        del centroid_features

        return {self.OUTPUT_RING: ring_id, self.OUTPUT_ANCHOR: anchor_id}
Example #51
0
 def createDigiFeature(pnts):
     line = QgsGeometry.fromPolylineXY(pnts)
     qgFeat = QgsFeature()
     qgFeat.setGeometry(line)
     return qgFeat
Example #52
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        reseau = self.parameterAsVectorLayer(parameters, self.RESEAU, context)
        fenetre = self.parameterAsExtent(parameters, self.FENETRE, context)
        cout_i = QgsExpression(
            self.parameterAsExpression(parameters, self.COUT_I, context))
        cout_j = QgsExpression(
            self.parameterAsExpression(parameters, self.COUT_J, context))
        sens = QgsExpression(
            self.parameterAsExpression(parameters, self.SENS, context))
        diffusion = QgsExpression(
            self.parameterAsExpression(parameters, self.DIFFUSION, context))
        traversabilite = QgsExpression(
            self.parameterAsExpression(parameters, self.TRAVERSABILITE,
                                       context))
        nb_pixels_x = self.parameterAsInt(parameters, self.NB_PIXELS_X,
                                          context)
        nb_pixels_y = self.parameterAsInt(parameters, self.NB_PIXELS_Y,
                                          context)
        taille_pixel_x = self.parameterAsDouble(parameters,
                                                self.TAILLE_PIXEL_X, context)
        taille_pixel_y = self.parameterAsDouble(parameters,
                                                self.TAILLE_PIXEL_Y, context)
        decimales = self.parameterAsInt(parameters, self.DECIMALES, context)
        rayon = self.parameterAsDouble(parameters, self.RAYON, context)
        vitesse_diffusion = QgsExpression(
            self.parameterAsExpression(parameters, self.VITESSE_DIFFUSION,
                                       context))
        intraversable = self.parameterAsBool(parameters, self.INTRAVERSABLE,
                                             context)
        valeurs_individuelles = QgsExpression(
            self.parameterAsExpression(parameters, self.IND_VALUES, context))

        resultat = self.parameterAsOutputLayer(
            parameters, self.RESULTAT, context
        )  # Compute the number of steps to display within the progress bar and

        poles = {}
        formule_cout_i = self.createExpressionContext(parameters, context)
        cout_i.prepare(formule_cout_i)
        formule_cout_j = self.createExpressionContext(parameters, context)
        cout_j.prepare(formule_cout_j)
        formule_sens = self.createExpressionContext(parameters, context)
        sens.prepare(formule_sens)
        formule_diffusion = self.createExpressionContext(parameters, context)
        diffusion.prepare(formule_diffusion)
        formule_traversabilite = self.createExpressionContext(
            parameters, context)
        traversabilite.prepare(formule_traversabilite)
        formule_vitesse_diffusion = self.createExpressionContext(
            parameters, context)
        vitesse_diffusion.prepare(formule_vitesse_diffusion)
        formule_valeurs_individuelles = self.createExpressionContext(
            parameters, context)
        valeurs_individuelles.prepare(formule_valeurs_individuelles)

        crsSrc = QgsCoordinateReferenceSystem('EPSG:' +
                                              str(reseau.crs().postgisSrid()))
        dist_unit = QgsUnitTypes.fromUnitToUnitFactor(
            crsSrc.mapUnits(), QgsUnitTypes.DistanceMeters)
        rayon = rayon / dist_unit

        grille = numpy.array([[-9999.0] * nb_pixels_y] * nb_pixels_x)
        grille_distance = numpy.array([[1e38] * nb_pixels_y] * nb_pixels_x)
        grille_ind = numpy.array([['0'] * nb_pixels_y] * nb_pixels_x,
                                 dtype='<U25')
        rep = os.path.dirname(resultat)
        a = fenetre.asWktCoordinates().split(',')
        fenetre2 = fenetre  #QgsRectangle(float(a[0]),float(a[2]),float(a[1]),float(a[3]))
        p1 = a[0].split()
        p2 = a[1].split()
        ll = (float(p1[0]), float(p1[1]))
        hauteur = float(p2[1]) - float(p1[1])
        largeur = float(p2[0]) - float(p1[0])
        if not (taille_pixel_x <= 0):
            nb_pixels_x = int(largeur / taille_pixel_x)
        else:
            taille_pixel_x = float(largeur / nb_pixels_x)
        if not (taille_pixel_y <= 0):
            nb_pixels_y = int(hauteur / taille_pixel_y)
        else:
            taille_pixel_y = float(hauteur / nb_pixels_y)
        layer = reseau
        if layer.type() == QgsMapLayer.VectorLayer:
            if not layer == None:
                if layer.geometryType() == 1:
                    simple = QgsSimplifyMethod()
                    simple.setMethodType(QgsSimplifyMethod.PreserveTopology)
                    simple.setTolerance(
                        min(taille_pixel_x, taille_pixel_y) / 2)
                    texte = diffusion.dump(
                    ) + ' in (\'1\',\'2\',\'3\') and (' + cout_j.dump(
                    ) + ' IS NOT NULL and ' + sens.dump(
                    ) + ' in (\'1\',\'3\')) '

                    #request=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(texte).setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect)
                    request = (QgsFeatureRequest().setFilterRect(fenetre2)
                               ).setFilterExpression(texte)
                    #req_intra=(QgsFeatureRequest().setFilterRect(fenetre2)).setFilterExpression(traversabilite.dump()+' in (\'1\',\'2\',\'3\')').setSimplifyMethod(simple).setFlags(QgsFeatureRequest.ExactIntersect)
                    req_intra = (
                        QgsFeatureRequest().setFilterRect(fenetre2)
                    ).setFilterExpression(traversabilite.dump() +
                                          ' in (\'1\',\'2\',\'3\')')
                    features = [f for f in layer.getFeatures(request)]

                    if intraversable:
                        features_intra = [
                            f for f in layer.getFeatures(req_intra)
                        ]
                    else:
                        features_intra = []
                    for k, i in enumerate(features):
                        formule_sens.setFeature(i)
                        formule_cout_i.setFeature(i)
                        formule_cout_j.setFeature(i)
                        formule_vitesse_diffusion.setFeature(i)
                        formule_diffusion.setFeature(i)
                        formule_traversabilite.setFeature(i)
                        formule_valeurs_individuelles.setFeature(i)
                        var_diffusion = diffusion.evaluate(formule_diffusion)
                        var_sens = sens.evaluate(formule_sens)
                        var_traversabilite = traversabilite.evaluate(
                            formule_traversabilite)
                        ti = cout_i.evaluate(formule_cout_i)
                        tj = cout_j.evaluate(formule_cout_j)
                        var_ind = valeurs_individuelles.evaluate(
                            formule_valeurs_individuelles)

                        var_vitesse_diffusion = vitesse_diffusion.evaluate(
                            formule_vitesse_diffusion)
                        speed = 60 / (1000 * var_vitesse_diffusion)

                        if var_sens in ['1', '2', '3']:

                            geom = i.geometry()
                            zone = geom.buffer(rayon, 12).boundingBox()
                            deltax = int(
                                (zone.xMinimum() - ll[0]) / taille_pixel_x)
                            deltay = int(
                                (zone.yMinimum() - ll[1]) / taille_pixel_y)
                            dx = int(zone.width() / taille_pixel_x)
                            dy = int(zone.height() / taille_pixel_y)
                            l1 = geom.length()
                            if geom.wkbType() == QgsWkbTypes.MultiLineString:
                                geom_l = geom.asMultiPolyline()
                            else:
                                geom_l = geom.asPolyline()

                            for p in range(dx):
                                d2x = deltax + p
                                for q in range(dy):
                                    d2y = deltay + q
                                    if 0 <= d2x < nb_pixels_x and 0 <= d2y < nb_pixels_y:
                                        pt1 = QgsGeometry.fromPointXY(
                                            QgsPointXY(
                                                ll[0] +
                                                (d2x + 0.5) * taille_pixel_x,
                                                ll[1] +
                                                (d2y + 0.5) * taille_pixel_y))
                                        res = geom.closestSegmentWithContext(
                                            pt1.asPoint())
                                        d = round(res[0], decimales)
                                        if d <= grille_distance[
                                                d2x,
                                                d2y] and d < rayon * rayon:
                                            if d > 0 and l1 > 0:
                                                pt2 = res[1]
                                                #feedback.setProgressText(geom.asWkt())
                                                if geom.wkbType(
                                                ) == QgsWkbTypes.MultiLineString:
                                                    num_poly = -1
                                                    npts = 0
                                                    for k, id_poly in enumerate(
                                                            geom_l):
                                                        if res[2] < npts + len(
                                                                id_poly):
                                                            infos_poly = (
                                                                k, res[2])
                                                        else:
                                                            npts += len(
                                                                id_poly)
                                                    #feedback.setProgressText(str(infos_poly[0])+"-"+str(infos_poly[1])+"-"+str(npts))
                                                    geoma = geom_l[infos_poly[
                                                        0]][:(infos_poly[1] -
                                                              npts)] + [pt2]
                                                else:
                                                    geoma = geom_l[:res[2]] + [
                                                        pt2
                                                    ]
                                                #geoma=QgsGeometry(geom)
                                                #geoma.insertVertex(pt2[0],pt2[1],res[2])
                                                l2 = QgsGeometry.fromPolylineXY(
                                                    geoma).length()
                                                if res[2] == 0:
                                                    pt3 = geom.vertexAt(res[2])
                                                    pt4 = geom.vertexAt(
                                                        res[2] + 1)
                                                else:
                                                    try:
                                                        pt3 = geom.vertexAt(
                                                            res[2] - 1)
                                                        pt4 = geom.vertexAt(
                                                            res[2])
                                                    except:
                                                        print(res, geom_l)
                                                        pt3 = geom_l[res[2] -
                                                                     1]
                                                        pt4 = geom_l[res[2]]
                                                p1 = pt1.asPoint()
                                                test_sens = (pt4.x() - pt3.x(
                                                )) * (p1.y() - pt2.y()) - (
                                                    p1.x() - pt2.x()) * (
                                                        pt4.y() - pt3.y())
                                                if var_sens in [
                                                        '1', '3'
                                                ] and not tj == None:
                                                    if (var_diffusion
                                                            in ['1', '3']
                                                            and test_sens <= 0
                                                        ) or (var_diffusion
                                                              in ['2', '3'] and
                                                              test_sens >= 0):

                                                        if not tj == None:

                                                            if not ti == None:
                                                                t = tj * (
                                                                    l2 / l1
                                                                ) + ti * (
                                                                    1 -
                                                                    (l2 / l1)
                                                                ) + math.sqrt(
                                                                    d
                                                                ) * speed / dist_unit
                                                                l3 = QgsGeometry.fromPolylineXY(
                                                                    [
                                                                        pt1.
                                                                        asPoint(
                                                                        ),
                                                                        QgsPointXY(
                                                                            pt2
                                                                        )
                                                                    ])
                                                        result_test = False
                                                        if l3 != None:
                                                            if len(features_intra
                                                                   ) > 0:
                                                                for intra in features_intra:
                                                                    if intra.geometry(
                                                                    ).intersects(
                                                                            l3
                                                                    ):
                                                                        result_test = True
                                                                        break
                                                        if result_test == False:
                                                            if (
                                                                    t <
                                                                    grille[d2x,
                                                                           d2y]
                                                                    and d ==
                                                                    grille_distance[
                                                                        d2x,
                                                                        d2y]
                                                            ) or d < grille_distance[
                                                                    d2x, d2y]:
                                                                grille_distance[
                                                                    d2x,
                                                                    d2y] = d
                                                                grille[d2x,
                                                                       d2y] = t
                                                                if var_ind not in poles:
                                                                    poles[
                                                                        var_ind] = len(
                                                                            poles
                                                                        ) + 1
                                                                grille_ind[
                                                                    d2x,
                                                                    d2y] = poles[
                                                                        var_ind]
                    sortie = os.path.splitext(resultat)
                    fichier_grille = open(sortie[0] + sortie[1], 'w')
                    fichier_grille.write(
                        "NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n"
                        .format(nb_pixels_x, nb_pixels_y, ll[0], ll[1],
                                taille_pixel_x, taille_pixel_y))
                    fichier_grille2 = open(sortie[0] + "_dist" + sortie[1],
                                           'w')
                    fichier_grille2.write(
                        "NCOLS {0:d}\nNROWS {1:d}\nXLLCORNER {2}\nYLLCORNER {3}\nDX {4}\nDY {5}\nNODATA_VALUE -9999\n"
                        .format(nb_pixels_x, nb_pixels_y, ll[0], ll[1],
                                taille_pixel_x, taille_pixel_y))
                    g1 = numpy.rot90(grille, 1)
                    #g1=numpy.flipud(g1)
                    g2 = numpy.rot90(grille_ind, 1)
                    #g2=numpy.flipud(g2)
                    for i in g1:
                        fichier_grille.write(" ".join([str(ii)
                                                       for ii in i]) + "\n")
                    fichier_grille.close()
                    for i in g2:
                        fichier_grille2.write(" ".join([str(ii)
                                                        for ii in i]) + "\n")
                    fichier_grille2.close()

                    fichier_prj = open(sortie[0] + ".prj", 'w')
                    fichier2_prj = open(sortie[0] + "_dist.prj", 'w')
                    fichier2_dict = open(sortie[0] + "_dist.dic", 'w')
                    fichier_prj.write(layer.crs().toWkt())
                    fichier2_prj.write(layer.crs().toWkt())
                    fichier2_dict.write(
                        json.dumps(dict(map(reversed, poles.items()))))
                    fichier_prj.close()
                    fichier2_prj.close()
                    fichier2_dict.close()
                    nom_sortie = os.path.basename(sortie[0])
                    rlayer = QgsRasterLayer(resultat, nom_sortie)

        return {self.RESULTAT: resultat}
Example #53
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS, context)
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context)
        defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = startPoints.fields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        feat = QgsFeature()
        feat.setFields(fields)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.LineString, network.sourceCrs())

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network,
                                          directionField,
                                          forwardValue,
                                          backwardValue,
                                          bothValue,
                                          defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField,
                                               defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(),
                                  True,
                                  tolerance)

        feedback.pushInfo(self.tr('Loading start points...'))
        request = QgsFeatureRequest()
        request.setDestinationCrs(network.sourceCrs())
        features = startPoints.getFeatures(request)
        total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0

        points = [endPoint]
        source_attributes = {}
        i = 1
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            for p in f.geometry().vertices():
                points.append(QgsPointXY(p))
                source_attributes[i] = f.attributes()
                i += 1

            feedback.setProgress(int(current * total))

        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(self.tr('Calculating shortest paths...'))
        graph = builder.graph()

        idxEnd = graph.findVertex(snappedPoints[0])

        nPoints = len(snappedPoints)
        total = 100.0 / nPoints if nPoints else 1
        for i in range(1, nPoints):
            if feedback.isCanceled():
                break

            idxStart = graph.findVertex(snappedPoints[i])

            tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

            if tree[idxEnd] == -1:
                msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(points[i].toString(), endPoint.toString()))
                feedback.reportError(msg)
                # add feature with no geometry
                feat.clearGeometry()
                attrs = source_attributes[i]
                attrs.append(points[i].toString())
                feat.setAttributes(attrs)
                sink.addFeature(feat, QgsFeatureSink.FastInsert)
                continue

            route = [graph.vertex(idxEnd).point()]
            cost = costs[idxEnd]
            current = idxEnd
            while current != idxStart:
                current = graph.edge(tree[current]).fromVertex()
                route.append(graph.vertex(current).point())

            route.reverse()

            geom = QgsGeometry.fromPolylineXY(route)
            feat.setGeometry(geom)
            attrs = source_attributes[i]
            attrs.extend([points[i].toString(), endPoint.toString(), cost / multiplier])
            feat.setAttributes(attrs)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Example #54
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.PrmInputLayer, context)
        shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
        cuspscol = self.parameterAsString(parameters, self.PrmCuspsField, context)
        startanglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context)
        radiuscol = self.parameterAsString(parameters, self.PrmRadiusField, context)
        radius = self.parameterAsDouble(parameters, self.PrmRadius, context)
        startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle, context)
        cusps = self.parameterAsInt(parameters, self.PrmCusps, context)
        segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context)
        units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context)
        
        measureFactor = conversionToMeters(units)
        radius *= measureFactor

        srcCRS = source.sourceCrs()
        if shapetype == 0:
            (sink, dest_id) = self.parameterAsSink(parameters,
                self.PrmOutputLayer, context, source.fields(),
                QgsWkbTypes.Polygon, srcCRS)
        else:
            (sink, dest_id) = self.parameterAsSink(parameters,
                self.PrmOutputLayer, context, source.fields(),
                QgsWkbTypes.LineString, srcCRS)
                
        if srcCRS != epsg4326:
            geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance())
            toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance())
        
        featureCount = source.featureCount()
        total = 100.0 / featureCount if featureCount else 0
        
        step = 360.0 / segments
        numbad = 0
        iterator = source.getFeatures()
        for index, feature in enumerate(iterator):
            if feedback.isCanceled():
                break
            try:
                if startanglecol:
                    sangle = float(feature[startanglecol])
                else:
                    sangle = startAngle
                if cuspscol:
                    cusps2 = int(feature[cuspscol])
                else:
                    cusps2 = cusps
                if radiuscol:
                    radius2 = float(feature[radiuscol]) * measureFactor
                else:
                    radius2 = radius
                r = radius2 / cusps2
            except:
                numbad += 1
                continue
            pts = []
            pt = feature.geometry().asPoint()
            # make sure the coordinates are in EPSG:4326
            if srcCRS != epsg4326:
                pt = geomTo4326.transform(pt.x(), pt.y())
            angle = 0.0
            while angle <= 360.0:
                a = math.radians(angle)
                x = r * (cusps2 - 1.0)*math.cos(a) + r * math.cos((cusps2 - 1.0) * a)
                y = r * (cusps2 - 1.0)*math.sin(a) - r * math.sin((cusps2 - 1.0) * a)
                a2 = math.degrees(math.atan2(y,x))+sangle
                dist = math.sqrt(x*x + y*y)
                g = geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE)
                pts.append(QgsPointXY(g['lon2'], g['lat2']))
                angle += step
                
            # If the Output crs is not 4326 transform the points to the proper crs
            if srcCRS != epsg4326:
                for x, ptout in enumerate(pts):
                    pts[x] = toSinkCrs.transform(ptout)
                    
            f = QgsFeature()
            if shapetype == 0:
                f.setGeometry(QgsGeometry.fromPolygonXY([pts]))
            else:
                f.setGeometry(QgsGeometry.fromPolylineXY(pts))
            f.setAttributes(feature.attributes())
            sink.addFeature(f)
            
            if index % 100 == 0:
                feedback.setProgress(int(index * total))
                
        if numbad > 0:
            feedback.pushInfo(tr("{} out of {} features had invalid parameters and were ignored.".format(numbad, featureCount)))
            
        return {self.PrmOutputLayer: dest_id}
 def processAlgorithm(self, parameters, context, feedback):
     source = self.parameterAsSource(parameters, self.PrmInputLayer, context)
     shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context)
     azimuthmode = self.parameterAsInt(parameters, self.PrmAzimuthMode, context)
     startanglecol = self.parameterAsString(parameters, self.PrmAzimuth1Field, context)
     endanglecol = self.parameterAsString(parameters, self.PrmAzimuth2Field, context)
     radiusCol = self.parameterAsString(parameters, self.PrmRadiusField, context)
     startangle = self.parameterAsDouble(parameters, self.PrmDefaultAzimuth1, context)
     endangle = self.parameterAsDouble(parameters, self.PrmDefaultAzimuth2, context)
     radius = self.parameterAsDouble(parameters, self.PrmDefaultRadius, context)
     segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context)
     units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context)
     export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context)
     
     measureFactor = conversionToMeters(units)
         
     radius *= measureFactor
     
     ptSpacing = 360.0 / segments
     srcCRS = source.sourceCrs()
     fields = source.fields()
     if export_geom:
         names = fields.names()
         name_x, name_y = settings.getGeomNames(names)
         fields.append(QgsField(name_x, QVariant.Double))
         fields.append(QgsField(name_y, QVariant.Double))
     if shapetype == 0:
         (sink, dest_id) = self.parameterAsSink(parameters,
             self.PrmOutputLayer, context, fields,
             QgsWkbTypes.Polygon, srcCRS)
     else:
         (sink, dest_id) = self.parameterAsSink(parameters,
             self.PrmOutputLayer, context, fields,
             QgsWkbTypes.LineString, srcCRS)
             
     if srcCRS != epsg4326:
         geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance())
         toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance())
     
     featureCount = source.featureCount()
     total = 100.0 / featureCount if featureCount else 0
     
     numbad = 0
     iterator = source.getFeatures()
     for cnt, feature in enumerate(iterator):
         if feedback.isCanceled():
             break
         try:
             pts = []
             pt = feature.geometry().asPoint()
             pt_orig_x = pt.x()
             pt_orig_y = pt.y()
             # make sure the coordinates are in EPSG:4326
             if srcCRS != epsg4326:
                 pt = geomTo4326.transform(pt.x(), pt.y())
             pts.append(pt)
             if startanglecol:
                 sangle = float(feature[startanglecol])
             else:
                 sangle = startangle
             if endanglecol:
                 eangle = float(feature[endanglecol])
             else:
                 eangle = endangle
             if azimuthmode == 1:
                 width = abs(eangle) / 2.0
                 eangle = sangle + width
                 sangle -= width
             if radiusCol:
                 dist = float(feature[radiusCol]) * measureFactor
             else:
                 dist = radius
                 
             sangle = sangle % 360
             eangle = eangle % 360
             
             if sangle > eangle:
                 # We are crossing the 0 boundry so lets just subtract
                 # 360 from it.
                 sangle -= 360.0
             while sangle < eangle:
                 g = geod.Direct(pt.y(), pt.x(), sangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE)
                 pts.append(QgsPointXY(g['lon2'], g['lat2']))
                 sangle += ptSpacing # add this number of degrees to the angle
                 
             g = geod.Direct(pt.y(), pt.x(), eangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE)
             pts.append(QgsPointXY(g['lon2'], g['lat2']))
             pts.append(pt)
                 
             # If the Output crs is not 4326 transform the points to the proper crs
             if srcCRS != epsg4326:
                 for x, ptout in enumerate(pts):
                     pts[x] = toSinkCrs.transform(ptout)
                     
             f = QgsFeature()
             if shapetype == 0:
                 f.setGeometry(QgsGeometry.fromPolygonXY([pts]))
             else:
                 f.setGeometry(QgsGeometry.fromPolylineXY(pts))
             attr = feature.attributes()
             if export_geom:
                 attr.append(pt_orig_x)
                 attr.append(pt_orig_y)
             f.setAttributes(attr)
             sink.addFeature(f)
         except:
             numbad += 1
             
         if cnt % 100 == 0:
             feedback.setProgress(int(cnt * total))
     
     if numbad > 0:
         feedback.pushInfo(tr("{} out of {} features had invalid parameters and were ignored.".format(numbad, featureCount)))
         
     return {self.PrmOutputLayer: dest_id}
Example #56
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # Retrieve the feature source and sink. The 'dest_id' variable is used
        # to uniquely identify the feature sink, and must be included in the
        # dictionary returned by the processAlgorithm function.
        couche_lines = self.parameterAsVectorLayer(parameters, self.LINES, context)
        couche_points = self.parameterAsVectorLayer(parameters, self.NODES, context)
        radius=self.parameterAsDouble(parameters,self.RAYON,context)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        delta=float(radius)
        index=QgsSpatialIndex()
        lines=couche_lines.getFeatures()
        for i in lines:
            if i.geometry().isMultipart():
                i.setGeometry(QgsGeometry.fromPolylineXY(i.geometry().asMultiPolyline()[0]))
            index.insertFeature(i)

        couche_lines.startEditing()
        couche_lines.beginEditCommand(self.tr("Split polylines at connections"))
        points=couche_points.getFeatures()
        nb=couche_points.featureCount()
        feedback.setProgressText(self.tr("Connecting points to lines..."))
        for pos,pt in enumerate(points):
            feedback.setProgress(pos*100.0/nb)
            ptg=pt.geometry()
            if ptg.isMultipart():
                ptg=QgsGeometry.fromPoint(ptg.asMultiPoint()[0])
            coor=ptg.asPoint()
            nearest=index.intersects(QgsRectangle(coor.x()-delta,coor.y()-delta,coor.x()+delta,coor.y()+delta))
            dmin=1e38
            if len(nearest)>0:
                for n in nearest:
                    f=couche_lines.getFeatures(request=QgsFeatureRequest(n))
                    for g in f:
                        d=g.geometry().distance(pt.geometry())
                        if d<=dmin:
                            dmin=d
                            gmin=g
                            gid=g.id()
                g=gmin
                if g.geometry().distance(pt.geometry())<delta:
                    a=g.geometry().closestSegmentWithContext(ptg.asPoint())
                    if not(a[2]==0):
                        geom=g.geometry()
                        geom.convertToSingleType()
                        geom_id=g.id()
                        att=g.attributes()
                        connexion=QgsFeature()
                        connexion.setGeometry(QgsGeometry.fromPolylineXY([ptg.asPoint(),a[1]]))
                        connexion.setAttributes(att)
                        couche_lines.addFeature(connexion)
                        geom.insertVertex(a[1][0],a[1][1],a[2])
                        geoma=geom.asPolyline()[:a[2]+1]
                        geomb=geom.asPolyline()[a[2]:]
                        feedback.setProgressText(unicode(geomb))
                        fa=QgsFeature()
                        fa.setGeometry(QgsGeometry.fromPolylineXY(geoma))
                        fa.setAttributes(att)
                        couche_lines.addFeature(fa)
                        index.insertFeature(fa)
                        fb=QgsFeature()
                        fb.setGeometry(QgsGeometry.fromPolylineXY(geomb))
                        fb.setAttributes(att)
                        couche_lines.addFeature(fb)
                        index.insertFeature(fb)
                        couche_lines.deleteFeature(g.id())
                        index.deleteFeature(g)
        couche_lines.commitChanges()
        couche_lines.endEditCommand()
        return {self.LINES: 'OK'}