Пример #1
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        layerHandler = LayerHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        ignoreClosed = self.parameterAsBool(parameters, self.IGNORE_CLOSED,
                                            context)
        fixInput = self.parameterAsBool(parameters, self.TYPE, context)
        self.prepareFlagSink(parameters, inputLyr, QgsWkbTypes.Point, context)

        multiStepFeedback = QgsProcessingMultiStepFeedback(2, feedback)
        multiStepFeedback.setCurrentStep(0)
        flagDict = layerHandler.identifyAndFixInvalidGeometries(
            inputLyr=inputLyr,
            ignoreClosed=ignoreClosed,
            fixInput=fixInput,
            onlySelected=onlySelected,
            feedback=multiStepFeedback)
        multiStepFeedback.setCurrentStep(1)
        itemSize = len(flagDict)
        progressSize = 100 / itemSize if itemSize else 0
        for current, (key, outDict) in enumerate(flagDict.items()):
            if multiStepFeedback.isCanceled():
                break
            self.flagFeature(flagGeom=outDict['geom'],
                             flagText=outDict['reason'])
            multiStepFeedback.setProgress(current * progressSize)

        return {self.FLAGS: self.flag_id, self.OUTPUT: inputLyr}
Пример #2
0
 def filterDangles(self, lyr, searchRadius, feedback = None):
     deleteList = []
     if feedback is not None:
         multiStepFeedback = QgsProcessingMultiStepFeedback(2, feedback)
         multiStepFeedback.setCurrentStep(0)
     else:
         multiStepFeedback = None
     spatialIdx, idDict = self.buildSpatialIndexAndIdDict(lyr, feedback=multiStepFeedback)
     if multiStepFeedback is not None:
         multiStepFeedback.setCurrentStep(1)
     featSize = len(idDict)
     size = 100 / featSize if featSize else 0
     for current, (id, feat) in enumerate(idDict.items()):
         if feedback is not None and feedback.isCanceled():
             break
         if id not in deleteList:
             buffer = feat.geometry().buffer(searchRadius, -1)
             bufferBB = buffer.boundingBox()
             #gets candidates from spatial index
             candidateIds = spatialIdx.intersects(bufferBB)
             for fid in candidateIds:
                 if fid != id and fid not in deleteList and buffer.intersects(feat.geometry()):
                     deleteList.append(fid)
         if feedback is not None:
             multiStepFeedback.setProgress(size * current)
     
     lyr.startEditing()
     lyr.beginEditCommand('Filter dangles')
     lyr.deleteFeatures(deleteList)
     lyr.commitChanges()
Пример #3
0
 def getFrameOutterBounds(self, frameLayer, algRunner, context, feedback = None):
     """
     Gets the outter bounds of all frame features composing frame layer.
     :param frameLayer: (QgsVectorLayer) frame layer.
     :return: (list-of-QgsGeometry) list of all disjuncts outter bounds of features in frame layer.
     """
     frameGeomList = []
     if feedback is not None:
         multiStepFeedback = QgsProcessingMultiStepFeedback(3, feedback)
         multiStepFeedback.setCurrentStep(0)
     else:
         multiStepFeedback = None
     # dissolve every feature into a single one
     outputLayer = algRunner.runDissolve(frameLayer, context, feedback = multiStepFeedback)
     if feedback is not None:
         multiStepFeedback.setCurrentStep(1)
     boundaryLayer = algRunner.runBoundary(outputLayer, context, feedback = multiStepFeedback)
     # get all frame outter layer found
     if feedback is not None:
         multiStepFeedback.setCurrentStep(2)
         featCount = boundaryLayer.featureCount()
         size = 100/featCount if featCount else 0
     for current, feat in enumerate(boundaryLayer.getFeatures()):
         if feedback is not None and feedback.isCanceled():
             break
         geom = feat.geometry()
         # deaggregate geometry, if necessary
         frameGeomList += self.geometryHandler.deaggregateGeometry(multiGeom=geom)
         if feedback is not None:
             multiStepFeedback.setProgress(size * current)
     return frameGeomList
Пример #4
0
 def getUnifiedLayerFeatures(self, unifiedLyr, layerList, attributeTupple=False, attributeBlackList=None, onlySelected=False, parameterDict=None, feedback=None):
     parameterDict = {} if parameterDict is None else parameterDict
     featList = []
     blackList = attributeBlackList.split(',') if attributeBlackList is not None and ',' in attributeBlackList else []
     if feedback:
         multiStepFeedback = QgsProcessingMultiStepFeedback(len(layerList), feedback)
     for i, layer in enumerate(layerList):
         if feedback:
             if feedback.isCanceled():
                 break
             multiStepFeedback.setCurrentStep(i)
         # recording class name
         layername = layer.name()
         coordinateTransformer = self.getCoordinateTransformer(unifiedLyr, layer)
         iterator, size = self.getFeatureList(layer, onlySelected=onlySelected, returnSize=True)
         for current, feature in enumerate(iterator):
             if feedback:
                 if multiStepFeedback.isCanceled():
                     break
             newFeats = self.featureHandler.createUnifiedFeature(unifiedLyr, feature, layername,\
                                                                bList=blackList, \
                                                                attributeTupple=attributeTupple, \
                                                                parameterDict=parameterDict, \
                                                                coordinateTransformer=coordinateTransformer)
             featList += newFeats
             if feedback:
                 multiStepFeedback.setProgress(current*size)
     return featList
