Exemple #1
0
 def testUpperCase(self):
     """ test uppercase """
     self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.AllUppercase))
     self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.AllUppercase), '')
     self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.AllUppercase), 'TESTING 123')
     self.assertEqual(QgsStringUtils.capitalize('    tESTinG abc    ', QgsStringUtils.AllUppercase), '    TESTING ABC    ')
     self.assertEqual(QgsStringUtils.capitalize('    TESTING ABC', QgsStringUtils.AllUppercase), '    TESTING ABC')
Exemple #2
0
 def testMixed(self):
     """ test mixed capitalization - ie, no change! """
     self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.MixedCase))
     self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.MixedCase), '')
     self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.MixedCase), 'testing 123')
     self.assertEqual(QgsStringUtils.capitalize('    tESTinG 123    ', QgsStringUtils.MixedCase), '    tESTinG 123    ')
     self.assertEqual(QgsStringUtils.capitalize('    TESTING ABC', QgsStringUtils.MixedCase), '    TESTING ABC')
Exemple #3
0
def addAlgorithmEntry(alg, menuName, submenuName, actionText=None, icon=None, addButton=False):
    if actionText is None:
        if (QgsGui.higFlags() & QgsGui.HigMenuTextIsTitleCase) and not (alg.flags() & QgsProcessingAlgorithm.FlagDisplayNameIsLiteral):
            alg_title = QgsStringUtils.capitalize(alg.displayName(), QgsStringUtils.TitleCase)
        else:
            alg_title = alg.displayName()
        actionText = alg_title + QCoreApplication.translate('Processing', '…')
    action = QAction(icon or alg.icon(), actionText, iface.mainWindow())
    alg_id = alg.id()
    action.setData(alg_id)
    action.triggered.connect(lambda: _executeAlgorithm(alg_id))
    action.setObjectName("mProcessingUserMenu_%s" % alg_id)

    if menuName:
        menu = getMenu(menuName, iface.mainWindow().menuBar())
        submenu = getMenu(submenuName, menu)
        submenu.addAction(action)

    if addButton:
        global algorithmsToolbar
        if algorithmsToolbar is None:
            algorithmsToolbar = iface.addToolBar(QCoreApplication.translate('MainWindow', 'Processing Algorithms'))
            algorithmsToolbar.setObjectName("ProcessingAlgorithms")
            algorithmsToolbar.setToolTip(QCoreApplication.translate('MainWindow', 'Processing Algorithms Toolbar'))
        algorithmsToolbar.addAction(action)
Exemple #4
0
 def testLowerCase(self):
     """ test lowercase """
     self.assertFalse(
         QgsStringUtils.capitalize(None, QgsStringUtils.AllLowercase))
     self.assertEqual(
         QgsStringUtils.capitalize('', QgsStringUtils.AllLowercase), '')
     self.assertEqual(
         QgsStringUtils.capitalize('testing 123',
                                   QgsStringUtils.AllLowercase),
         'testing 123')
     self.assertEqual(
         QgsStringUtils.capitalize('    tESTinG abc    ',
                                   QgsStringUtils.AllLowercase),
         '    testing abc    ')
     self.assertEqual(
         QgsStringUtils.capitalize('    TESTING ABC',
                                   QgsStringUtils.AllLowercase),
         '    testing abc')
