Пример #1
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))

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

        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, 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)

        include_bounds = True # default to true to maintain 3.0 API
        if self.INCLUDE_BOUNDS in parameters:
            include_bounds = self.parameterAsBool(parameters, self.INCLUDE_BOUNDS, context)

        fields = startPoints.fields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        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)

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

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', '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 = []
        source_attributes = {}
        i = 0
        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('ServiceAreaFromLayer', 'Building graph…'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Calculating service areas…'))
        graph = builder.graph()

        (point_sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                                     fields, QgsWkbTypes.MultiPoint, network.sourceCrs())
        (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context,
                                                         fields, QgsWkbTypes.MultiLineString, network.sourceCrs())

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

            idxStart = graph.findVertex(snappedPoints[i])
            origPoint = points[i].toString()

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

            vertices = set()
            area_points = []
            lines = []
            for vertex, start_vertex_cost in enumerate(cost):
                inbound_edge_index = tree[vertex]
                if inbound_edge_index == -1 and vertex != idxStart:
                    # unreachable vertex
                    continue

                if start_vertex_cost > travelCost:
                    # vertex is too expensive, discard
                    continue

                vertices.add(vertex)
                start_point = graph.vertex(vertex).point()

                # find all edges coming from this vertex
                for edge_id in graph.vertex(vertex).outgoingEdges():
                    edge = graph.edge(edge_id)
                    end_vertex_cost = start_vertex_cost + edge.cost(0)
                    end_point = graph.vertex(edge.toVertex()).point()
                    if end_vertex_cost <= travelCost:
                        # end vertex is cheap enough to include
                        vertices.add(edge.toVertex())
                        lines.append([start_point, end_point])
                    else:
                        # travelCost sits somewhere on this edge, interpolate position
                        interpolated_end_point = QgsGeometryUtils.interpolatePointOnLineByValue(start_point.x(), start_point.y(), start_vertex_cost,
                                                                                                end_point.x(), end_point.y(), end_vertex_cost, travelCost)
                        area_points.append(interpolated_end_point)
                        lines.append([start_point, interpolated_end_point])

            for v in vertices:
                area_points.append(graph.vertex(v).point())

            feat = QgsFeature()
            if point_sink is not None:
                geomPoints = QgsGeometry.fromMultiPointXY(area_points)
                feat.setGeometry(geomPoints)
                attrs = source_attributes[i]
                attrs.extend(['within', origPoint])
                feat.setAttributes(attrs)
                point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

                if include_bounds:
                    upperBoundary = []
                    lowerBoundary = []

                    vertices = []
                    for vertex, c in enumerate(cost):
                        if c > travelCost and tree[vertex] != -1:
                            vertexId = graph.edge(tree[vertex]).fromVertex()
                            if cost[vertexId] <= travelCost:
                                vertices.append(vertex)

                    for v in vertices:
                        upperBoundary.append(graph.vertex(graph.edge(tree[v]).toVertex()).point())
                        lowerBoundary.append(graph.vertex(graph.edge(tree[v]).fromVertex()).point())

                    geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
                    geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

                    feat.setGeometry(geomUpper)
                    attrs[-2] = 'upper'
                    feat.setAttributes(attrs)
                    point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

                    feat.setGeometry(geomLower)
                    attrs[-2] = 'lower'
                    feat.setAttributes(attrs)
                    point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

            if line_sink is not None:
                geom_lines = QgsGeometry.fromMultiPolylineXY(lines)
                feat.setGeometry(geom_lines)
                attrs = source_attributes[i]
                attrs.extend(['lines', origPoint])
                feat.setAttributes(attrs)
                line_sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(i * total))

        results = {}
        if point_sink is not None:
            results[self.OUTPUT] = dest_id
        if line_sink is not None:
            results[self.OUTPUT_LINES] = line_dest_id
        return results