Пример #5
0
 def make_inventory_from_processing(self,
                                    parent_folder,
                                    format_list,
                                    destination_folder=None,
                                    make_copy=False,
                                    onlyGeo=True,
                                    feedback=None):
     featList = []
     fileList = []
     format_set = self.get_format_set(format_list)
     tuple_list = [i for i in os.walk(parent_folder)]
     nSteps = len(tuple_list) if make_copy else len(tuple_list) - 1
     multiStepFeedback = QgsProcessingMultiStepFeedback(
         nSteps, feedback) if feedback else None
     for current_step, [root, dirs, files] in enumerate(tuple_list):
         if feedback is not None:
             if feedback.isCanceled():
                 return []
             multiStepFeedback.setCurrentStep(current_step)
         n_files = len(files)
         files_progress = 100 / n_files if n_files else 0
         for current, current_file in enumerate(files):
             if multiStepFeedback is not None and multiStepFeedback.isCanceled(
             ):
                 break
             extension = current_file.split('.')[-1]
             if extension not in format_set:
                 continue
             full_path = self.get_full_path(current_file, root)
             if gdal.Open(full_path) or ogr.Open(full_path):
                 bbox_geom, attributes = self.computeBoxAndAttributes(
                     None, full_path, extension, insertIntoMemory=False)
                 new_feat = self.get_new_feat(bbox_geom, attributes)
                 featList.append(new_feat)
                 fileList.append(full_path)
             if multiStepFeedback is not None:
                 multiStepFeedback.setProgress(files_progress * current)
     if make_copy:
         if multiStepFeedback is not None:
             multiStepFeedback.setCurrentStep(nSteps)
         copy_len = len(fileList)
         for current, file_ in fileList:
             if multiStepFeedback is not None and multiStepFeedback.isCanceled:
                 break
             try:
                 self.copy_single_file(file_, destination_folder)
                 if multiStepFeedback is not None:
                     multiStepFeedback.pushInfo(
                         self.tr(
                             'File {file} copied to {destination}').format(
                                 file=file_,
                                 destination=destination_folder))
             except Exception as e:
                 if multiStepFeedback is not None:
                     multiStepFeedback.pushInfo(
                         self.tr('Error copying file {file}: {exception}\n'
                                 ).format(file=file_,
                                          exception='\n'.join(e.args)))
     return featList
Пример #6
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        inputLyrList = self.parameterAsLayerList(parameters, self.INPUTLAYERS,
                                                 context)
        if inputLyrList == []:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUTLAYERS))
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        self.prepareFlagSink(parameters, inputLyrList[0], QgsWkbTypes.Polygon,
                             context)
        # Compute the number of steps to display within the progress bar and
        # get features from source
        geomDict = dict()
        multiStepFeedback = QgsProcessingMultiStepFeedback(
            len(inputLyrList) + 1, feedback)
        for currentLyrIdx, lyr in enumerate(inputLyrList):
            multiStepFeedback.setCurrentStep(currentLyrIdx)
            featIterator, total = self.getIteratorAndFeatureCount(
                lyr, onlySelected=onlySelected)
            size = 100 / total if total else 0
            lyrName = lyr.name()
            for current, feat in enumerate(featIterator):
                # Stop the algorithm if cancel button has been clicked
                if multiStepFeedback.isCanceled():
                    break
                geom = feat.geometry()
                geomKey = geom.asWkb()
                if geomKey not in geomDict:
                    geomDict[geomKey] = []
                geomDict[geomKey].append({'feat': feat, 'layerName': lyrName})
                # # Update the progress bar
                multiStepFeedback.setProgress(current * size)
        for v in geomDict.values():
            if multiStepFeedback.isCanceled():
                break
            if len(v) > 1:
                flagStrList = [
                    '{lyrName} (id={id})'.format(lyrName=featDict['layerName'],
                                                 id=featDict['feat'].id())
                    for featDict in v
                ]
                flagStr = ', '.join(flagStrList)
                flagText = self.tr(
                    'Features from coverage with same geometry: {0}.').format(
                        flagStr)
                self.flagFeature(v[0]['feat'].geometry(), flagText)

        return {self.FLAGS: self.flag_id}
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        geometryHandler = GeometryHandler()
        layerHandler = LayerHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        if inputLyr is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))
        isMulti = QgsWkbTypes.isMultiType(int(inputLyr.wkbType()))
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        self.prepareFlagSink(parameters, inputLyr, QgsWkbTypes.Polygon,
                             context)
        # Compute the number of steps to display within the progress bar and
        # get features from source

        multiStepFeedback = QgsProcessingMultiStepFeedback(3, feedback)
        multiStepFeedback.setCurrentStep(0)
        lyr = self.overlayCoverage(inputLyr, context, multiStepFeedback)
        featureList, total = self.getIteratorAndFeatureCount(
            lyr
        )  #only selected is not applied because we are using an inner layer, not the original ones
        QgsProject.instance().removeMapLayer(lyr)
        geomDict = dict()
        multiStepFeedback.setCurrentStep(1)
        for current, feat in enumerate(featureList):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break
            geom = feat.geometry()
            if isMulti and not geom.isMultipart():
                geom.convertToMultiType()
            geomKey = geom.asWkb()
            if geomKey not in geomDict:
                geomDict[geomKey] = []
            geomDict[geomKey].append(feat)
            # # Update the progress bar
            multiStepFeedback.setProgress(current * total)
        multiStepFeedback.setCurrentStep(2)
        total = 100 / len(geomDict) if len(geomDict) != 0 else 0
        for k, v in geomDict.items():
            if feedback.isCanceled():
                break
            if len(v) > 1:
                flagText = self.tr('Features from {0} overlap.').format(
                    inputLyr.name())
                self.flagFeature(v[0].geometry(), flagText)
            multiStepFeedback.setProgress(current * total)
        return {self.FLAGS: self.flag_id}