Exemple #5
0
 def testCapitalizeFirst(self):
     """ test capitalize first """
     self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.ForceFirstLetterToCapital))
     self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.ForceFirstLetterToCapital), '')
     self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.ForceFirstLetterToCapital), 'Testing 123')
     self.assertEqual(QgsStringUtils.capitalize('testing', QgsStringUtils.ForceFirstLetterToCapital),
                      'Testing')
     self.assertEqual(QgsStringUtils.capitalize('Testing', QgsStringUtils.ForceFirstLetterToCapital),
                      'Testing')
     self.assertEqual(QgsStringUtils.capitalize('TESTING', QgsStringUtils.ForceFirstLetterToCapital),
                      'TESTING')
     self.assertEqual(QgsStringUtils.capitalize('    tESTinG abc    ', QgsStringUtils.ForceFirstLetterToCapital),
                      '    TESTinG Abc    ')
     self.assertEqual(QgsStringUtils.capitalize('    TESTING ABC', QgsStringUtils.ForceFirstLetterToCapital), '    TESTING ABC')
     self.assertEqual(QgsStringUtils.capitalize('    testing abc', QgsStringUtils.ForceFirstLetterToCapital),
                      '    Testing Abc')
 def testCapitalizeFirst(self):
     """ test capitalize first """
     self.assertFalse(QgsStringUtils.capitalize(None, QgsStringUtils.ForceFirstLetterToCapital))
     self.assertEqual(QgsStringUtils.capitalize('', QgsStringUtils.ForceFirstLetterToCapital), '')
     self.assertEqual(QgsStringUtils.capitalize('testing 123', QgsStringUtils.ForceFirstLetterToCapital), 'Testing 123')
     self.assertEqual(QgsStringUtils.capitalize('testing', QgsStringUtils.ForceFirstLetterToCapital),
                      'Testing')
     self.assertEqual(QgsStringUtils.capitalize('Testing', QgsStringUtils.ForceFirstLetterToCapital),
                      'Testing')
     self.assertEqual(QgsStringUtils.capitalize('TESTING', QgsStringUtils.ForceFirstLetterToCapital),
                      'TESTING')
     self.assertEqual(QgsStringUtils.capitalize('    tESTinG abc    ', QgsStringUtils.ForceFirstLetterToCapital),
                      '    TESTinG Abc    ')
     self.assertEqual(QgsStringUtils.capitalize('    TESTING ABC', QgsStringUtils.ForceFirstLetterToCapital), '    TESTING ABC')
     self.assertEqual(QgsStringUtils.capitalize('    testing abc', QgsStringUtils.ForceFirstLetterToCapital),
                      '    Testing Abc')
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry/current layer is not thread safe

        if iface.activeLayer() is None or iface.activeLayer().type(
        ) != QgsMapLayerType.VectorLayer:
            return

        for a in QgsApplication.processingRegistry().algorithms():
            if not a.flags() & QgsProcessingAlgorithm.FlagSupportsInPlaceEdits:
                continue

            if not a.supportInPlaceEdit(iface.activeLayer()):
                continue

            result = QgsLocatorResult()
            result.filter = self
            result.displayString = a.displayName()
            result.icon = a.icon()
            result.userData = a.id()
            result.score = 0

            if (context.usingPrefix and not string):
                self.resultFetched.emit(result)

            if not string:
                return

            string = string.lower()
            tagScore = 0
            tags = [*a.tags(), a.provider().name()]
            if a.group():
                tags.append(a.group())

            for t in tags:
                if string in t.lower():
                    tagScore = 1
                    break

            result.score = QgsStringUtils.fuzzyScore(
                result.displayString, string) * 0.5 + tagScore * 0.5

            if result.score > 0:
                self.resultFetched.emit(result)
Exemple #8
0
def addAlgorithmEntry(alg, menuName, submenuName, actionText=None, icon=None, addButton=False):
    if actionText is None:
        actionText = QgsStringUtils.capitalize(alg.displayName(), QgsStringUtils.TitleCase) + QCoreApplication.translate('Processing', '…')
    action = QAction(icon or alg.icon(), actionText, iface.mainWindow())
    action.setData(alg.id())
    action.triggered.connect(lambda: _executeAlgorithm(alg))
    action.setObjectName("mProcessingUserMenu_%s" % alg.id())

    if menuName:
        menu = getMenu(menuName, iface.mainWindow().menuBar())
        submenu = getMenu(submenuName, menu)
        submenu.addAction(action)

    if addButton:
        global algorithmsToolbar
        if algorithmsToolbar is None:
            algorithmsToolbar = iface.addToolBar(QCoreApplication.translate('MainWindow', 'Processing Algorithms'))
            algorithmsToolbar.setToolTip(QCoreApplication.translate('MainWindow', 'Processing Algorithms Toolbar'))
        algorithmsToolbar.addAction(action)