Пример #2
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context, network.sourceCrs())
        endPoints = self.parameterAsSource(parameters, self.END_POINTS,
                                           context)
        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 = endPoints.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('ShortestPathPointToLayer',
                                       'Loading end points…'))
        request = QgsFeatureRequest()
        request.setDestinationCrs(network.sourceCrs(),
                                  context.transformContext())
        features = endPoints.getFeatures(request)
        total = 100.0 / endPoints.featureCount() if endPoints.featureCount(
        ) else 0

        points = [startPoint]
        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('ShortestPathPointToLayer',
                                       'Building graph…'))
        snappedPoints = director.makeGraph(builder, points, feedback)

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

        idxStart = graph.findVertex(snappedPoints[0])
        tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

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

            idxEnd = graph.findVertex(snappedPoints[i])

            if tree[idxEnd] == -1:
                msg = self.tr(
                    'There is no route from start point ({}) to end point ({}).'
                    .format(startPoint.toString(), points[i].toString()))
                feedback.reportError(msg)
                # add feature with no geometry
                feat.clearGeometry()
                attrs = source_attributes[i]
                attrs.extend([NULL, 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)
            attrs = source_attributes[i]
            attrs.extend([
                startPoint.toString(), points[i].toString(), cost / multiplier
            ])
            feat.setAttributes(attrs)
            feat.setGeometry(geom)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Пример #3
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        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())

        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(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint, endPoint],
                                           feedback)

        feedback.pushInfo(self.tr('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(self.tr('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
Пример #4
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS,
                                             context)
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST,
                                            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('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        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)

        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 = []
        source_attributes = {}
        i = 0
        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 service areas...'))
        graph = builder.graph()

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

        vertices = []
        upperBoundary = []
        lowerBoundary = []
        total = 100.0 / len(snappedPoints) if snappedPoints else 1
        for i, p in enumerate(snappedPoints):
            if feedback.isCanceled():
                break

            idxStart = graph.findVertex(snappedPoints[i])
            origPoint = points[i].toString()

            tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
            for j, v in enumerate(cost):
                if v > travelCost and tree[j] != -1:
                    vertexId = graph.edge(tree[j]).fromVertex()
                    if cost[vertexId] <= travelCost:
                        vertices.append(j)

            for j in vertices:
                upperBoundary.append(
                    graph.vertex(graph.edge(tree[j]).toVertex()).point())
                lowerBoundary.append(
                    graph.vertex(graph.edge(tree[j]).fromVertex()).point())

            geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
            geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

            feat.setGeometry(geomUpper)

            attrs = source_attributes[i]
            attrs.extend(['upper', origPoint])
            feat.setAttributes(attrs)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feat.setGeometry(geomLower)
            attrs[-2] = 'lower'
            feat.setAttributes(attrs)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            vertices[:] = []
            upperBoundary[:] = []
            lowerBoundary[:] = []

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Пример #5
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoints = dataobjects.getLayerFromString(
            self.getParameterValue(self.START_POINTS))
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        writerPoints = self.getOutputFromName(
            self.OUTPUT_POINTS).getVectorWriter(fields, QgsWkbTypes.MultiPoint,
                                                layer.crs())

        writerPolygons = self.getOutputFromName(
            self.OUTPUT_POLYGON).getVectorWriter(fields, QgsWkbTypes.Polygon,
                                                 layer.crs())

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

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

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)

        feedback.pushInfo(self.tr('Loading start points...'))
        request = QgsFeatureRequest()
        request.setFlags(request.flags()
                         ^ QgsFeatureRequest.SubsetOfAttributes)
        features = vector.features(startPoints, request)
        points = []
        for f in features:
            points.append(f.geometry().asPoint())

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

        feedback.pushInfo(self.tr('Calculating service areas...'))
        graph = builder.graph()

        vertices = []
        upperBoundary = []
        lowerBoundary = []
        total = 100.0 / len(snappedPoints)
        for i, p in enumerate(snappedPoints):
            idxStart = graph.findVertex(snappedPoints[i])
            origPoint = points[i].toString()

            tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
            for j, v in enumerate(cost):
                if v > travelCost and tree[j] != -1:
                    vertexId = graph.edge(tree[j]).outVertex()
                    if cost[vertexId] <= travelCost:
                        vertices.append(j)

            for j in vertices:
                upperBoundary.append(
                    graph.vertex(graph.edge(tree[j]).inVertex()).point())
                lowerBoundary.append(
                    graph.vertex(graph.edge(tree[j]).outVertex()).point())

            geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
            geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

            feat.setGeometry(geomUpper)
            feat['type'] = 'upper'
            feat['start'] = origPoint
            writerPoints.addFeature(feat)

            feat.setGeometry(geomLower)
            feat['type'] = 'lower'
            feat['start'] = origPoint
            writerPoints.addFeature(feat)

            upperBoundary.append(origPoint)
            lowerBoundary.append(origPoint)
            geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
            geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

            geom = geomUpper.convexHull()
            feat.setGeometry(geom)
            feat['type'] = 'upper'
            feat['start'] = origPoint
            writerPolygons.addFeature(feat)

            geom = geomLower.convexHull()
            feat.setGeometry(geom)
            feat['type'] = 'lower'
            feat['start'] = origPoint
            writerPolygons.addFeature(feat)

            vertices[:] = []
            upperBoundary[:] = []
            lowerBoundary[:] = []

            feedback.setProgress(int(i * total))

        del writerPoints
        del writerPolygons
Пример #6
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)
        startPoint = self.getParameterValue(self.START_POINT)
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        tmp = startPoint.split(',')
        startPoint = QgsPointXY(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

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

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)
        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint])

        feedback.pushInfo(self.tr('Calculating service area...'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = []
        for i, v in enumerate(cost):
            if v > travelCost and tree[i] != -1:
                vertexId = graph.edge(tree[i]).outVertex()
                if cost[vertexId] <= travelCost:
                    vertices.append(i)

        upperBoundary = []
        lowerBoundary = []
        for i in vertices:
            upperBoundary.append(
                graph.vertex(graph.edge(tree[i]).inVertex()).point())
            lowerBoundary.append(
                graph.vertex(graph.edge(tree[i]).outVertex()).point())

        feedback.pushInfo(self.tr('Writing results...'))

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
        geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

        writer = self.getOutputFromName(self.OUTPUT_POINTS).getVectorWriter(
            fields, QgsWkbTypes.MultiPoint, layer.crs(), context)

        feat.setGeometry(geomUpper)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat, QgsFeatureSink.FastInsert)

        feat.setGeometry(geomLower)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat, QgsFeatureSink.FastInsert)

        del writer

        upperBoundary.append(startPoint)
        lowerBoundary.append(startPoint)
        geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
        geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

        writer = self.getOutputFromName(self.OUTPUT_POLYGON).getVectorWriter(
            fields, QgsWkbTypes.Polygon, layer.crs(), context)

        geom = geomUpper.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat, QgsFeatureSink.FastInsert)

        geom = geomLower.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat, QgsFeatureSink.FastInsert)
        del writer