Пример #8
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        geometryHandler = GeometryHandler()
        layerHandler = LayerHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        if inputLyr is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))
        isMulti = QgsWkbTypes.isMultiType(int(inputLyr.wkbType()))
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        self.prepareFlagSink(parameters, inputLyr, QgsWkbTypes.Polygon,
                             context)
        # Compute the number of steps to display within the progress bar and
        # get features from source
        multiStepFeedback = QgsProcessingMultiStepFeedback(4, feedback)
        lyr = self.getGapLyr(inputLyr,
                             context,
                             multiStepFeedback,
                             onlySelected=onlySelected)
        featureList, total = self.getIteratorAndFeatureCount(
            lyr
        )  #only selected is not applied because we are using an inner layer, not the original ones
        QgsProject.instance().removeMapLayer(lyr)
        geomDict = dict()

        multiStepFeedback.setCurrentStep(3)
        for current, feat in enumerate(featureList):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break
            attrList = feat.attributes()
            if attrList == len(attrList) * [None]:
                geom = feat.geometry()
                self.flagFeature(
                    geom,
                    self.tr('Gap in layer {0}.').format(inputLyr.name()))
            # # Update the progress bar
            multiStepFeedback.setProgress(current * total)
        return {self.FLAGS: self.flag_id}
    def processAlgorithm(self, parameters, context, model_feedback):

        # source: 'export as python script' in processing modeler
        feedback = QgsProcessingMultiStepFeedback(3, model_feedback)

        # pass
        source = self.parameterAsFile(parameters, self.INPUT, context)
        server_name = self.server_name_options[self.parameterAsInt(
            parameters, self.SERVER_NAME, context)]
        graph_name = self.parameterAsString(parameters, self.GRAPH_NAME,
                                            context)
        graph_version = self.graph_version_options[self.parameterAsInt(
            parameters, self.GRAPH_VERSION, context)]
        routing_mode = self.routing_mode_options[self.parameterAsInt(
            parameters, self.ROUTING_MODE, context)]

        if os.path.splitext(source)[-1].lower() == '.json':
            feedback.pushInfo('Load json track file')
            with open(source) as json_data:
                track_data = json.load(json_data)
        elif os.path.splitext(source)[-1].lower() == '.gpx':
            feedback.pushInfo(
                'Convert track file from GPX to JSON format using Graphium:Gpx2JsonConverter'
            )
            try:
                output = processing.run("Graphium:gpx2jsonconverter",
                                        parameters={
                                            'INPUT': source,
                                            'OUTPUT': 'TEMPORARY_OUTPUT'
                                        },
                                        is_child_algorithm=True,
                                        context=context,
                                        feedback=feedback)['OUTPUT']
                with open(output) as json_data:
                    track_data = json.load(json_data)
            except QgsProcessingException as e:
                feedback.reportError(
                    "Could not convert GPX file to JSON: " + str(e), True)
                return {self.OUTPUT_MATCHED_SEGMENTS: None}
        else:
            feedback.reportError(
                "Wrong track file format (" +
                os.path.splitext(source)[-1].lower() + ")", True)
            return {self.OUTPUT_MATCHED_SEGMENTS: None}

        # Connect to Graphium
        feedback.setCurrentStep(2)
        feedback.pushInfo("Connect to Graphium server '" + server_name +
                          "' ...")

        graphium = GraphiumUtilitiesApi(feedback)
        selected_connection = self.connection_manager.select_graphium_server(
            server_name)
        if selected_connection is None:
            feedback.reportError('Cannot select connection to Graphium', True)
            return {self.OUTPUT_MATCHED_SEGMENTS: None}

        if graphium.connect(selected_connection) is False:
            feedback.reportError('Cannot connect to Graphium', True)
            return {self.OUTPUT_MATCHED_SEGMENTS: None}

        feedback.pushInfo("Start Map-Matching task on Graphium server '" +
                          server_name + "' ...")
        response = graphium.do_map_matching(track_data, graph_name,
                                            graph_version, routing_mode)

        # Process map matching result
        if 'segments' in response:
            feedback.pushInfo('Finished map matching task!')
        elif 'error' in response:
            if 'msg' in response['error']:
                if response['error']['msg'] == 'ContentNotFoundError':
                    feedback.reportError(
                        'Graphium server "' + server_name +
                        '" does not support map matching', True)
                else:
                    feedback.reportError(response['error']['msg'], True)
            return {self.OUTPUT_MATCHED_SEGMENTS: None}
        elif 'exception' in response:
            feedback.reportError(response['exception'], True)
            return {self.OUTPUT_MATCHED_SEGMENTS: None}
        else:
            feedback.reportError('Unknown mapmatching error', True)
            return {self.OUTPUT_MATCHED_SEGMENTS: None}

        feedback.setCurrentStep(3)
        feedback.pushInfo("Prepare result vector layer ...")
        vector_layer = self.prepare_vector_layer('matched_track')

        (sink, dest_id) = self.parameterAsSink(parameters,
                                               self.OUTPUT_MATCHED_SEGMENTS,
                                               context, vector_layer.fields(),
                                               QgsWkbTypes.LineString,
                                               vector_layer.sourceCrs())

        total = 100.0 / len(response['segments'])
        for current, segment in enumerate(response['segments']):
            if feedback.isCanceled():
                break
            feature = QgsFeature()
            feature.setGeometry(QgsGeometry.fromWkt(segment['geometry']))
            feature.setFields(vector_layer.fields(), True)
            feature.setAttribute('order', current)
            for attribute_key in segment:
                try:
                    feature.setAttribute(attribute_key, segment[attribute_key])
                except KeyError:
                    pass
            sink.addFeature(feature, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        feedback.pushInfo("Finished preparing vector layer " + dest_id)
        return {
            self.OUTPUT_MATCHED_SEGMENTS:
            dest_id,
            self.OUTPUT_NR_OF_U_TURNS:
            response['nrOfUTurns'],
            self.OUTPUT_NR_OF_SHORTEST_PATH_SEARCHES:
            response['nrOfShortestPathSearches'],
            self.OUTPUT_LENGTH:
            response['length'],
            self.OUTPUT_MATCHED_FACTOR:
            response['matchedFactor'],
            self.OUTPUT_MATCHED_POINTS:
            response['matchedPoints'],
            self.OUTPUT_CERTAIN_PATH_END_SEGMENT_ID:
            response['certainPathEndSegmentId']
        }
Пример #10
0
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)

        source = self.parameterAsSource(parameters, self.INPUT, context)
        field_segment_id = self.parameterAsString(parameters, self.FIELD_SEGMENT_ID, context)
        segment_attribute_index = self.parameterAsInt(parameters, self.SEGMENT_ATTRIBUTE, context)
        segment_attribute = self.segment_attribute_options[segment_attribute_index]
        target_field = self.parameterAsString(parameters, self.TARGET_FIELD, context)

        server_name = self.connection_options[self.parameterAsInt(parameters, self.SERVER_NAME, context)]
        graph_name = self.parameterAsString(parameters, self.GRAPH_NAME, context)
        graph_version = self.parameterAsString(parameters, self.GRAPH_VERSION, context)

        feedback.pushInfo("Connect to Graphium server '" + server_name + "' ...")

        graphium = GraphiumGraphDataApi(feedback)
        selected_connection = self.connection_manager.select_graphium_server(server_name)

        if selected_connection is None:
            feedback.reportError('Cannot select connection to Graphium', True)
            return {self.OUTPUT: None}

        if graphium.connect(selected_connection) is False:
            feedback.reportError('Cannot connect to [' + server_name + ']', True)
            return {self.OUTPUT: None}

        feedback.pushInfo("Start downloading task on Graphium server '" + server_name + "' ...")

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

        # Read segment IDs
        segment_ids = []
        attributes_per_segment = dict()
        for current, feature in enumerate(source.getFeatures()):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            if not feature[field_segment_id]:
                continue

            if not feature[field_segment_id] in segment_ids:
                segment_ids.append(feature[field_segment_id])
            if len(segment_ids) > 50:
                self.get_segment_attributes(feedback, graphium, graph_name, graph_version, segment_attribute,
                                            segment_ids, attributes_per_segment)
            # Update the progress bar
            feedback.setProgress(int(current * total))
        if len(segment_ids) > 0:
            self.get_segment_attributes(feedback, graphium, graph_name, graph_version, segment_attribute,
                                        segment_ids, attributes_per_segment)

        feedback.setCurrentStep(1)
        feedback.pushInfo("Add attributes to features")

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(),
                                               source.wkbType(), source.sourceCrs())

        for current, feature in enumerate(source.getFeatures()):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            if feature[field_segment_id]:
                if int(feature[field_segment_id]) in attributes_per_segment:
                    feature[target_field] = attributes_per_segment[int(feature[field_segment_id])]
                else:
                    feedback.pushInfo("No attribute for segment " + str(feature[field_segment_id]))

            sink.addFeature(feature, QgsFeatureSink.FastInsert)

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

        feedback.setProgress(100)

        return {
            self.OUTPUT: dest_id
        }
    def processAlgorithm(self, parameters, context, model_feedback):

        # source: 'export as python script' in processing modeler
        feedback = QgsProcessingMultiStepFeedback(4, model_feedback)

        start_coordinate = self.parameterAsPoint(
            parameters, self.START_COORDINATE, context,
            QgsCoordinateReferenceSystem(4326))
        end_coordinate = self.parameterAsPoint(
            parameters, self.END_COORDINATE, context,
            QgsCoordinateReferenceSystem(4326))
        routing_mode = self.routing_mode_options[self.parameterAsInt(
            parameters, self.ROUTING_MODE, context)]
        routing_criteria = self.routing_criteria_options[self.parameterAsInt(
            parameters, self.ROUTING_CRITERIA, context)]
        # cut_segments = self.parameterAsBool(parameters, self.CUT_SEGMENTS, context)

        server_name = self.server_name_options[self.parameterAsInt(
            parameters, self.SERVER_NAME, context)]
        graph_name = self.parameterAsString(parameters, self.GRAPH_NAME,
                                            context)
        graph_version = self.parameterAsString(parameters, self.GRAPH_VERSION,
                                               context)

        # Connect to Graphium
        feedback.setCurrentStep(2)
        feedback.pushInfo("Connect to Graphium server '" + server_name +
                          "' ...")

        graphium = GraphiumUtilitiesApi(feedback)
        selected_connection = self.connection_manager.select_graphium_server(
            server_name)
        if selected_connection is None:
            feedback.reportError('Cannot select connection to Graphium', True)
            return {self.OUTPUT: None, self.OUTPUT_PATH: None}

        if graphium.connect(selected_connection) is False:
            feedback.reportError('Cannot connect to Graphium', True)
            return {self.OUTPUT: None, self.OUTPUT_PATH: None}

        feedback.pushInfo("Start Routing task on Graphium server '" +
                          server_name + "' ...")
        response = graphium.do_routing(graph_name, graph_version,
                                       start_coordinate.x(),
                                       start_coordinate.y(),
                                       end_coordinate.x(), end_coordinate.y(),
                                       datetime.today(), None, routing_mode,
                                       routing_criteria)

        # Process routing result
        if 'route' in response:
            if response['route']['length'] == 0:
                feedback.reportError('No route found', False)
                return {self.OUTPUT: None, self.OUTPUT_PATH: None}
        elif 'error' in response:
            if 'msg' in response['error']:
                if response['error']['msg'] == 'ContentNotFoundError':
                    feedback.reportError(
                        'Graphium server "' + server_name +
                        '" does not support routing', True)
                else:
                    feedback.reportError(response['error']['msg'], True)
            return {self.OUTPUT: None, self.OUTPUT_PATH: None}
        else:
            feedback.reportError('Unknown routing error', True)
            feedback.reportError(str(response), True)
            return {self.OUTPUT: None, self.OUTPUT_PATH: None}

        # create feature output
        feedback.setCurrentStep(3)
        vector_layer = self.prepare_vector_layer('route')

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, vector_layer.fields(),
                                               QgsWkbTypes.LineString,
                                               vector_layer.sourceCrs())
        if response['route']['geometry'] is not None:
            feature = QgsFeature()
            feature.setGeometry(
                QgsGeometry.fromWkt(response['route']['geometry']))
            feature.setFields(vector_layer.fields(), True)
            for attribute_key in response['route']:
                if feedback.isCanceled():
                    break
                try:
                    feature.setAttribute(attribute_key,
                                         response['route'][attribute_key])
                except KeyError:
                    pass
            sink.addFeature(feature, QgsFeatureSink.FastInsert)

        # create path output
        feedback.setCurrentStep(4)

        path_layer = self.prepare_path_layer('route_path')

        (sink_path,
         dest_id_path) = self.parameterAsSink(parameters, self.OUTPUT_PATH,
                                              context, path_layer.fields(),
                                              QgsWkbTypes.NoGeometry,
                                              vector_layer.sourceCrs())
        if response['route']['geometry'] is not None:
            total = 100.0 / len(response['route']['segments'])
            for current, path_segment in enumerate(
                    response['route']['segments']):
                if feedback.isCanceled():
                    break
                feature = QgsFeature()
                feature.setFields(path_layer.fields(), True)
                feature.setAttribute('order', current)
                feature.setAttribute('segment_id', path_segment['id'])
                feature.setAttribute('linkDirectionForward',
                                     path_segment['linkDirectionForward'])
                sink_path.addFeature(feature, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id, self.OUTPUT_PATH: dest_id_path}