Exemple #9
0
def addAlgorithmEntry(alg, menuName, submenuName, actionText=None, icon=None, addButton=False):
    if actionText is None:
        actionText = QgsStringUtils.capitalize(alg.displayName(), QgsStringUtils.TitleCase) + QCoreApplication.translate('Processing', '…')
    action = QAction(icon or alg.icon(), actionText, iface.mainWindow())
    action.setData(alg.id())
    action.triggered.connect(lambda: _executeAlgorithm(alg))
    action.setObjectName("mProcessingUserMenu_%s" % alg.id())

    if menuName:
        menu = getMenu(menuName, iface.mainWindow().menuBar())
        submenu = getMenu(submenuName, menu)
        submenu.addAction(action)

    if addButton:
        global algorithmsToolbar
        if algorithmsToolbar is None:
            algorithmsToolbar = iface.addToolBar(QCoreApplication.translate('MainWindow', 'Processing Algorithms'))
            algorithmsToolbar.setToolTip(QCoreApplication.translate('MainWindow', 'Processing Algorithms Toolbar'))
        algorithmsToolbar.addAction(action)
Exemple #10
0
    def search(self, search_term):
        if not search_term or search_term.isspace():
            self.last_search_result = 100
            return 100

        ret_val = 0

        # give more weight if exact search term occurs in title or description
        if search_term.lower() in self.__title.lower():
            ret_val += 10
        if search_term.lower() in self.description.lower():
            ret_val += 5

        for search_token in search_term.split():
            for title_token in self.title.split():
                if QgsStringUtils.levenshteinDistance(title_token, search_token, False) < 2:
                    ret_val += 1
        # always put custom instances first
        if self.is_custom:
            ret_val *= 100
        self.last_search_result = ret_val
        return ret_val
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry is not thread safe
        for a in QgsApplication.processingRegistry().algorithms():
            if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
                continue
            if not ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES) and \
                    a.flags() & QgsProcessingAlgorithm.FlagKnownIssues:
                continue

            result = QgsLocatorResult()
            result.filter = self
            result.displayString = a.displayName()
            result.icon = a.icon()
            result.userData = a.id()
            result.score = 0

            if (context.usingPrefix and not string):
                self.resultFetched.emit(result)

            if not string:
                return

            string = string.lower()
            tagScore = 0
            tags = [*a.tags(), a.provider().name()]
            if a.group():
                tags.append(a.group())

            for t in tags:
                if string in t.lower():
                    tagScore = 1
                    break

            result.score = QgsStringUtils.fuzzyScore(
                result.displayString, string) * 0.5 + tagScore * 0.5

            if result.score > 0:
                self.resultFetched.emit(result)
Exemple #12
0
def addAlgorithmEntry(alg,
                      menuName,
                      submenuName,
                      object_name,
                      actionText=None,
                      icon=None,
                      addButton=False):
    if actionText is None:
        if (QgsGui.higFlags() & QgsGui.HigMenuTextIsTitleCase) and not (
                alg.flags() & QgsProcessingAlgorithm.FlagDisplayNameIsLiteral):
            alg_title = QgsStringUtils.capitalize(alg.displayName(),
                                                  QgsStringUtils.TitleCase)
        else:
            alg_title = alg.displayName()
        actionText = alg_title + QCoreApplication.translate('Processing', '…')
    action = QAction(icon or alg.icon(), actionText, iface.mainWindow())
    alg_id = alg.id()
    action.setData(alg_id)
    action.triggered.connect(lambda: _executeAlgorithm(alg_id))
    action.setObjectName("mProcessingUserMenu_%s" % alg_id)

    if menuName:
        menu = getMenu(menuName, iface.mainWindow().menuBar())
        submenu = getMenu(submenuName, menu)
        submenu.setObjectName(object_name)
        submenu.addAction(action)

    if addButton:
        global algorithmsToolbar
        if algorithmsToolbar is None:
            algorithmsToolbar = iface.addToolBar(
                QCoreApplication.translate('MainWindow',
                                           'Processing Algorithms'))
            algorithmsToolbar.setObjectName("ProcessingAlgorithms")
            algorithmsToolbar.setToolTip(
                QCoreApplication.translate('MainWindow',
                                           'Processing Algorithms Toolbar'))
        algorithmsToolbar.addAction(action)