Пример #7
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoint = self.getParameterValue(self.START_POINT)
        endPoint = self.getParameterValue(self.END_POINT)
        strategy = self.getParameterValue(self.STRATEGY)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        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))

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            fields.toList(), QgsWkbTypes.LineString, layer.crs())

        tmp = startPoint.split(',')
        startPoint = QgsPoint(float(tmp[0]), float(tmp[1]))
        tmp = endPoint.split(',')
        endPoint = QgsPoint(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

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

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().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(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)
        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint, endPoint])

        feedback.pushInfo(self.tr('Calculating shortest path...'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])
        idxEnd = graph.findVertex(snappedPoints[1])

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

        route = []
        cost = 0.0
        current = idxEnd
        while current != idxStart:
            cost += graph.edge(tree[current]).cost(0)
            route.append(
                graph.vertex(graph.edge(tree[current]).inVertex()).point())
            current = graph.edge(tree[current]).outVertex()

        route.append(snappedPoints[0])
        route.reverse()

        self.setOutputValue(self.TRAVEL_COST, cost / multiplier)

        feedback.pushInfo(self.tr('Writing results...'))
        geom = QgsGeometry.fromPolyline(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        writer.addFeature(feat)
        del writer
Пример #8
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_VECTOR), context)
        startPoints = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.START_POINTS), context)
        endPoint = self.getParameterValue(self.END_POINT)
        strategy = self.getParameterValue(self.STRATEGY)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        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))

        feat = QgsFeature()
        feat.setFields(fields)

        writer = self.getOutputFromName(
            self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.LineString, layer.crs(), context)

        tmp = endPoint.split(',')
        endPoint = QgsPointXY(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

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

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().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(iface.mapCanvas().mapSettings().destinationCrs(),
                                  True,
                                  tolerance)

        feedback.pushInfo(self.tr('Loading start points...'))
        request = QgsFeatureRequest()
        request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes)
        features = QgsProcessingUtils.getFeatures(startPoints, context, request)
        count = QgsProcessingUtils.featureCount(startPoints, context)

        points = [endPoint]
        for f in features:
            points.append(f.geometry().asPoint())

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

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

        idxEnd = graph.findVertex(snappedPoints[0])
        route = []

        total = 100.0 / count if count else 1
        for i in range(1, count + 1):
            idxStart = graph.findVertex(snappedPoints[i])
            tree, cost = 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.setProgressText(msg)
                QgsMessageLog.logMessage(msg, self.tr('Processing'), QgsMessageLog.WARNING)
                continue

            cost = 0.0
            current = idxEnd
            while current != idxStart:
                cost += graph.edge(tree[current]).cost(0)
                route.append(graph.vertex(graph.edge(tree[current]).inVertex()).point())
                current = graph.edge(tree[current]).outVertex()

            route.append(snappedPoints[i])
            route.reverse()

            geom = QgsGeometry.fromPolyline(route)
            feat.setGeometry(geom)
            feat['start'] = points[i].toString()
            feat['end'] = endPoint.toString()
            feat['cost'] = cost / multiplier
            writer.addFeature(feat, QgsFeatureSink.FastInsert)

            route[:] = []

            feedback.setProgress(int(i * total))

        del writer