Пример #12
0
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(4, model_feedback)
        outputs = {}
        self.doRenderer = False
        feedback.setProgressText(
            self.
            tr('Preprocessing input (fix geometries, explode lines and remove null geometries)'
               ))
        # Fix geometries
        alg_params = {
            'INPUT': parameters[self.INPUT],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['FixGeometries'] = processing.run('native:fixgeometries',
                                                  alg_params,
                                                  context=context,
                                                  feedback=feedback,
                                                  is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        # Explode lines
        alg_params = {
            'INPUT': outputs['FixGeometries']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['ExplodeLines'] = processing.run('native:explodelines',
                                                 alg_params,
                                                 context=context,
                                                 feedback=feedback,
                                                 is_child_algorithm=True)

        if feedback.isCanceled():
            return {}

        # Remove null geometries
        alg_params = {
            'INPUT': outputs['ExplodeLines']['OUTPUT'],
            'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
        }
        outputs['RemoveNullGeometries'] = processing.run(
            'native:removenullgeometries',
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True)

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

        source = self.parameterAsSource(outputs['RemoveNullGeometries'],
                                        'OUTPUT', context)
        fields = source.fields()

        cluster_field = self.parameterAsString(parameters, self.CLUSTER_FIELD,
                                               context)
        compatibility = self.parameterAsDouble(parameters, self.COMPATIBILITY,
                                               context)
        cycles = self.parameterAsInt(parameters, self.CYCLES, context)
        iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
        initial_step_size = self.parameterAsDouble(parameters,
                                                   self.INITIAL_STEP_SIZE,
                                                   context)
        max_distance = self.parameterAsDouble(parameters, self.MAX_DISTANCE,
                                              context)
        self.max_distance = max_distance
        weight_field = self.parameterAsString(parameters, self.WEIGHT_FIELD,
                                              context)
        weight_field_index = None
        if weight_field != '':
            weight_field_index = fields.lookupField(weight_field)

        # Create edge list
        features = source.getFeatures(QgsFeatureRequest())
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        edges = []
        for current, feat in enumerate(features):
            if feedback.isCanceled(): break
            edges.append(Edge(feat, weight_field_index))

        # Create clusters
        clusters = []
        if cluster_field != '':
            # Arrange edges in clusters according to cluster-id
            labels = []
            for edge in edges:
                if feedback.isCanceled(): return {}
                labels.append(edge[cluster_field])
            feedback.pushDebugInfo(cluster_field)
            for l in range(0, len(labels) + 1):
                if feedback.isCanceled(): return {}
                clusters.append(list())
            for i, label in enumerate(labels):
                if feedback.isCanceled(): return {}
                if label >= 0:
                    clusters[label].append(edges[i])
                else:
                    clusters.append([edges[i]])
            for i, cluster in enumerate(clusters):
                if feedback.isCanceled(): return {}
                clusters[i] = EdgeCluster(cluster, initial_step_size,
                                          iterations, cycles, compatibility)
        else:
            # If clustering should not be used, create only one big cluster containing all edges
            clusters = [
                EdgeCluster(edges, initial_step_size, iterations, cycles,
                            compatibility)
            ]
        fields.append(QgsField('CLUSTER', QVariant.Int))
        cluster_index = fields.lookupField('CLUSTER')
        if max_distance > 0:
            self.doRenderer = True
            fields.append(QgsField('PATH', QVariant.Int))
            fields.append(QgsField('OVERLAP_COUNT', QVariant.Int))
            overlap_index = fields.lookupField('OVERLAP_COUNT')

        (sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                    context, fields,
                                                    source.wkbType(),
                                                    source.sourceCrs())

        # Do edge-bundling (separately for all clusters)
        if max_distance == 0:
            feedback.setProgressText(
                self.tr('Compute Flow without merging lines'))
            for c, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                if cl.E > 1:
                    cl.force_directed_eb(feedback)
            feedback.setCurrentStep(3)
            for id, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                feedback.setProgress(100.0 * id / len(clusters))
                for e, edge in enumerate(cl.edges):
                    feat = QgsFeature()
                    feat.setGeometry(edge.geometry())
                    attr = edge.attributes()
                    attr.append(id)
                    feat.setAttributes(attr)
                    sink.addFeature(feat, QgsFeatureSink.FastInsert)
        else:
            feedback.setProgressText(
                self.tr('Compute Flow and try to merge lines'))
            for c, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                if cl.E > 1:
                    cl.force_directed_eb(feedback)
            feedback.setCurrentStep(3)
            for id, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                feedback.setProgressText(
                    "Segment lines for cluster {0}".format(id))
                cl.create_segments(weight_field_index, feedback)
                feedback.setProgressText(
                    "Collapse lines for cluster {0}".format(id))
                cl.collapse_lines(max_distance, feedback)
            fid = 0
            for id, cl in enumerate(clusters):
                if feedback.isCanceled(): return {}
                for e, edge in enumerate(cl.edges):
                    segments = cl.get_segments(edge)
                    for key, segment in segments.items():
                        feat = QgsFeature()
                        feat.setGeometry(segment.geometry())
                        attr = edge.attributes()
                        path_id = attr[0]
                        attr[0] = fid
                        attr.append(id)
                        attr.append(path_id)
                        attr.append(int(
                            segment.get_agg_weight()))  #Overlap count
                        feat.setAttributes(attr)
                        sink.addFeature(feat, QgsFeatureSink.FastInsert)
                        fid += 1

        return {self.OUTPUT: self.dest_id}
Пример #13
0
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD,
                                                  context)
        order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD,
                                                  context)
        date_format = self.parameterAsString(parameters, self.DATE_FORMAT,
                                             context)
        group_field_index = source.fields().lookupField(group_field_name)
        order_field_index = source.fields().lookupField(order_field_name)
        field_names = self.parameterAsFields(parameters, self.FIELDS, context)

        if group_field_index >= 0:
            group_field_def = source.fields().at(group_field_index)
        else:
            group_field_def = None
        order_field_def = source.fields().at(order_field_index)

        #Create output for lines
        fields = QgsFields()
        self.addFields(source, fields, 'start_order', field_names,
                       order_field_def)
        self.addFields(source, fields, 'end_order', field_names,
                       order_field_def)
        fields.append(QgsField('COUNT', QVariant.LongLong))

        output_wkb = QgsWkbTypes.LineString
        if QgsWkbTypes.hasM(source.wkbType()):
            output_wkb = QgsWkbTypes.addM(output_wkb)
        if QgsWkbTypes.hasZ(source.wkbType()):
            output_wkb = QgsWkbTypes.addZ(output_wkb)

        (self.sink,
         self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINE,
                                              context, fields, output_wkb,
                                              source.sourceCrs())
        if self.sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT_LINE))

        #Create output for Points
        fields_point = QgsFields()
        fields_point.append(QgsField("fid", QVariant.Int, "int", 9, 0))
        self.addFields(source, fields_point, 'end_order', field_names)
        fields_point.append(QgsField("COUNT", QVariant.LongLong))
        fields_point.append(QgsField("COUNT_IN", QVariant.LongLong))
        fields_point.append(QgsField("COUNT_OUT", QVariant.LongLong))

        (self.sink_point, self.dest_id_point) = self.parameterAsSink(
            parameters, self.OUTPUT_POINT, context, fields_point,
            source.wkbType(), source.sourceCrs(),
            QgsFeatureSink.RegeneratePrimaryKey)
        if self.sink_point is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT_POINT))

        #Compute the lines
        points = dict()
        features = source.getFeatures(
            QgsFeatureRequest(),
            QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled(): return {}

            if not f.hasGeometry(): continue

            point = f.geometry().asPoint()
            if group_field_index >= 0:
                group = f[group_field_index]
            else:
                group = 1
            order = f[order_field_index]
            if date_format != '':
                if isinstance(order, QDateTime):
                    pass
                else:
                    try:
                        order = datetime.strptime(str(order), date_format)
                    except ValueError as ve:
                        feedback.reportError(
                            self.tr('Invalid format {}').format(ve))
                        return {}
            data = [order, point]
            for indice in self.field_indices:
                data.append(f[indice])
            if group in points:
                points[group].append(data)
            else:
                points[group] = [data]

            feedback.setProgress(int(current * total))
        feedback.setCurrentStep(1)

        #Create the features
        current = 0
        total = 100.0 / len(points) if points else 1
        edge_ids = {}
        end_points = {}
        self.point_id = 0
        for group, vertices in points.items():
            if feedback.isCanceled(): return {}
            feedback.setProgress(int(current * total))
            # log("attrs: {}".format(vertices))
            vertices.sort(key=lambda x: (x[0] is None, x[0]))
            for i in range(len(vertices) - 1):
                if feedback.isCanceled(): return {}
                start_id = vertices[i][1].asWkt()
                end_id = vertices[i + 1][1].asWkt()
                edge_id = start_id + "-" + end_id

                if edge_id in edge_ids:
                    f = edge_ids[edge_id]
                    count_index = 2 * (len(self.field_indices) + 1)
                    count = f.attribute(count_index) + 1
                    f.setAttribute(count_index, count)
                else:
                    f = QgsFeature()
                    attrs = []
                    attrs.append(vertices[i][0])  #Add Order begin
                    for j in range(len(
                            self.field_indices)):  #Add Attrs for begin
                        attrs.append(
                            vertices[i][j + 2])  # +2 ignore order and point
                    attrs.append(vertices[i + 1][0])  #Add Order end
                    for j in range(0, len(
                            self.field_indices)):  #Add Attrs for end
                        attrs.append(
                            vertices[i + 1][j +
                                            2])  # +2 ignore order and point
                    attrs.append(1)  #Count = 1
                    f.setAttributes(attrs)
                    line = [vertices[i][1], vertices[i + 1][1]]
                    geom = QgsGeometry()
                    f.setGeometry(QgsGeometry(geom.fromPolylineXY(line)))
                    edge_ids[edge_id] = f

                self.updatePoints(start_id, end_points, vertices[i], 'start')
                self.updatePoints(end_id, end_points, vertices[i + 1], 'end')

                current += 1
                feedback.setProgress(int(current * total))
        for id in edge_ids:
            if feedback.isCanceled(): return {}
            self.sink.addFeature(edge_ids[id], QgsFeatureSink.FastInsert)
        for id in end_points:
            if feedback.isCanceled(): return {}
            self.sink_point.addFeature(end_points[id],
                                       QgsFeatureSink.FastInsert)

        return {self.OUTPUT_LINE: self.dest_id}
Пример #14
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        spatialRealtionsHandler = SpatialRealtionsHandler()
        algRunner = AlgRunner()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        if inputLyr is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        contourFieldName = self.parameterAsField(parameters, self.CONTOUR_ATTR, context)
        threshold = self.parameterAsDouble(parameters, self.TOLERANCE, context)
        topology_radius = self.parameterAsDouble(parameters, self.TOPOLOGY_RADIUS, context)
        refLyr = self.parameterAsVectorLayer(parameters, self.REFERENCE_LYR, context)
        self.prepareFlagSink(parameters, inputLyr, QgsWkbTypes.Polygon, context)

        #1. Get all lines into one line lyr
        currentStep = 0
        if refLyr is not None:
            multiStepFeedback = QgsProcessingMultiStepFeedback(4, feedback)
            multiStepFeedback.setCurrentStep(currentStep)
            multiStepFeedback.pushInfo(self.tr('Identifying dangles...'))
            dangles = algRunner.runIdentifyDangles(
                inputLayer=inputLayer,
                searchRadius=topology_radius,
                context=context,
                onlySelected=onlySelected,
                polygonFilter=refLyr,
                feedback=multiStepFeedback
            )
            currentStep += 1
            #2. Snap frame to dangles
            multiStepFeedback.setCurrentStep(currentStep)
            multiStepFeedback.pushInfo(self.tr('Adjusting frame lyr...'))
            snappedFrame = algRunner.runSnapGeometriesToLayer(
                inputLayer=inputLyr,
                referenceLayer=dangles,
                tol=topology_radius,
                context=context
                feedback=multiStepFeedback
            )
            currentStep += 1
        else:
            multiStepFeedback = QgsProcessingMultiStepFeedback(2, feedback)

        #3. Validate contour lines
        multiStepFeedback.setCurrentStep(currentStep)
        multiStepFeedback.pushInfo(self.tr('Validating contour lines...'))
        invalidDict = spatialRealtionsHandler.validateContourLines(
            contourLyr=inputLyr,
            contourAttrName=contourFieldName,
            refLyr=refLyr,
            feedback=multiStepFeedback
        )
        currentStep+=1
        multiStepFeedback.setCurrentStep(currentStep)
        multiStepFeedback.pushInfo(self.tr('Raising flags...'))
        nFlags = len(invalidDict)
        step = 100/nFlags if nFlags else 0
        for current, (geom, text) in enumerate(invalidDict.items()):
            self.flagFeature(geom, text, fromWkb=True)
            multiStepFeedback.setProgress(step * current)
            
        return {self.FLAGS: self.flag_id}
Пример #15
0
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)
        source = self.parameterAsSource(parameters, self.INPUT, context)
        field_segment_id = self.parameterAsString(parameters,
                                                  self.FIELD_SEGMENT_ID,
                                                  context)

        server_name = self.connection_options[self.parameterAsInt(
            parameters, self.SERVER_NAME, context)]
        graph_name = self.parameterAsString(parameters, self.GRAPH_NAME,
                                            context)
        graph_version = self.parameterAsString(parameters, self.GRAPH_VERSION,
                                               context)

        # Connect to Graphium
        feedback.pushInfo("Connect to Graphium server '" + server_name +
                          "' ...")

        graphium = GraphiumGraphDataApi(feedback)
        selected_connection = self.connection_manager.select_graphium_server(
            server_name)

        if selected_connection is None:
            feedback.reportError('Cannot select connection to Graphium', True)
            return {self.OUTPUT_SEGMENTS: None}

        if graphium.connect(selected_connection) is False:
            feedback.reportError('Cannot connect to Graphium', True)
            return {self.OUTPUT_SEGMENTS: None}

        feedback.pushInfo("Start downloading task on Graphium server '" +
                          server_name + "' ...")

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

        segments_with_geometry = 0

        # Read segment IDs
        segment_ids = []
        segment_geometries = dict()
        for current, feature in enumerate(source.getFeatures()):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            segment_ids.append(feature[field_segment_id])
            if len(segment_ids) > 50:
                self.get_segment_geometries(feedback, graphium, graph_name,
                                            graph_version, segment_ids,
                                            segment_geometries)
            # Update the progress bar
            feedback.setProgress(int(current * total))
        if len(segment_ids) > 0:
            self.get_segment_geometries(feedback, graphium, graph_name,
                                        graph_version, segment_ids,
                                        segment_geometries)

        feedback.setCurrentStep(1)
        feedback.pushInfo("Add geometries to segments")

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUTPUT_SEGMENTS, context, source.fields(),
            QgsWkbTypes.LineString, QgsCoordinateReferenceSystem('EPSG:4326'))

        for current, feature in enumerate(source.getFeatures()):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            if int(feature[field_segment_id]) in segment_geometries:
                feature.setGeometry(segment_geometries[int(
                    feature[field_segment_id])])
                segments_with_geometry += 1
            else:
                pass
                # feedback.pushInfo("No geometry for segment " + str(feature[field_segment_id]))

            sink.addFeature(feature, QgsFeatureSink.FastInsert)

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

        feedback.setProgress(100)

        return {
            self.OUTPUT_SEGMENTS:
            dest_id,
            self.OUTPUT_SEGMENT_COUNT:
            source.featureCount() if source.featureCount() else 0,
            self.OUTPUT_SEGMENT_WITH_GEOMETRY_COUNT:
            segments_with_geometry
        }