Exemple #13
0
    def processAlgorithm(self, parameters, context, feedback):
        # Get Parameters and assign to variable to work with
        layer = self.parameterAsLayer(parameters, self.SOURCE_LYR, context)
        field = self.parameterAsString(parameters, self.SOURCE_FIELD, context)
        maxdist = self.parameterAsDouble(parameters, self.MAX_DISTANCE,
                                         context)
        th_levenshtein = self.parameterAsInt(parameters,
                                             self.THRESHOLD_LEVENSHTEIN,
                                             context)
        th_substring = self.parameterAsInt(parameters,
                                           self.THRESHOLD_SUBSTRING, context)
        th_hamming = self.parameterAsInt(parameters, self.THRESHOLD_HAMMING,
                                         context)
        alg = self.parameterAsEnums(parameters, self.ALGORITHM, context)
        ao = self.parameterAsInt(parameters, self.ANDORALG, context)
        op = self.parameterAsString(parameters, self.OPERATOR, context)

        total = 100.0 / layer.featureCount() if layer.featureCount(
        ) else 0  # Initialize progress for progressbar

        layer.removeSelection()  # clear selection before every run
        #totalfeatcount = layer.featureCount()

        for current, feat in enumerate(
                layer.getFeatures()):  # iterate over source
            s = None  # reset selection indicator
            s0 = None
            s1 = None
            s2 = None
            s3 = None
            s4 = None
            th_levenshtein_new = th_levenshtein
            th_substring_new = th_substring
            th_hamming_new = th_hamming
            if feat[field] is not None and len(str(
                    feat[field])) > 0:  # only compare if field is not empty
                # recalc thresholds based on current attribute values
                th_levenshtein_new = th_levenshtein_new
                if th_levenshtein_new < 0:  # set to 0 if it would be negative
                    th_levenshtein_new = 0
                th_substring_new = len(str(feat[field])) - th_substring
                if th_substring_new < 0:  # set to 0 if it would be negative
                    th_substring_new = 0
                th_hamming_new = len(str(feat[field])) - th_hamming
                if th_hamming_new < 0:  # set to 0 if it would be negative
                    th_hamming_new = 0
                for lookupnr in range(
                        1, feat.id(), 1
                ):  # only compare to previous features, because we do not want to select the first feature of each duplicate group
                    lookup = layer.getFeature(
                        lookupnr)  # get the lookup-feature
                    if lookup[field] is not None and len(
                            str(lookup[field]
                                )) > 0:  # only compare if field is not empty
                        if feat.geometry().centroid().distance(
                                lookup.geometry().centroid()
                        ) <= maxdist:  # only select if within given maxdistance
                            if 0 in alg:  # Exact Duplicates
                                if feat[field] == lookup[field]:
                                    s0 = 1
                                else:
                                    s0 = 0
                            if 1 in alg:  # Soundex
                                if QgsStringUtils.soundex(
                                        str(feat[field]
                                            )) == QgsStringUtils.soundex(
                                                str(lookup[field])):
                                    s1 = 1
                                else:
                                    s1 = 0
                            if 2 in alg:  # Levenshtein
                                if QgsStringUtils.levenshteinDistance(
                                        str(feat[field]), str(lookup[field])
                                ) < th_levenshtein_new:
                                    s2 = 1
                                else:
                                    s2 = 0
                            if 3 in alg:  # Longest Common Substring
                                if len(
                                        QgsStringUtils.longestCommonSubstring(
                                            str(feat[field]), str(
                                                lookup[field]))
                                ) > th_substring_new:
                                    s3 = 1
                                else:
                                    s3 = 0
                            if 4 in alg:  # Hamming Distance:
                                if QgsStringUtils.hammingDistance(
                                        str(feat[field]), str(
                                            lookup[field])) > th_hamming_new:
                                    s4 = 1
                                else:
                                    s4 = 0

                            if ao == 0:  # All chosen algorithms need to match
                                if 0 in (
                                        s0, s1, s2, s3, s4
                                ):  # Dont select current feature if at least one used algorithm returned 0
                                    s = 0
                                else:  # Select current feature if all algorithms returned 1 or None
                                    s = 1
                            elif ao == 1:  # Only at least one algorithm needs to match
                                if 1 in (
                                        s0, s1, s2, s3, s4
                                ):  # Select current feature if at least one used algorithm returned 1
                                    s = 1
                                else:  # Dont select current feature if no used algorithm returned 1
                                    s = 0

                            if s == 1:  # select the current feature if indicator is true
                                layer.select(feat.id())

                if feedback.isCanceled(
                ):  # Cancel algorithm if button is pressed
                    break
            feedback.setProgress(int(current *
                                     total))  # Set Progress in Progressbar

        return {
            self.OUTPUT: parameters[self.SOURCE_LYR]
        }  # Return result of algorithm