Пример #9
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST,
                                            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)

        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)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance)
        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint], feedback)

        feedback.pushInfo(self.tr('Calculating service area...'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = []
        for i, v in enumerate(cost):
            if v > travelCost and tree[i] != -1:
                vertexId = graph.edge(tree[i]).fromVertex()
                if cost[vertexId] <= travelCost:
                    vertices.append(i)

        upperBoundary = []
        lowerBoundary = []
        for i in vertices:
            upperBoundary.append(
                graph.vertex(graph.edge(tree[i]).toVertex()).point())
            lowerBoundary.append(
                graph.vertex(graph.edge(tree[i]).fromVertex()).point())

        feedback.pushInfo(self.tr('Writing results...'))

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
        geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

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

        feat.setGeometry(geomUpper)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        feat.setGeometry(geomLower)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        upperBoundary.append(startPoint)
        lowerBoundary.append(startPoint)
        geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
        geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

        return {self.OUTPUT: dest_id}
Пример #10
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context)
        endPoints = self.parameterAsSource(parameters, self.END_POINTS,
                                           context)
        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))

        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(context.project().crs(), True, tolerance)

        feedback.pushInfo(self.tr('Loading end points...'))
        request = QgsFeatureRequest()
        request.setFlags(request.flags()
                         ^ QgsFeatureRequest.SubsetOfAttributes)
        request.setDestinationCrs(network.sourceCrs())
        features = endPoints.getFeatures(request)
        total = 100.0 / endPoints.featureCount() if endPoints.featureCount(
        ) else 0

        points = [startPoint]
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            points.append(f.geometry().asPoint())
            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()

        idxStart = graph.findVertex(snappedPoints[0])
        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        route = []

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

            idxEnd = graph.findVertex(snappedPoints[i])

            if tree[idxEnd] == -1:
                msg = self.tr(
                    'There is no route from start point ({}) to end point ({}).'
                    .format(startPoint.toString(), points[i].toString()))
                feedback.setProgressText(msg)
                QgsMessageLog.logMessage(msg, self.tr('Processing'),
                                         QgsMessageLog.WARNING)
                continue

            cost = 0.0
            current = idxEnd
            while current != idxStart:
                cost += graph.edge(tree[current]).cost(0)
                route.append(
                    graph.vertex(graph.edge(tree[current]).inVertex()).point())
                current = graph.edge(tree[current]).outVertex()

            route.append(snappedPoints[0])
            route.reverse()

            geom = QgsGeometry.fromPolyline(route)
            feat.setGeometry(geom)
            feat['start'] = startPoint.toString()
            feat['end'] = points[i].toString()
            feat['cost'] = cost / multiplier
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            route[:] = []

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Пример #11
0
    def __init__(
            self,
            input_network,  #QgsProcessingParameterFeatureSource
            input_points,  #[QgsPointXY] or QgsProcessingParameterFeatureSource or QgsVectorLayer --> Implement List of QgsFeatures [QgsFeatures]
            input_strategy,  #int
            input_directionFieldName,  #str, empty if field not given
            input_forwardValue,  #str
            input_backwardValue,  #str
            input_bothValue,  #str
            input_defaultDirection,  #int
            input_analysisCrs,  #QgsCoordinateReferenceSystem
            input_speedField,  #str
            input_defaultSpeed,  #float
            input_tolerance,  #float
            feedback  #feedback object from processing (log window)
    ):
        """
        Constructor for a Qneat3Network object.
        @type input_network: QgsProcessingParameterFeatureSource
        @param input_network: input network dataset from processing algorithm 
        @type input_points: QgsProcessingParameterFeatureSource/QgsVectorLayer/[QgsPointXY]
        @param input_points: input point dataset from processing algorithm
        @type input_strategy: int
        @param input_strategy: Strategy parameter (0 for distance evaluation, 1 time evaluation)
        @type directionFieldName: string
        @param directionFieldName: Field name of field containing direction information
        @type input_forwardValue: string
        @param input_forwardValue: Value assigned to forward-directed edges
        @type input_backwardValue: string
        @param input_backwardValue: Value assigned to backward-directed edges
        @type input_bothValue: string
        @param input_bothValues: Value assigned to undirected edges (accessible from both directions)
        @type input_defaultDirection: QgsVectorLayerDirector.DirectionForward/DirectionBackward/DirectionBoth
        @param input_defaultDirection: QgsVectorLayerDirector Direction enum to determine default direction
        @type input_analysisCrs: QgsCoordinateReferenceSystem
        @param input_analysisCrs: Analysis coordinate system
        @type input_speedField: string
        @param input_speedField: Field name of field containing speed information
        @type input_tolerance: float
        @param input_tolerance: tolerance value when connecting graph edges
        @type feedback: QgsProcessingFeedback
        @param feedback: feedback object from processing algorithm
        """

        #initialize feedback
        self.feedback = feedback

        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Setting up parameters")
        self.AnalysisCrs = input_analysisCrs

        #enable polygon calculation in geographic coordinate systems
        distUnit = self.AnalysisCrs.mapUnits()
        self.meter_to_unit_factor = QgsUnitTypes.fromUnitToUnitFactor(
            QgsUnitTypes.DistanceMeters, distUnit)

        #init direction fields
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Setting up network direction parameters"
        )
        self.directedAnalysis = self.setNetworkDirection(
            (input_directionFieldName, input_forwardValue, input_backwardValue,
             input_bothValue, input_defaultDirection))
        self.director = QgsVectorLayerDirector(
            input_network,
            getFieldIndexFromQgsProcessingFeatureSource(
                input_network, input_directionFieldName), input_forwardValue,
            input_backwardValue, input_bothValue, input_defaultDirection)

        #init analysis points
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Setting up analysis points")
        if isinstance(input_points, (list, )):
            self.list_input_points = input_points  #[QgsPointXY]
        else:
            self.list_input_points = getListOfPoints(
                input_points)  #[QgsPointXY]
            self.input_points = input_points

        #Setup cost-strategy pattern.
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Setting analysis strategy: {}".format(
                input_strategy))
        self.default_speed = input_defaultSpeed

        self.setNetworkStrategy(input_strategy, input_network,
                                input_speedField, input_defaultSpeed)

        #add the strategy to the QgsGraphDirector
        self.director.addStrategy(self.strategy)
        self.builder = QgsGraphBuilder(self.AnalysisCrs)
        #tell the graph-director to make the graph using the builder object and tie the start point geometry to the graph

        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Start tying analysis points to the graph and building it."
        )
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] This is a compute intensive task and may take some time depending on network size"
        )
        start_local_time = time.localtime()
        start_time = time.time()
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Start Time: {}".format(
                time.strftime(":%Y-%m-%d %H:%M:%S", start_local_time)))
        self.feedback.pushInfo("[QNEAT3Network][__init__] Building...")
        self.list_tiedPoints = self.director.makeGraph(self.builder,
                                                       self.list_input_points,
                                                       self.feedback)
        self.network = self.builder.graph()
        end_local_time = time.localtime()
        end_time = time.time()
        self.feedback.pushInfo("[QNEAT3Network][__init__] End Time: {}".format(
            time.strftime(":%Y-%m-%d %H:%M:%S", end_local_time)))
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Total Build Time: {}".format(
                end_time - start_time))
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Analysis setup complete")
Пример #12
0
    def graph_builder(self, network, cost_field, origins, tolerance, crs,
                      epsg):

        # Settings
        otf = False

        # Get index of cost field
        network_fields = network.fields()
        network_cost_index = network_fields.indexFromName(cost_field)

        # Setting up graph build director
        director = QgsVectorLayerDirector(network, -1, '', '', '',
                                          QgsVectorLayerDirector.DirectionBoth)

        # Determining cost calculation
        if cost_field != 'length':
            strategy = ct.CustomCost(network_cost_index, 0.01)
        else:
            strategy = QgsNetworkDistanceStrategy()

        # Creating graph builder
        director.addStrategy(strategy)
        builder = QgsGraphBuilder(crs, otf, tolerance, epsg)

        # Reading origins and making list of coordinates
        graph_origin_points = []

        # Loop through the origin points and add graph vertex indices
        for index, origin in enumerate(origins):
            graph_origin_points.append(origins[index]['geom'].asPoint())

        # Get origin graph vertex index
        tied_origin_vertices = director.makeGraph(builder, graph_origin_points)

        # Build the graph
        graph = builder.graph()

        # Create dictionary of origin names and tied origins
        tied_origins = {}

        # Combine origin names and tied point vertices
        for index, tied_origin in enumerate(tied_origin_vertices):
            tied_origins[index] = {
                'name': origins[index]['name'],
                'vertex': tied_origin
            }

        self.spIndex = QgsSpatialIndex()
        self.indices = {}
        self.attributes_dict = {}
        self.centroids = {}
        i = 0
        for f in network.getFeatures():
            if f.geometry().type() == QgsWkbTypes.LineGeometry:
                if not f.geometry().isMultipart():
                    self.attributes_dict[f.id()] = f.attributes()
                    polyline = f.geometry().asPolyline()
                    for idx, p in enumerate(polyline[1:]):
                        ml = QgsGeometry.fromPolylineXY([polyline[idx], p])
                        new_f = QgsFeature()
                        new_f.setGeometry(ml.centroid())
                        new_f.setAttributes([f.id()])
                        new_f.setId(i)
                        self.spIndex.addFeature(new_f)
                        self.centroids[i] = f.id()
                        i += 1
                else:
                    self.attributes_dict[f.id()] = f.attributes()
                    for pl in f.geometry().asMultiPolyline():
                        for idx, p in enumerate(pl[1:]):
                            ml = QgsGeometry.fromPolylineXY([pl[idx], p])
                            new_f = QgsFeature()
                            new_f.setGeometry(ml.centroid())
                            new_f.setAttributes([f.id()])
                            new_f.setId(i)
                            self.spIndex.addFeature(new_f)
                            self.centroids[i] = f.id()
                            i += 1

        self.network_fields = network_fields
        return graph, tied_origins
# Get index of cost field
network_fields = network.pendingFields()
network_cost_index = network_fields.indexFromName(cost_field)

# Setting up graph build director
director = QgsLineVectorLayerDirector(network, -1, '', '', '', 3)

# Determining cost calculation
if cost_field != 'length':
    properter = CustomCost(network_cost_index, 0.01)
else:
    properter = QgsDistanceArcProperter()

# Creating graph builder
director.addProperter(properter)
builder = QgsGraphBuilder(crs, otf, tolerance, epsg)

# Reading origins and making list of coordinates
graph_origin_points = []

# Loop through the origin points and add graph vertex indices
for index, origin in enumerate(origins):
    graph_origin_points.append(origins[index]['geom'].asPoint())

# Get origin graph vertex index
tied_origin_vertices = director.makeGraph(builder, graph_origin_points)

# Build the graph
graph = builder.graph()

# Create dictionary of origin names and tied origins