Пример #16
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        self.layerHandler = LayerHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        searchRadius = self.parameterAsDouble(parameters, self.TOLERANCE,
                                              context)
        lineFilterLyrList = self.parameterAsLayerList(parameters,
                                                      self.LINEFILTERLAYERS,
                                                      context)
        polygonFilterLyrList = self.parameterAsLayerList(
            parameters, self.POLYGONFILTERLAYERS, context)
        ignoreNotSplit = self.parameterAsBool(parameters, self.TYPE, context)
        ignoreInner = self.parameterAsBool(parameters, self.IGNOREINNER,
                                           context)
        self.prepareFlagSink(parameters, inputLyr, QgsWkbTypes.Point, context)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        feedbackTotal = 3
        feedbackTotal += 1 if lineFilterLyrList or polygonFilterLyrList else 0
        feedbackTotal += 1 if not ignoreInner else 0
        multiStep = QgsProcessingMultiStepFeedback(feedbackTotal, feedback)
        currentStep = 0
        multiStep.setCurrentStep(currentStep)
        multiStep.pushInfo(self.tr('Building search structure...'))
        endVerticesDict = self.layerHandler.buildInitialAndEndPointDict(
            inputLyr, onlySelected=onlySelected, feedback=multiStep)

        #search for dangles candidates
        currentStep += 1
        multiStep.setCurrentStep(currentStep)
        multiStep.pushInfo(self.tr('Looking for dangles...'))
        pointList = self.searchDanglesOnPointDict(endVerticesDict, multiStep)
        #build filter layer
        currentStep += 1
        multiStep.setCurrentStep(currentStep)
        multiStep.pushInfo(self.tr('Filtering dangles candidates...'))
        filterLayer = self.buildFilterLayer(lineFilterLyrList,
                                            polygonFilterLyrList,
                                            context,
                                            multiStep,
                                            onlySelected=onlySelected)
        #filter pointList with filterLayer

        if filterLayer:
            currentStep += 1
            multiStep.setCurrentStep(currentStep)
            multiStep.pushInfo(
                self.tr('Filtering dangles candidates with filter...'))
            filteredPointList = self.filterPointListWithFilterLayer(
                pointList, filterLayer, searchRadius, multiStep)
        else:
            filteredPointList = pointList
        #filter with own layer
        if not ignoreInner:  #True when looking for dangles on contour lines
            currentStep += 1
            multiStep.setCurrentStep(currentStep)
            multiStep.pushInfo(self.tr('Filtering inner dangles...'))
            filteredPointList = self.filterPointListWithFilterLayer(
                filteredPointList,
                inputLyr,
                searchRadius,
                multiStep,
                isRefLyr=True,
                ignoreNotSplit=ignoreNotSplit)
        #build flag list with filtered points
        currentStep += 1
        multiStep.setCurrentStep(currentStep)
        multiStep.pushInfo(self.tr('Raising flags...'))
        if filteredPointList:
            # currentValue = feedback.progress()
            currentTotal = 100 / len(filteredPointList)
            for current, point in enumerate(filteredPointList):
                if multiStep.isCanceled():
                    break
                self.flagFeature(
                    QgsGeometry.fromPointXY(point),
                    self.tr('Dangle on {0}').format(inputLyr.name()))
                multiStep.setProgress(current * currentTotal)
        # feedback.setProgress(100)
        return {self.FLAGS: self.flag_id}