Exemple #14
0
 def testfuzzyScore(self):
     self.assertEqual(QgsStringUtils.fuzzyScore('', ''), 0)
     self.assertEqual(QgsStringUtils.fuzzyScore('foo', ''), 0)
     self.assertEqual(QgsStringUtils.fuzzyScore('', 'foo'), 0)
     self.assertEqual(QgsStringUtils.fuzzyScore('foo', 'foo'), 1)
     self.assertEqual(QgsStringUtils.fuzzyScore('bar', 'foo'), 0)
     self.assertEqual(QgsStringUtils.fuzzyScore('FOO', 'foo'), 1)
     self.assertEqual(QgsStringUtils.fuzzyScore('foo', 'FOO'), 1)
     self.assertEqual(QgsStringUtils.fuzzyScore('   foo   ', 'foo'), 1)
     self.assertEqual(QgsStringUtils.fuzzyScore('foo', '   foo   '), 1)
     self.assertEqual(QgsStringUtils.fuzzyScore('foo', '   foo   '), 1)
     self.assertEqual(QgsStringUtils.fuzzyScore('foo_bar', 'foo bar'), 1)
     self.assertGreater(QgsStringUtils.fuzzyScore('foo bar', 'foo'), 0)
     self.assertGreater(QgsStringUtils.fuzzyScore('foo bar', 'fooba'), 0)
     self.assertGreater(QgsStringUtils.fuzzyScore('foo_bar', 'ob'), 0)
     self.assertGreater(QgsStringUtils.fuzzyScore('foo bar', 'foobar'), 0)
     self.assertGreater(QgsStringUtils.fuzzyScore('foo bar', 'foo_bar'), 0)
     self.assertGreater(QgsStringUtils.fuzzyScore('foo_bar', 'foo bar'), 0)
     self.assertEqual(QgsStringUtils.fuzzyScore('foo bar', 'foobar'),
                      QgsStringUtils.fuzzyScore('foo_bar', 'foobar'))
     self.assertEqual(QgsStringUtils.fuzzyScore('foo bar', 'foo_bar'),
                      QgsStringUtils.fuzzyScore('foo_bar', 'foo_bar'))
     self.assertEqual(QgsStringUtils.fuzzyScore('foo bar', 'foo bar'),
                      QgsStringUtils.fuzzyScore('foo_bar', 'foo bar'))
     # note the accent
     self.assertEqual(QgsStringUtils.fuzzyScore('foo_bér', 'foober'),
                      QgsStringUtils.fuzzyScore('foo_ber', 'foobér'))
     self.assertGreater(
         QgsStringUtils.fuzzyScore('abcd efg hig', 'abcd hig'),
         QgsStringUtils.fuzzyScore('abcd efg hig', 'abcd e h'))
     #  full words are preferred, even though the same number of characters used
     self.assertGreater(
         QgsStringUtils.fuzzyScore('abcd efg hig', 'abcd hig'),
         QgsStringUtils.fuzzyScore('abcd efg hig', 'abcd e hi'))
Exemple #15
0
    def processAlgorithm(self, parameters, context, feedback):
        line_source = self.parameterAsSource(parameters, self.LINES, context)
        if line_source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.LINES))

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

        distance = self.parameterAsDouble(parameters, self.DIST, context)
        field_rn_line = self.parameterAsString(parameters,
                                               self.LINES_ROAD_NAMES, context)
        field_rn_point = self.parameterAsString(parameters,
                                                self.POINTS_ROAD_NAMES,
                                                context)
        if field_rn_line:
            feedback.pushInfo(
                'Calculation with Levenshtein matching between \'{}\' (lines) and \'{}\' (points)'
                .format(field_rn_line, field_rn_point))
            field_rn_line_index = line_source.fields().lookupField(
                field_rn_line)
            if field_rn_point is None:
                raise QgsProcessingException(
                    self.invalidSourceError(parameters,
                                            self.POINTS_ROAD_NAMES))
        if field_rn_point:
            field_rn_point_index = point_source.fields().lookupField(
                field_rn_point)
            # raise QgsProcessingException(self.invalidSourceError(parameters, self.POINTS_ROAD_NAMES))

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

        fields = line_source.fields()
        fields.append(QgsField(field_name, QVariant.LongLong))
        field_count_index = fields.lookupField(field_name)
        if fields.lookupField('fid') < 0:
            fields.append(QgsField('fid', QVariant.Int))
        field_id_index = fields.lookupField('fid')

        fields_point = QgsFields()
        fields_point.append(QgsField("fid", QVariant.Int, "int", 9, 0))
        fields_point.append(QgsField("line_id", QVariant.Int, "int", 9, 0))
        fields_point.append(QgsField(self.field_name, QVariant.LongLong))
        field_point_count_index = fields_point.lookupField(field_name)
        field_point_id_index = fields_point.lookupField('fid')
        field_point_lid_index = fields_point.lookupField('line_id')
        if field_rn_point:
            fields_point.append(QgsField(field_rn_point, QVariant.String))
            field_point_rname_index = fields_point.lookupField(field_rn_point)
            fields_point.append(
                QgsField(field_rn_point + "_levenshtein", QVariant.String))
            field_point_rname_clean_index = fields_point.lookupField(
                field_rn_point + "_levenshtein")

        (self.sink, self.dest_id) = self.parameterAsSink(
            parameters,
            self.OUTPUT_LINE, context, fields, line_source.wkbType(),
            line_source.sourceCrs(), QgsFeatureSink.RegeneratePrimaryKey)
        if self.sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT_LINE))

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

        #Calculate Proportional Symbol Map
        features = point_source.getFeatures()
        total = 100.0 / point_source.featureCount(
        ) if point_source.featureCount() else 0
        feedback.setProgressText(
            self.tr('Create a Proportional Symbols Map with points'))
        points = {}
        for current, point_feature in enumerate(features):
            if feedback.isCanceled():
                break
            point = point_feature.geometry().asPoint()
            idList = []
            key = str(point.x()) + "_" + str(point.y())
            if key in points:
                idList = points[key][1]
            idList.append(point_feature.id())
            points[key] = [point, idList]
            if field_rn_point:
                points[key].append(point_feature[field_rn_point_index])
        for i, key in enumerate(points):
            if feedback.isCanceled():
                break
            point = points[key][0]
            output_feature = QgsFeature()
            inGeom = QgsGeometry()
            output_feature.setGeometry(inGeom.fromPointXY(point))
            attrs = [i, None, len(points[key][1])]
            if field_rn_point:
                attrs.append(points[key][2])
                attrs.append(self.NameClean(points[key][2], feedback))
            output_feature.setAttributes(attrs)
            self.sink_point.addFeature(output_feature,
                                       QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        #Calculate Graduated Line Map
        prop_point_source = QgsProcessingUtils.mapLayerFromString(
            self.dest_id_point, context)
        prop_point_source.startEditing()
        segList = {}
        t = QgsCoordinateTransform(point_source.sourceCrs(),
                                   line_source.sourceCrs(),
                                   context.transformContext())
        request = QgsFeatureRequest().setFilterRect(
            t.transform(line_source.sourceExtent(),
                        QgsCoordinateTransform.ReverseTransform))
        count = count_iterable(prop_point_source.getFeatures(request))
        total = 100.0 / count if count else 0
        feedback.setProgressText(
            self.tr('Calculate the number points for each segment'))
        for current, point_feature in enumerate(
                prop_point_source.getFeatures(request)):
            if feedback.isCanceled():
                break
            minDist = None
            minFeatId = None
            point = point_feature.geometry().asPoint()
            point = t.transform(point)
            pointBox = QgsRectangle(point.x() - distance,
                                    point.y() - distance,
                                    point.x() + distance,
                                    point.y() + distance)
            request = QgsFeatureRequest().setFilterRect(pointBox)

            if field_rn_line:
                # récupérer le nom de la rue pour feat
                pointRoadName = point_feature[field_point_rname_index]
                #Première boucle pour identifier la rue qui match le mieux
                bestMatchingFeats = None
                matchingScores = {}
                bestMatchingScore = None
                #SK : pre-traitement du point
                pointRoadNameClean = self.NameClean(pointRoadName, feedback)
                if pointRoadNameClean != '':  # verifie qu'il y a bien un nom de rue pour le point
                    minDist = None
                    for line_feature in line_source.getFeatures(request):
                        # feedback.pushInfo('Line: {}'.format(line_feature))
                        if feedback.isCanceled():
                            break
                        # récupérer le nom de la rue pour inFeat
                        lineRoadName = line_feature[field_rn_line_index]
                        # SK: pre-traitement segment
                        lineRoadNameClean = self.NameClean(
                            lineRoadName, feedback)
                        if pointRoadNameClean == '':  # verifie qu'il y a bien un nom de rue pour la ligne
                            continue
                        # SK: Calcul de la distance de Levenshtein
                        matchScore = QgsStringUtils.levenshteinDistance(
                            pointRoadNameClean, lineRoadNameClean)
                        if matchScore is not None:
                            #on stock tous les scores dans un dictionnaire que l'on interrogera plus tard avec le meilleur score
                            #on stock la liste des feature pour chaque score
                            if matchScore in matchingScores:
                                matchingScores[matchScore].append(line_feature)
                            else:
                                matchingScores[matchScore] = [line_feature]
                            #On identifie le meilleur score dans la boucle
                            if bestMatchingScore is None or matchScore < bestMatchingScore:
                                bestMatchingScore = matchScore
                        #QR : compute minDist in case MatchingScore is empty
                        geom = line_feature.geometry()
                        dist = geom.closestSegmentWithContext(
                            point)  #closestVertex
                        if minDist == None or dist[0] < minDist:
                            minDist = dist[0]
                            minFeatId = line_feature.id()
                    #On récupère la liste des segments qui ont le meilleur matching
                    if bestMatchingScore is None:  #Gestion erreur inconnue
                        if minFeatId is not None:
                            feedback.pushInfo(
                                'No matching line for {} at line: {} (closest road id used: {})'
                                .format(pointRoadName, current, minFeatId))
                    else:
                        bestMatchingFeats = matchingScores[bestMatchingScore]
                        #réutiliser ici la liste "bestMatchingFeats" pour assurer que les 2 conditions soient prises en compte : matchingName + distance la plus courte
                        minDist = None
                        oldFeatId = minFeatId
                        minFeatId = None
                        for line_feature in bestMatchingFeats:
                            geom = line_feature.geometry()
                            dist = geom.closestSegmentWithContext(
                                point)  #closestVertex
                            if minDist == None or dist[0] < minDist:
                                minDist = dist[0]
                                minFeatId = line_feature.id()
                        # if oldFeatId != minFeatId:
                        #     feedback.pushInfo('Line change based on name {} - {} for {})'.format(oldFeatId, minFeatId, pointRoadName))

                else:  # si le champ nom est vide
                    minDist = None
                    minFeatId = None
                    # passe au calcul juste sur la distance
                    for line_feature in line_source.getFeatures(request):
                        # feedback.pushInfo('Line: {}'.format(line_feature))
                        if feedback.isCanceled():
                            break
                        geom = line_feature.geometry()
                        dist = geom.closestSegmentWithContext(
                            point)  #closestVertex
                        if minDist == None or dist[0] < minDist:
                            minDist = dist[0]
                            minFeatId = line_feature.id()
                    feedback.pushInfo(
                        'Cleaned address is Empty for {} at line {} (closest road id used: {})'
                        .format(pointRoadName, current, minFeatId))

                    #FIN
            else:
                for line_feature in line_source.getFeatures(request):
                    # feedback.pushInfo('Line: {}'.format(line_feature))
                    if feedback.isCanceled():
                        break
                    geom = line_feature.geometry()
                    dist = geom.closestSegmentWithContext(
                        point)  #closestVertex
                    if minDist == None or dist[0] < minDist:
                        minDist = dist[0]
                        minFeatId = line_feature.id()

            if minFeatId is not None:
                if minFeatId in segList:
                    segList[minFeatId]["TOT"] += point_feature[
                        field_point_count_index]
                else:
                    segList[minFeatId] = {
                        "TOT": point_feature[field_point_count_index]
                    }
                prop_point_source.changeAttributeValue(point_feature.id(),
                                                       field_point_lid_index,
                                                       minFeatId)
            feedback.setProgress(int(current * total))
        prop_point_source.commitChanges()
        if len(segList) == 0:
            feedback.reportError(
                self.tr('No match between points and lines layers'),
                fatalError=True)
            return {}

        feedback.setProgressText(self.tr('Create the layer'))
        total = 100.0 / len(segList)
        current = 0
        for fid, values in segList.items():
            feat = QgsFeature()
            line_source.getFeatures(QgsFeatureRequest(fid)).nextFeature(feat)
            attrs = feat.attributes()
            attrs.append(values["TOT"])  #count
            attrs.append(fid)
            output_feature = QgsFeature()
            output_feature.setGeometry(feat.geometry())
            output_feature.setAttributes(attrs)
            self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))
            current += 1

        return {self.OUTPUT_LINE: self.dest_id}
Exemple #16
0
 def test_truncate_from_middle(self):
     """
     Test QgsStringUtils.truncateMiddleOfString
     """
     self.assertEqual(QgsStringUtils.truncateMiddleOfString('', 0), '')
     self.assertEqual(QgsStringUtils.truncateMiddleOfString('', 10), '')
     self.assertEqual(QgsStringUtils.truncateMiddleOfString('abcdef', 10),
                      'abcdef')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('abcdefghij', 10),
         'abcdefghij')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('abcdefghijk', 10),
         'abcd…ghijk')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('abcdefghijkl', 10),
         'abcde…ijkl')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('abcdefghijklmnop', 10),
         'abcde…mnop')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('this is a test', 11),
         'this … test')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('this is a test', 1), '…')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('this is a test', 2), 't…')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('this is a test', 3), 't…t')
     self.assertEqual(
         QgsStringUtils.truncateMiddleOfString('this is a test', 0), '…')
Exemple #17
0
 def testSubstituteVerticalCharacters(self):
     """ test subsitute vertical characters """
     self.assertEqual(
         QgsStringUtils.substituteVerticalCharacters('123{[(45654)]}321'),
         '123︷﹇︵45654︶﹈︸321')