Пример #17
0
    def processAlgorithm(self, parameters, context, model_feedback):
        feedback = QgsProcessingMultiStepFeedback(2, model_feedback)

        server_name = self.connection_options[self.parameterAsInt(parameters, self.SERVER_NAME, context)]
        graph_name = self.parameterAsString(parameters, self.GRAPH_NAME, context)
        graph_version = self.parameterAsString(parameters, self.GRAPH_VERSION, context)
        save_json_file = self.parameterAsBoolean(parameters, self.SAVE_JSON_FILE, context)
        json_file = self.parameterAsFileOutput(parameters, self.OUTPUT_JSON, context)

        # Connect to Graphium
        feedback.pushInfo("Connect to Graphium server '" + server_name + "' ...")

        graphium_data = GraphiumGraphDataApi(feedback)
        graphium_management = GraphiumGraphManagementApi(feedback)
        selected_connection = self.connection_manager.select_graphium_server(server_name)

        if selected_connection is None:
            feedback.reportError('Cannot select connection to Graphium', True)
            return {self.OUTPUT_SEGMENTS: None}

        if graphium_management.connect(selected_connection) is False:
            feedback.reportError('Cannot connect to Graphium', True)
            return {self.OUTPUT_SEGMENTS: None}
        if graphium_data.connect(selected_connection) is False:
            feedback.reportError('Cannot connect to Graphium', True)
            return {self.OUTPUT_SEGMENTS: None}

        metadata = graphium_management.get_graph_version_metadata(graph_name, graph_version)

        if not metadata['type']:
            feedback.reportError('Cannot correctly retrieve graph metadata', True)
            return {self.OUTPUT_SEGMENTS: None}

        feedback.pushInfo("Start downloading task on Graphium server '" + server_name + "' ...")
        response = graphium_data.export_graph(graph_name, graph_version, metadata.get('type') == 'hdwaysegment')

        if save_json_file:
            feedback.pushInfo("Write graph to JSON file...")
            with open(json_file, 'w') as output_file:
                output_file.write(json.dumps(response))

        feedback.setCurrentStep(1)
        if 'graphVersionMetadata' in response:
            # if response['graphVersionMetadata']['segmentsCount'] == 0:
            #     feedback.reportError('No segments available', False)
            #     return {self.OUTPUT_SEGMENT_COUNT: 0}
            # elif response['graphVersionMetadata']['state'] == 'DELETED':
            if response['graphVersionMetadata']['state'] == 'DELETED':
                feedback.reportError('Graph version has been deleted', False)
                return {self.OUTPUT_SEGMENT_COUNT: 0}
        elif 'error' in response:
            if 'msg' in response['error']:
                feedback.reportError(response['error']['msg'], True)
            return {self.OUTPUT_SEGMENT_COUNT: 0}
        else:
            feedback.reportError('Unknown error', True)
            return {self.OUTPUT_SEGMENT_COUNT: 0}

        feedback.pushInfo("Prepare result vector layer ...")
        vector_layer = self.prepare_vector_layer('segments_' + graph_name + '_' + graph_version,
                                                 response['graphVersionMetadata']['type'])

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_SEGMENTS, context, vector_layer.fields(),
                                               QgsWkbTypes.LineString, vector_layer.sourceCrs())

        total = 100.0 / len(response[response['graphVersionMetadata']['type']])
        for current, segment in enumerate(response[response['graphVersionMetadata']['type']]):
            if feedback.isCanceled():
                break
            feature = QgsFeature()
            feature.setGeometry(QgsGeometry.fromWkt(segment['geometry']))
            feature.setFields(vector_layer.fields(), True)
            for attribute_key in segment:
                try:
                    if attribute_key == 'tags' or attribute_key == 'connection':
                        feature.setAttribute(attribute_key, json.dumps(segment[attribute_key]))
                    else:
                        feature.setAttribute(attribute_key, segment[attribute_key])
                except KeyError:
                    pass
            sink.addFeature(feature, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        feedback.pushInfo("Finished preparing vector layer " + dest_id)
        return {self.OUTPUT_SEGMENTS: dest_id,
                self.OUTPUT_JSON: json_file if save_json_file else None,
                self.OUTPUT_SEGMENT_COUNT: response['graphVersionMetadata']['segmentsCount']
                }