Example #1
0
    def testFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between units"""

        expected = {QgsUnitTypes.DistanceMeters: {QgsUnitTypes.DistanceMeters: 1.0, QgsUnitTypes.DistanceKilometers: 0.001, QgsUnitTypes.DistanceFeet: 3.28083989501, QgsUnitTypes.DistanceYards: 1.0936133, QgsUnitTypes.DistanceMiles: 0.00062136931818182, QgsUnitTypes.DistanceDegrees: 0.00000898315, QgsUnitTypes.DistanceNauticalMiles: 0.000539957},
                    QgsUnitTypes.DistanceKilometers: {QgsUnitTypes.DistanceMeters: 1000.0, QgsUnitTypes.DistanceKilometers: 1.0, QgsUnitTypes.DistanceFeet: 3280.8398950, QgsUnitTypes.DistanceYards: 1093.6132983, QgsUnitTypes.DistanceMiles: 0.62137121212119317271, QgsUnitTypes.DistanceDegrees: 0.0089832, QgsUnitTypes.DistanceNauticalMiles: 0.53995682073432482717},
                    QgsUnitTypes.DistanceFeet: {QgsUnitTypes.DistanceMeters: 0.3048, QgsUnitTypes.DistanceKilometers: 0.0003048, QgsUnitTypes.DistanceFeet: 1.0, QgsUnitTypes.DistanceYards: 0.3333333, QgsUnitTypes.DistanceMiles: 0.00018939375, QgsUnitTypes.DistanceDegrees: 2.73806498599629E-06, QgsUnitTypes.DistanceNauticalMiles: 0.000164579},
                    QgsUnitTypes.DistanceYards: {QgsUnitTypes.DistanceMeters: 0.9144, QgsUnitTypes.DistanceKilometers: 0.0009144, QgsUnitTypes.DistanceFeet: 3.0, QgsUnitTypes.DistanceYards: 1.0, QgsUnitTypes.DistanceMiles: 0.000568182, QgsUnitTypes.DistanceDegrees: 0.0000082, QgsUnitTypes.DistanceNauticalMiles: 0.0004937366590756},
                    QgsUnitTypes.DistanceDegrees: {QgsUnitTypes.DistanceMeters: 111319.49079327358, QgsUnitTypes.DistanceKilometers: 111.3194908, QgsUnitTypes.DistanceFeet: 365221.4264871, QgsUnitTypes.DistanceYards: 121740.4754957, QgsUnitTypes.DistanceMiles: 69.1707247, QgsUnitTypes.DistanceDegrees: 1.0, QgsUnitTypes.DistanceNauticalMiles: 60.1077164},
                    QgsUnitTypes.DistanceMiles: {QgsUnitTypes.DistanceMeters: 1609.3440000, QgsUnitTypes.DistanceKilometers: 1.6093440, QgsUnitTypes.DistanceFeet: 5280.0000000, QgsUnitTypes.DistanceYards: 1760.0000000, QgsUnitTypes.DistanceMiles: 1.0, QgsUnitTypes.DistanceDegrees: 0.0144570, QgsUnitTypes.DistanceNauticalMiles: 0.8689762},
                    QgsUnitTypes.DistanceNauticalMiles: {QgsUnitTypes.DistanceMeters: 1852.0, QgsUnitTypes.DistanceKilometers: 1.8520000, QgsUnitTypes.DistanceFeet: 6076.1154856, QgsUnitTypes.DistanceYards: 2025.3718285, QgsUnitTypes.DistanceMiles: 1.1507794, QgsUnitTypes.DistanceDegrees: 0.0166367990650, QgsUnitTypes.DistanceNauticalMiles: 1.0},
                    QgsUnitTypes.DistanceUnknownUnit: {QgsUnitTypes.DistanceMeters: 1.0, QgsUnitTypes.DistanceKilometers: 1.0, QgsUnitTypes.DistanceFeet: 1.0, QgsUnitTypes.DistanceYards: 1.0, QgsUnitTypes.DistanceMiles: 1.0, QgsUnitTypes.DistanceDegrees: 1.0, QgsUnitTypes.DistanceNauticalMiles: 1.0}
                    }

        for from_unit in list(expected.keys()):
            for to_unit in list(expected[from_unit].keys()):
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(res,
                                       expected_factor,
                                       msg='got {:.7f}, expected {:.7f} when converting from {} to {}'.format(res, expected_factor,
                                                                                                              QgsUnitTypes.toString(from_unit),
                                                                                                              QgsUnitTypes.toString(to_unit)))
                #test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QgsUnitTypes.DistanceUnknownUnit)
                self.assertAlmostEqual(res,
                                       1.0,
                                       msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor,
                                                                                                                      QgsUnitTypes.toString(from_unit)))
Example #2
0
    def testFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between units"""

        expected = {QGis.Meters: {QGis.Meters: 1.0, QGis.Feet: 3.28083989501, QGis.Degrees: 0.00000898315, QGis.NauticalMiles: 0.000539957},
                    QGis.Feet: {QGis.Meters: 0.3048, QGis.Feet: 1.0, QGis.Degrees: 2.73806498599629E-06, QGis.NauticalMiles: 0.000164579},
                    QGis.Degrees: {QGis.Meters: 111319.49079327358, QGis.Feet: 365221.4264871, QGis.Degrees: 1.0, QGis.NauticalMiles: 60.1077164},
                    QGis.NauticalMiles: {QGis.Meters: 1852.0, QGis.Feet: 6076.1154856, QGis.Degrees: 0.0166367990650, QGis.NauticalMiles: 1.0},
                    QGis.UnknownUnit: {QGis.Meters: 1.0, QGis.Feet: 1.0, QGis.Degrees: 1.0, QGis.NauticalMiles: 1.0}
                    }

        for from_unit in expected.keys():
            for to_unit in expected[from_unit].keys():
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(res,
                                       expected_factor,
                                       msg='got {:.7f}, expected {:.7f} when converting from {} to {}'.format(res, expected_factor,
                                                                                                              QgsUnitTypes.toString(from_unit),
                                                                                                              QgsUnitTypes.toString(to_unit)))
                #test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QGis.UnknownUnit)
                self.assertAlmostEqual(res,
                                       1.0,
                                       msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor,
                                                                                                                      QgsUnitTypes.toString(from_unit)))
Example #3
0
    def testAreaFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between areal units"""

        expected = {QgsUnitTypes.AreaSquareMeters: {QgsUnitTypes.AreaSquareMeters: 1.0, QgsUnitTypes.AreaSquareKilometers: 1e-6, QgsUnitTypes.AreaSquareFeet: 10.7639104, QgsUnitTypes.AreaSquareYards: 1.19599, QgsUnitTypes.AreaSquareMiles: 3.86102e-7, QgsUnitTypes.AreaHectares: 0.0001, QgsUnitTypes.AreaAcres: 0.000247105, QgsUnitTypes.AreaSquareNauticalMiles: 2.91553e-7, QgsUnitTypes.AreaSquareDegrees: 0.000000000080697, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaSquareKilometers: {QgsUnitTypes.AreaSquareMeters: 1e6, QgsUnitTypes.AreaSquareKilometers: 1, QgsUnitTypes.AreaSquareFeet: 10763910.4167097, QgsUnitTypes.AreaSquareYards: 1195990.04630108, QgsUnitTypes.AreaSquareMiles: 0.386102158, QgsUnitTypes.AreaHectares: 100, QgsUnitTypes.AreaAcres: 247.105381467, QgsUnitTypes.AreaSquareNauticalMiles: 0.291553349598, QgsUnitTypes.AreaSquareDegrees: 0.000080697034968, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaSquareFeet: {QgsUnitTypes.AreaSquareMeters: 0.092903, QgsUnitTypes.AreaSquareKilometers: 9.2903e-8, QgsUnitTypes.AreaSquareFeet: 1.0, QgsUnitTypes.AreaSquareYards: 0.11111111111, QgsUnitTypes.AreaSquareMiles: 3.58701e-8, QgsUnitTypes.AreaHectares: 9.2903e-6, QgsUnitTypes.AreaAcres: 2.29568e-5, QgsUnitTypes.AreaSquareNauticalMiles: 2.70862e-8, QgsUnitTypes.AreaSquareDegrees: 0.000000000007497, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaSquareYards: {QgsUnitTypes.AreaSquareMeters: 0.836127360, QgsUnitTypes.AreaSquareKilometers: 8.36127e-7, QgsUnitTypes.AreaSquareFeet: 9.0, QgsUnitTypes.AreaSquareYards: 1.0, QgsUnitTypes.AreaSquareMiles: 3.22831e-7, QgsUnitTypes.AreaHectares: 8.3612736E-5, QgsUnitTypes.AreaAcres: 0.00020661157, QgsUnitTypes.AreaSquareNauticalMiles: 2.43776e-7, QgsUnitTypes.AreaSquareDegrees: 0.000000000067473, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaSquareMiles: {QgsUnitTypes.AreaSquareMeters: 2589988.110336, QgsUnitTypes.AreaSquareKilometers: 2.589988110, QgsUnitTypes.AreaSquareFeet: 27878400, QgsUnitTypes.AreaSquareYards: 3097600, QgsUnitTypes.AreaSquareMiles: 1.0, QgsUnitTypes.AreaHectares: 258.998811, QgsUnitTypes.AreaAcres: 640, QgsUnitTypes.AreaSquareNauticalMiles: 0.75511970898, QgsUnitTypes.AreaSquareDegrees: 0.000209004361107, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaHectares: {QgsUnitTypes.AreaSquareMeters: 10000, QgsUnitTypes.AreaSquareKilometers: 0.01, QgsUnitTypes.AreaSquareFeet: 107639.1041670972, QgsUnitTypes.AreaSquareYards: 11959.9004630, QgsUnitTypes.AreaSquareMiles: 0.00386102, QgsUnitTypes.AreaHectares: 1.0, QgsUnitTypes.AreaAcres: 2.471053814, QgsUnitTypes.AreaSquareNauticalMiles: 0.00291553, QgsUnitTypes.AreaSquareDegrees: 0.000000806970350, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaAcres: {QgsUnitTypes.AreaSquareMeters: 4046.8564224, QgsUnitTypes.AreaSquareKilometers: 0.00404686, QgsUnitTypes.AreaSquareFeet: 43560, QgsUnitTypes.AreaSquareYards: 4840, QgsUnitTypes.AreaSquareMiles: 0.0015625, QgsUnitTypes.AreaHectares: 0.404685642, QgsUnitTypes.AreaAcres: 1.0, QgsUnitTypes.AreaSquareNauticalMiles: 0.00117987, QgsUnitTypes.AreaSquareDegrees: 0.000000326569314, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaSquareNauticalMiles: {QgsUnitTypes.AreaSquareMeters: 3429904, QgsUnitTypes.AreaSquareKilometers: 3.4299040, QgsUnitTypes.AreaSquareFeet: 36919179.39391434, QgsUnitTypes.AreaSquareYards: 4102131.04376826, QgsUnitTypes.AreaSquareMiles: 1.324293337, QgsUnitTypes.AreaHectares: 342.9904000000, QgsUnitTypes.AreaAcres: 847.54773631, QgsUnitTypes.AreaSquareNauticalMiles: 1.0, QgsUnitTypes.AreaSquareDegrees: 0.000276783083025, QgsUnitTypes.AreaUnknownUnit: 1.0},
                    QgsUnitTypes.AreaSquareDegrees: {QgsUnitTypes.AreaSquareMeters: 12392029030.5, QgsUnitTypes.AreaSquareKilometers: 12392.029030499, QgsUnitTypes.AreaSquareFeet: 133386690365.5682220, QgsUnitTypes.AreaSquareYards: 14820743373.9520263, QgsUnitTypes.AreaSquareMiles: 4784.5891573967, QgsUnitTypes.AreaHectares: 1239202.903050, QgsUnitTypes.AreaAcres: 3062137.060733889, QgsUnitTypes.AreaSquareNauticalMiles: 3612.93757215, QgsUnitTypes.AreaSquareDegrees: 1.0, QgsUnitTypes.AreaUnknownUnit: 1.0}}

        for from_unit in list(expected.keys()):
            for to_unit in list(expected[from_unit].keys()):
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(res,
                                       expected_factor,
                                       msg='got {:.15f}, expected {:.15f} when converting from {} to {}'.format(res, expected_factor,
                                                                                                                QgsUnitTypes.toString(from_unit),
                                                                                                                QgsUnitTypes.toString(to_unit)))
                #test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QgsUnitTypes.AreaUnknownUnit)
                self.assertAlmostEqual(res,
                                       1.0,
                                       msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor,
                                                                                                                      QgsUnitTypes.toString(from_unit)))
    def testAngleFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between angular units"""

        expected = {QgsUnitTypes.AngleDegrees: {QgsUnitTypes.AngleDegrees: 1.0, QgsUnitTypes.AngleRadians: 0.0174533, QgsUnitTypes.AngleGon: 1.1111111, QgsUnitTypes.AngleMinutesOfArc: 60, QgsUnitTypes.AngleSecondsOfArc: 3600, QgsUnitTypes.AngleTurn: 0.00277777777778},
                    QgsUnitTypes.AngleRadians: {QgsUnitTypes.AngleDegrees: 57.2957795, QgsUnitTypes.AngleRadians: 1.0, QgsUnitTypes.AngleGon: 63.6619772, QgsUnitTypes.AngleMinutesOfArc: 3437.7467708, QgsUnitTypes.AngleSecondsOfArc: 206264.8062471, QgsUnitTypes.AngleTurn: 0.159154943092},
                    QgsUnitTypes.AngleGon: {QgsUnitTypes.AngleDegrees: 0.9000000, QgsUnitTypes.AngleRadians: 0.015707968623450838802, QgsUnitTypes.AngleGon: 1.0, QgsUnitTypes.AngleMinutesOfArc: 54.0000000, QgsUnitTypes.AngleSecondsOfArc: 3240.0000000, QgsUnitTypes.AngleTurn: 0.0025},
                    QgsUnitTypes.AngleMinutesOfArc: {QgsUnitTypes.AngleDegrees: 0.016666672633390722247, QgsUnitTypes.AngleRadians: 0.00029088831280398030638, QgsUnitTypes.AngleGon: 0.018518525464057963154, QgsUnitTypes.AngleMinutesOfArc: 1.0, QgsUnitTypes.AngleSecondsOfArc: 60.0, QgsUnitTypes.AngleTurn: 4.62962962962963e-05},
                    QgsUnitTypes.AngleSecondsOfArc: {QgsUnitTypes.AngleDegrees: 0.00027777787722304257169, QgsUnitTypes.AngleRadians: 4.848138546730629518e-6, QgsUnitTypes.AngleGon: 0.0003086420910674814405, QgsUnitTypes.AngleMinutesOfArc: 0.016666672633325253783, QgsUnitTypes.AngleSecondsOfArc: 1.0, QgsUnitTypes.AngleTurn: 7.71604938271605e-07},
                    QgsUnitTypes.AngleTurn: {QgsUnitTypes.AngleDegrees: 360.0, QgsUnitTypes.AngleRadians: 6.2831853071795, QgsUnitTypes.AngleGon: 400.0, QgsUnitTypes.AngleMinutesOfArc: 21600, QgsUnitTypes.AngleSecondsOfArc: 1296000, QgsUnitTypes.AngleTurn: 1}
                    }

        for from_unit in list(expected.keys()):
            for to_unit in list(expected[from_unit].keys()):
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(res,
                                       expected_factor,
                                       msg='got {:.7f}, expected {:.7f} when converting from {} to {}'.format(res, expected_factor,
                                                                                                              QgsUnitTypes.toString(from_unit),
                                                                                                              QgsUnitTypes.toString(to_unit)))
                # test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QgsUnitTypes.AngleUnknownUnit)
                self.assertAlmostEqual(res,
                                       1.0,
                                       msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor,
                                                                                                                      QgsUnitTypes.toString(from_unit)))
Example #5
0
    def getValue(self):
        val = super().getValue()
        if isinstance(val, float) and self.units_combo.isVisible():
            display_unit = self.units_combo.currentData()
            return val * QgsUnitTypes.fromUnitToUnitFactor(display_unit, self.base_units)

        return val
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS,
                                             context)
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context)
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(context.project().crs(), True, tolerance)

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

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

            points.append(f.geometry().asPoint())
            feedback.setProgress(int(current * total))

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

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

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

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

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

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

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

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

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

            route[:] = []

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
    def saveScale(self):
        d = VoGISProfilToolScaleDialog(self)
        result = d.exec_()
        if result == QDialog.Rejected:
            return

        scale = d.ui.cmbScale.currentText()
        dpi = d.ui.cmbDpi.currentText()
        scaleFactor = float(scale.split(":")[1])

        crsUnit = self.iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        toCm = QgsUnitTypes.fromUnitToUnitFactor(crsUnit, QgsUnitTypes.DistanceCentimeters)
        m2Cm = QgsUnitTypes.fromUnitToUnitFactor(QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceCentimeters)

        profile_length = 0
        profile_height = 0
        plt_extent = PlotExtent()
        for p in self.profiles:
            profile_length = max(p.getExtent().xmax, profile_length)
            profile_height = max(p.getExtent().ymax, profile_height)
            plt_extent.union(p.getExtent())
        plt_extent.expand()

        s = self.subplot.figure.get_size_inches()
        maxLength = toCm * profile_length
        maxHeight = m2Cm * profile_height
        imgWidth = (maxLength / scaleFactor) * TO_INCH
        imgHeight = s[1] * imgWidth / s[0]
        fig = plt.figure(figsize=(imgWidth, imgHeight),
                         dpi=10,
                         linewidth=0.0,
                         subplotpars=matplotlib.figure.SubplotParams(left=0,
                                                                     bottom=0,
                                                                     right=1,
                                                                     top=1,
                                                                     wspace=0,
                                                                     hspace=0
                                                                    )
                        )

        axes = fig.add_axes((LEFT_MARGIN, BOTTOM_MARGIN, RIGHT_MARGIN, TOP_MARGIN),
                            adjustable="datalim",
                            aspect=1
                           )
        axes.set_xbound(plt_extent.xmin, plt_extent.xmax)
        axes.set_ybound(plt_extent.ymin, plt_extent.ymax)
        self.__setupAxes(axes)
        self.__drawProfiles(axes)

        exaggeration = floor(float(self.editExaggeration.text().replace(",", ".")) * 10) / 10
        oldexa = axes.get_aspect()
        ratioexa = oldexa / exaggeration
        ylim = axes.get_ylim()
        deltaYold = ylim[1] - ylim[0]
        deltaYnew = deltaYold * ratioexa
        centerY = ylim[0] + (deltaYold / 2)
        axes.set_ylim(centerY - deltaYnew/2,centerY + deltaYnew/2)
        axes.set_aspect(exaggeration, "datalim", "C")

        axes.set_xlim(self.subplot.get_xlim())
        axes.set_ylim(self.subplot.get_ylim())
        axes.set_xbound(self.subplot.get_xbound())
        axes.set_ybound(self.subplot.get_ybound())

        u = Util(self.iface)
        caption = QApplication.translate("code", "PNG export")
        file_format = [["PNG files", "png"]]
        fileName, fileExt = u.getFileName(caption, file_format, self.filePath)
        if fileName == "":
            return
        fInfo = QFileInfo(fileName)
        self.filePath = fInfo.path()
        QgsSettings().setValue("vogisprofiltoolmain/savepath", self.filePath)
        fig.show()
        fig.savefig(fileName, dpi=int(dpi), format="png", bbox_inches='tight')
        plt.close(fig)
Example #8
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

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

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

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

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

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

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

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

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

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

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

        route.reverse()

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

        results = {}
        results[self.TRAVEL_COST] = cost / multiplier
        results[self.OUTPUT] = dest_id
        return results
Example #9
0
    def testAngleFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between angular units"""

        expected = {
            QgsUnitTypes.AngleDegrees: {
                QgsUnitTypes.AngleDegrees: 1.0,
                QgsUnitTypes.AngleRadians: 0.0174533,
                QgsUnitTypes.AngleGon: 1.1111111,
                QgsUnitTypes.AngleMinutesOfArc: 60,
                QgsUnitTypes.AngleSecondsOfArc: 3600,
                QgsUnitTypes.AngleTurn: 0.00277777777778,
                QgsUnitTypes.AngleMilliradiansSI: 17.453292519943297,
                QgsUnitTypes.AngleMilNATO: 17.77777777777778
            },
            QgsUnitTypes.AngleRadians: {
                QgsUnitTypes.AngleDegrees: 57.2957795,
                QgsUnitTypes.AngleRadians: 1.0,
                QgsUnitTypes.AngleGon: 63.6619772,
                QgsUnitTypes.AngleMinutesOfArc: 3437.7467708,
                QgsUnitTypes.AngleSecondsOfArc: 206264.8062471,
                QgsUnitTypes.AngleTurn: 0.159154943092,
                QgsUnitTypes.AngleMilliradiansSI: 1000.0,
                QgsUnitTypes.AngleMilNATO: 1018.5916357881301
            },
            QgsUnitTypes.AngleGon: {
                QgsUnitTypes.AngleDegrees: 0.9000000,
                QgsUnitTypes.AngleRadians: 0.015707968623450838802,
                QgsUnitTypes.AngleGon: 1.0,
                QgsUnitTypes.AngleMinutesOfArc: 54.0000000,
                QgsUnitTypes.AngleSecondsOfArc: 3240.0000000,
                QgsUnitTypes.AngleTurn: 0.0025,
                QgsUnitTypes.AngleMilliradiansSI: 15.707963267948967,
                QgsUnitTypes.AngleMilNATO: 16
            },
            QgsUnitTypes.AngleMinutesOfArc: {
                QgsUnitTypes.AngleDegrees: 0.016666672633390722247,
                QgsUnitTypes.AngleRadians: 0.00029088831280398030638,
                QgsUnitTypes.AngleGon: 0.018518525464057963154,
                QgsUnitTypes.AngleMinutesOfArc: 1.0,
                QgsUnitTypes.AngleSecondsOfArc: 60.0,
                QgsUnitTypes.AngleTurn: 4.62962962962963e-05,
                QgsUnitTypes.AngleMilliradiansSI: 0.29088820866572157,
                QgsUnitTypes.AngleMilNATO: 0.29629629629629634
            },
            QgsUnitTypes.AngleSecondsOfArc: {
                QgsUnitTypes.AngleDegrees: 0.00027777787722304257169,
                QgsUnitTypes.AngleRadians: 4.848138546730629518e-6,
                QgsUnitTypes.AngleGon: 0.0003086420910674814405,
                QgsUnitTypes.AngleMinutesOfArc: 0.016666672633325253783,
                QgsUnitTypes.AngleSecondsOfArc: 1.0,
                QgsUnitTypes.AngleTurn: 7.71604938271605e-07,
                QgsUnitTypes.AngleMilliradiansSI: 0.0048481482527009582897,
                QgsUnitTypes.AngleMilNATO: 0.0049382716049382715
            },
            QgsUnitTypes.AngleTurn: {
                QgsUnitTypes.AngleDegrees: 360.0,
                QgsUnitTypes.AngleRadians: 6.2831853071795,
                QgsUnitTypes.AngleGon: 400.0,
                QgsUnitTypes.AngleMinutesOfArc: 21600,
                QgsUnitTypes.AngleSecondsOfArc: 1296000,
                QgsUnitTypes.AngleTurn: 1,
                QgsUnitTypes.AngleMilliradiansSI: 6283.185307179586,
                QgsUnitTypes.AngleMilNATO: 6400
            },
            QgsUnitTypes.AngleMilliradiansSI: {
                QgsUnitTypes.AngleDegrees: 0.057295779513082325,
                QgsUnitTypes.AngleRadians: 0.001,
                QgsUnitTypes.AngleGon: 0.06366197723675814,
                QgsUnitTypes.AngleMinutesOfArc: 3.4377467707849396,
                QgsUnitTypes.AngleSecondsOfArc: 206.26480624709637,
                QgsUnitTypes.AngleTurn: 0.0015707963267948967,
                QgsUnitTypes.AngleMilliradiansSI: 1.0,
                QgsUnitTypes.AngleMilNATO: 1.0185916357881302
            },
            QgsUnitTypes.AngleMilNATO: {
                QgsUnitTypes.AngleDegrees: 0.05625,
                QgsUnitTypes.AngleRadians: 0.0009817477042468104,
                QgsUnitTypes.AngleGon: 0.0625,
                QgsUnitTypes.AngleMinutesOfArc: 3.375,
                QgsUnitTypes.AngleSecondsOfArc: 202.5,
                QgsUnitTypes.AngleTurn: 0.000015625,
                QgsUnitTypes.AngleMilliradiansSI: 0.9817477042468102,
                QgsUnitTypes.AngleMilNATO: 1.0
            }
        }

        for from_unit in list(expected.keys()):
            for to_unit in list(expected[from_unit].keys()):
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(
                    res,
                    expected_factor,
                    msg=
                    'got {:.7f}, expected {:.7f} when converting from {} to {}'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit),
                            QgsUnitTypes.toString(to_unit)))
                # test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(
                    from_unit, QgsUnitTypes.AngleUnknownUnit)
                self.assertAlmostEqual(
                    res,
                    1.0,
                    msg=
                    'got {:.7f}, expected 1.0 when converting from {} to unknown units'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit)))
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST,
                                            context)

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

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

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

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

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

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

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

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

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

        return {self.OUTPUT: dest_id}
Example #11
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

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

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

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

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

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

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

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

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

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

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

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

        route.reverse()

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

        results = {}
        results[self.TRAVEL_COST] = cost / multiplier
        results[self.OUTPUT] = dest_id
        return results
Example #12
0
    def processAlgorithm(self, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_VECTOR), context)
        startPoint = self.getParameterValue(self.START_POINT)
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

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

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

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

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

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

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

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

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

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

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

        del writer

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

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

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

        geom = geomLower.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)
        del writer
Example #13
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context)

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

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

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

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

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

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

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

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

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

        return {self.OUTPUT: dest_id}
Example #14
0
    def compute(self):
        from AcATaMa.gui.acatama_dockwidget import AcATaMaDockWidget as AcATaMa
        AcATaMa.dockwidget.QPBtn_ComputeViewAccurasyAssessment.setText("Processing, please wait ...")
        QApplication.processEvents()

        # get labels from classification buttons
        labels = {}
        for button_config in self.classification.buttons_config.values():
            labels[button_config["thematic_class"]] = button_config["name"]

        # get the classified and thematic map values
        thematic_map_values = []
        classified_values = []
        samples_outside_the_thematic = []
        classification_points = [point for point in self.classification.points if point.is_classified]
        points_ordered = sorted(classification_points, key=lambda p: p.shape_id)
        for point in points_ordered:
            # classification from the pixel values in the thematic map
            thematic_map_value = self.ThematicR.get_pixel_value_from_pnt(point.QgsPnt)
            if not thematic_map_value:
                samples_outside_the_thematic.append(point)
                continue
            thematic_map_values.append(int(thematic_map_value))
            # classified value made/checked by user with classification buttons
            classified_value = self.classification.buttons_config[point.classif_id]["thematic_class"]
            classified_values.append(int(classified_value))

        # all unique and sorted values
        values = sorted(set(thematic_map_values + classified_values))
        # Construct a value->index dictionary
        indices = dict((val, i) for (i, val) in enumerate(values))

        # calculate the error/confusion matrix
        # https://github.com/nltk/nltk/blob/develop/nltk/metrics/confusionmatrix.py
        #
        #             classified
        #   t |    | L1 | L2 | L3 | L4 |
        #   h | L1 |    |    |    |    |
        #   e | L2 |    |    |    |    |
        #   m | L3 |    |    |    |    |
        #   a | L4 |    |    |    |    |
        #
        error_matrix = [[0 for column in values] for row in values]
        for thematic, classified in zip(thematic_map_values, classified_values):
            error_matrix[indices[thematic]][indices[classified]] += 1

        # calculate the total number of pixel in the thematic raster
        # by each thematic raster class used in the classification buttons
        for thematic_map_value in values:
            if thematic_map_value not in self.thematic_pixels_count:
                self.thematic_pixels_count[thematic_map_value] = self.ThematicR.get_total_pixels_by_value(thematic_map_value)

        # values necessary for results
        self.values = values
        self.labels = labels
        self.error_matrix = error_matrix
        self.samples_outside_the_thematic = samples_outside_the_thematic
        # set area by pixel
        self.pixel_area_base = self.ThematicR.qgs_layer.rasterUnitsPerPixelX() * self.ThematicR.qgs_layer.rasterUnitsPerPixelY()
        self.pixel_area_value = self.pixel_area_base * QgsUnitTypes.fromUnitToUnitFactor(self.base_area_unit, self.area_unit)
        self.pixel_area_unit = QgsUnitTypes.toAbbreviatedString(self.area_unit)
Example #15
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS,
                                             context)
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST,
                                            context)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

            if not f.hasGeometry():
                continue

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

            feedback.setProgress(int(current * total))

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

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

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

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

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

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

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

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

            feat.setGeometry(geomUpper)

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

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

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

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Example #16
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)
        startPoints = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.START_POINTS), context)
        endPoint = self.getParameterValue(self.END_POINT)
        strategy = self.getParameterValue(self.STRATEGY)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

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

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

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

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

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

        total = 100.0 / count
        for i in range(1, count + 1):
            idxStart = graph.findVertex(snappedPoints[i])
            tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

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

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

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

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

            route[:] = []

            feedback.setProgress(int(i * total))

        del writer
Example #17
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS,
                                             context)
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context,
                                         network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

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

            if not f.hasGeometry():
                continue

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

            feedback.setProgress(int(current * total))

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

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

        idxEnd = graph.findVertex(snappedPoints[0])

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

            idxStart = graph.findVertex(snappedPoints[i])

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

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

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

            route.reverse()

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

            feedback.setProgress(int(i * total))

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

        #initialize feedback
        self.feedback = feedback

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

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

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

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

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

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

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

        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Start tying analysis points to the graph and building it."
        )
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] This is a compute intensive task and may take some time depending on network size"
        )
        start_local_time = time.localtime()
        start_time = time.time()
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Start Time: {}".format(
                time.strftime(":%Y-%m-%d %H:%M:%S", start_local_time)))
        self.feedback.pushInfo("[QNEAT3Network][__init__] Building...")
        self.list_tiedPoints = self.director.makeGraph(self.builder,
                                                       self.list_input_points,
                                                       self.feedback)
        self.network = self.builder.graph()
        end_local_time = time.localtime()
        end_time = time.time()
        self.feedback.pushInfo("[QNEAT3Network][__init__] End Time: {}".format(
            time.strftime(":%Y-%m-%d %H:%M:%S", end_local_time)))
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Total Build Time: {}".format(
                end_time - start_time))
        self.feedback.pushInfo(
            "[QNEAT3Network][__init__] Analysis setup complete")
Example #19
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
                self.getParameterValue(self.INPUT_VECTOR))
        startPoint = self.getParameterValue(self.START_POINT)
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

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

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

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

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

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

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

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

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

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

        progress.setInfo(self.tr('Writting results...'))

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

        del writer

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

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

        geom = geomLower.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)
        del writer
Example #20
0
    def testAreaFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between areal units"""

        expected = {
            QgsUnitTypes.AreaSquareMeters: {
                QgsUnitTypes.AreaSquareMeters: 1.0,
                QgsUnitTypes.AreaSquareKilometers: 1e-6,
                QgsUnitTypes.AreaSquareFeet: 10.7639104,
                QgsUnitTypes.AreaSquareYards: 1.19599,
                QgsUnitTypes.AreaSquareMiles: 3.86102e-7,
                QgsUnitTypes.AreaHectares: 0.0001,
                QgsUnitTypes.AreaAcres: 0.000247105,
                QgsUnitTypes.AreaSquareNauticalMiles: 2.91553e-7,
                QgsUnitTypes.AreaSquareDegrees: 0.000000000080697,
                QgsUnitTypes.AreaSquareMillimeters: 1e6,
                QgsUnitTypes.AreaSquareCentimeters: 1e4,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareKilometers: {
                QgsUnitTypes.AreaSquareMeters: 1e6,
                QgsUnitTypes.AreaSquareKilometers: 1,
                QgsUnitTypes.AreaSquareFeet: 10763910.4167097,
                QgsUnitTypes.AreaSquareYards: 1195990.04630108,
                QgsUnitTypes.AreaSquareMiles: 0.386102158,
                QgsUnitTypes.AreaHectares: 100,
                QgsUnitTypes.AreaAcres: 247.105381467,
                QgsUnitTypes.AreaSquareNauticalMiles: 0.291553349598,
                QgsUnitTypes.AreaSquareDegrees: 0.000080697034968,
                QgsUnitTypes.AreaSquareMillimeters: 1e12,
                QgsUnitTypes.AreaSquareCentimeters: 1e10,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareFeet: {
                QgsUnitTypes.AreaSquareMeters: 0.092903,
                QgsUnitTypes.AreaSquareKilometers: 9.2903e-8,
                QgsUnitTypes.AreaSquareFeet: 1.0,
                QgsUnitTypes.AreaSquareYards: 0.11111111111,
                QgsUnitTypes.AreaSquareMiles: 3.58701e-8,
                QgsUnitTypes.AreaHectares: 9.2903e-6,
                QgsUnitTypes.AreaAcres: 2.29568e-5,
                QgsUnitTypes.AreaSquareNauticalMiles: 2.70862e-8,
                QgsUnitTypes.AreaSquareDegrees: 0.000000000007497,
                QgsUnitTypes.AreaSquareMillimeters: 92903.04,
                QgsUnitTypes.AreaSquareCentimeters: 929.0304,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareYards: {
                QgsUnitTypes.AreaSquareMeters: 0.836127360,
                QgsUnitTypes.AreaSquareKilometers: 8.36127e-7,
                QgsUnitTypes.AreaSquareFeet: 9.0,
                QgsUnitTypes.AreaSquareYards: 1.0,
                QgsUnitTypes.AreaSquareMiles: 3.22831e-7,
                QgsUnitTypes.AreaHectares: 8.3612736E-5,
                QgsUnitTypes.AreaAcres: 0.00020661157,
                QgsUnitTypes.AreaSquareNauticalMiles: 2.43776e-7,
                QgsUnitTypes.AreaSquareDegrees: 0.000000000067473,
                QgsUnitTypes.AreaSquareMillimeters: 836127.360,
                QgsUnitTypes.AreaSquareCentimeters: 8361.27360,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareMiles: {
                QgsUnitTypes.AreaSquareMeters: 2589988.110336,
                QgsUnitTypes.AreaSquareKilometers: 2.589988110,
                QgsUnitTypes.AreaSquareFeet: 27878400,
                QgsUnitTypes.AreaSquareYards: 3097600,
                QgsUnitTypes.AreaSquareMiles: 1.0,
                QgsUnitTypes.AreaHectares: 258.998811,
                QgsUnitTypes.AreaAcres: 640,
                QgsUnitTypes.AreaSquareNauticalMiles: 0.75511970898,
                QgsUnitTypes.AreaSquareDegrees: 0.000209004361107,
                QgsUnitTypes.AreaSquareMillimeters: 2589988110336.0,
                QgsUnitTypes.AreaSquareCentimeters: 25899881103.36,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaHectares: {
                QgsUnitTypes.AreaSquareMeters: 10000,
                QgsUnitTypes.AreaSquareKilometers: 0.01,
                QgsUnitTypes.AreaSquareFeet: 107639.1041670972,
                QgsUnitTypes.AreaSquareYards: 11959.9004630,
                QgsUnitTypes.AreaSquareMiles: 0.00386102,
                QgsUnitTypes.AreaHectares: 1.0,
                QgsUnitTypes.AreaAcres: 2.471053814,
                QgsUnitTypes.AreaSquareNauticalMiles: 0.00291553,
                QgsUnitTypes.AreaSquareDegrees: 0.000000806970350,
                QgsUnitTypes.AreaSquareMillimeters: 10000000000.0,
                QgsUnitTypes.AreaSquareCentimeters: 100000000.0,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaAcres: {
                QgsUnitTypes.AreaSquareMeters: 4046.8564224,
                QgsUnitTypes.AreaSquareKilometers: 0.00404686,
                QgsUnitTypes.AreaSquareFeet: 43560,
                QgsUnitTypes.AreaSquareYards: 4840,
                QgsUnitTypes.AreaSquareMiles: 0.0015625,
                QgsUnitTypes.AreaHectares: 0.404685642,
                QgsUnitTypes.AreaAcres: 1.0,
                QgsUnitTypes.AreaSquareNauticalMiles: 0.00117987,
                QgsUnitTypes.AreaSquareDegrees: 0.000000326569314,
                QgsUnitTypes.AreaSquareMillimeters: 4046856422.4000005,
                QgsUnitTypes.AreaSquareCentimeters: 40468564.224,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareNauticalMiles: {
                QgsUnitTypes.AreaSquareMeters: 3429904,
                QgsUnitTypes.AreaSquareKilometers: 3.4299040,
                QgsUnitTypes.AreaSquareFeet: 36919179.39391434,
                QgsUnitTypes.AreaSquareYards: 4102131.04376826,
                QgsUnitTypes.AreaSquareMiles: 1.324293337,
                QgsUnitTypes.AreaHectares: 342.9904000000,
                QgsUnitTypes.AreaAcres: 847.54773631,
                QgsUnitTypes.AreaSquareNauticalMiles: 1.0,
                QgsUnitTypes.AreaSquareDegrees: 0.000276783083025,
                QgsUnitTypes.AreaSquareMillimeters: 3429904000000.0,
                QgsUnitTypes.AreaSquareCentimeters: 34299040000.0,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareDegrees: {
                QgsUnitTypes.AreaSquareMeters: 12392029030.5,
                QgsUnitTypes.AreaSquareKilometers: 12392.029030499,
                QgsUnitTypes.AreaSquareFeet: 133386690365.5682220,
                QgsUnitTypes.AreaSquareYards: 14820743373.9520263,
                QgsUnitTypes.AreaSquareMiles: 4784.5891573967,
                QgsUnitTypes.AreaHectares: 1239202.903050,
                QgsUnitTypes.AreaAcres: 3062137.060733889,
                QgsUnitTypes.AreaSquareNauticalMiles: 3612.93757215,
                QgsUnitTypes.AreaSquareDegrees: 1.0,
                QgsUnitTypes.AreaSquareMillimeters: 12392029030500000.0,
                QgsUnitTypes.AreaSquareCentimeters: 123920290305000.0,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareMillimeters: {
                QgsUnitTypes.AreaSquareMeters: 1e-6,
                QgsUnitTypes.AreaSquareKilometers: 1e-12,
                QgsUnitTypes.AreaSquareFeet: 0.000010763910417,
                QgsUnitTypes.AreaSquareYards: 0.000001195990046,
                QgsUnitTypes.AreaSquareMiles: 3.861021585424458e-13,
                QgsUnitTypes.AreaHectares: 1e-10,
                QgsUnitTypes.AreaAcres: 2.471053814671653e-10,
                QgsUnitTypes.AreaSquareNauticalMiles: 2.9155334959812287e-13,
                QgsUnitTypes.AreaSquareDegrees: 8.069703496810251e-17,
                QgsUnitTypes.AreaSquareMillimeters: 1.0,
                QgsUnitTypes.AreaSquareCentimeters: 0.01,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            },
            QgsUnitTypes.AreaSquareCentimeters: {
                QgsUnitTypes.AreaSquareMeters: 1e-4,
                QgsUnitTypes.AreaSquareKilometers: 1e-10,
                QgsUnitTypes.AreaSquareFeet: 0.0010763910417,
                QgsUnitTypes.AreaSquareYards: 0.0001195990046,
                QgsUnitTypes.AreaSquareMiles: 3.861021585424458e-11,
                QgsUnitTypes.AreaHectares: 1e-8,
                QgsUnitTypes.AreaAcres: 2.471053814671653e-8,
                QgsUnitTypes.AreaSquareNauticalMiles: 2.9155334959812287e-11,
                QgsUnitTypes.AreaSquareDegrees: 8.069703496810251e-15,
                QgsUnitTypes.AreaSquareMillimeters: 100,
                QgsUnitTypes.AreaSquareCentimeters: 1.0,
                QgsUnitTypes.AreaUnknownUnit: 1.0
            }
        }

        for from_unit in list(expected.keys()):
            for to_unit in list(expected[from_unit].keys()):
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(
                    res,
                    expected_factor,
                    msg=
                    'got {:.15f}, expected {:.15f} when converting from {} to {}'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit),
                            QgsUnitTypes.toString(to_unit)))
                # test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(
                    from_unit, QgsUnitTypes.AreaUnknownUnit)
                self.assertAlmostEqual(
                    res,
                    1.0,
                    msg=
                    'got {:.7f}, expected 1.0 when converting from {} to unknown units'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit)))
Example #21
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoints = dataobjects.getObjectFromUri(
            self.getParameterValue(self.START_POINTS))
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            feedback.setProgress(int(i * total))

        del writerPoints
        del writerPolygons
Example #22
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

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

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

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

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

            if not f.hasGeometry():
                continue

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

            feedback.setProgress(int(current * total))

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

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

        idxEnd = graph.findVertex(snappedPoints[0])

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

            idxStart = graph.findVertex(snappedPoints[i])

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

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

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

            route.reverse()

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

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Example #23
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS, context)
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

            if not f.hasGeometry():
                continue

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

            feedback.setProgress(int(current * total))

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

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

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

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

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

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

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

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

            feat.setGeometry(geomUpper)

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

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

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

            feedback.setProgress(int(i * total))

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

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(context.project().crs(),
                                  True,
                                  tolerance)

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

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

            points.append(f.geometry().asPoint())
            feedback.setProgress(int(current * total))

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

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

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

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

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

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

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

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

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

            route[:] = []

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
Example #25
0
            QgsUnitTypes.DistanceYards, QgsUnitTypes.DistanceMeters)
    elif units == 5:  # Feet
        measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
            QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMeters)
    elif units == 6:  # Inches
        measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
            QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMeters) / 12.0
    elif units == 7:  # Nautical Miles
        measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
            QgsUnitTypes.DistanceNauticalMiles, QgsUnitTypes.DistanceMeters)
    return measureFactor


epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326")

nmToMeters = QgsUnitTypes.fromUnitToUnitFactor(
    QgsUnitTypes.DistanceNauticalMiles, QgsUnitTypes.DistanceMeters)
metersToFeet = QgsUnitTypes.fromUnitToUnitFactor(QgsUnitTypes.DistanceMeters,
                                                 QgsUnitTypes.DistanceFeet)
degToMeters = nmToMeters * 60
metersToDeg = 1 / degToMeters


# vector addition of two XY points
def addPoints(a, b):
    return QgsPointXY(a.x() + b.x(), a.y() + b.y())


# vector difference of two XY points
def diffPoints(a, b):
    return QgsPointXY(a.x() - b.x(), a.y() - b.y())
Example #26
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoint = self.getParameterValue(self.START_POINT)
        endPoint = self.getParameterValue(self.END_POINT)
        strategy = self.getParameterValue(self.STRATEGY)

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

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

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

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

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

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

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

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

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

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

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

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

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

        feedback.pushInfo(self.tr('Writing results...'))
        geom = QgsGeometry.fromPolyline(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        writer.addFeature(feat)
        del writer
Example #27
0
    def testAngleFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between angular units"""

        expected = {
            QgsUnitTypes.AngleDegrees: {
                QgsUnitTypes.AngleDegrees: 1.0,
                QgsUnitTypes.AngleRadians: 0.0174533,
                QgsUnitTypes.AngleGon: 1.1111111,
                QgsUnitTypes.AngleMinutesOfArc: 60,
                QgsUnitTypes.AngleSecondsOfArc: 3600,
                QgsUnitTypes.AngleTurn: 0.00277777777778
            },
            QgsUnitTypes.AngleRadians: {
                QgsUnitTypes.AngleDegrees: 57.2957795,
                QgsUnitTypes.AngleRadians: 1.0,
                QgsUnitTypes.AngleGon: 63.6619772,
                QgsUnitTypes.AngleMinutesOfArc: 3437.7467708,
                QgsUnitTypes.AngleSecondsOfArc: 206264.8062471,
                QgsUnitTypes.AngleTurn: 0.159154943092
            },
            QgsUnitTypes.AngleGon: {
                QgsUnitTypes.AngleDegrees: 0.9000000,
                QgsUnitTypes.AngleRadians: 0.015707968623450838802,
                QgsUnitTypes.AngleGon: 1.0,
                QgsUnitTypes.AngleMinutesOfArc: 54.0000000,
                QgsUnitTypes.AngleSecondsOfArc: 3240.0000000,
                QgsUnitTypes.AngleTurn: 0.0025
            },
            QgsUnitTypes.AngleMinutesOfArc: {
                QgsUnitTypes.AngleDegrees: 0.016666672633390722247,
                QgsUnitTypes.AngleRadians: 0.00029088831280398030638,
                QgsUnitTypes.AngleGon: 0.018518525464057963154,
                QgsUnitTypes.AngleMinutesOfArc: 1.0,
                QgsUnitTypes.AngleSecondsOfArc: 60.0,
                QgsUnitTypes.AngleTurn: 4.62962962962963e-05
            },
            QgsUnitTypes.AngleSecondsOfArc: {
                QgsUnitTypes.AngleDegrees: 0.00027777787722304257169,
                QgsUnitTypes.AngleRadians: 4.848138546730629518e-6,
                QgsUnitTypes.AngleGon: 0.0003086420910674814405,
                QgsUnitTypes.AngleMinutesOfArc: 0.016666672633325253783,
                QgsUnitTypes.AngleSecondsOfArc: 1.0,
                QgsUnitTypes.AngleTurn: 7.71604938271605e-07
            },
            QgsUnitTypes.AngleTurn: {
                QgsUnitTypes.AngleDegrees: 360.0,
                QgsUnitTypes.AngleRadians: 6.2831853071795,
                QgsUnitTypes.AngleGon: 400.0,
                QgsUnitTypes.AngleMinutesOfArc: 21600,
                QgsUnitTypes.AngleSecondsOfArc: 1296000,
                QgsUnitTypes.AngleTurn: 1
            }
        }

        for from_unit in list(expected.keys()):
            for to_unit in list(expected[from_unit].keys()):
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(
                    res,
                    expected_factor,
                    msg=
                    'got {:.7f}, expected {:.7f} when converting from {} to {}'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit),
                            QgsUnitTypes.toString(to_unit)))
                # test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(
                    from_unit, QgsUnitTypes.AngleUnknownUnit)
                self.assertAlmostEqual(
                    res,
                    1.0,
                    msg=
                    'got {:.7f}, expected 1.0 when converting from {} to unknown units'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit)))
Example #28
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoints = dataobjects.getObjectFromUri(
            self.getParameterValue(self.START_POINTS))
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            feedback.setProgress(int(i * total))

        del writerPoints
        del writerPolygons
Example #29
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoint = self.getParameterValue(self.START_POINT)
        endPoint = self.getParameterValue(self.END_POINT)
        strategy = self.getParameterValue(self.STRATEGY)

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

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

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

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

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

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

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

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

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

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

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

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

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

        feedback.pushInfo(self.tr('Writing results...'))
        geom = QgsGeometry.fromPolyline(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        writer.addFeature(feat)
        del writer
Example #30
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST,
                                            context)

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

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

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

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

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

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

        feedback.pushInfo(
            QCoreApplication.translate('ServiceAreaFromPoint',
                                       'Calculating service area…'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = set()
        points = []
        lines = []

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

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

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

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

        for i in vertices:
            points.append(graph.vertex(i).point())

        feedback.pushInfo(
            QCoreApplication.translate('ServiceAreaFromPoint',
                                       'Writing results…'))

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

        feat = QgsFeature()
        feat.setFields(fields)

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

        results = {}

        if point_sink is not None:
            results[self.OUTPUT] = dest_id
            geomPoints = QgsGeometry.fromMultiPointXY(points)
            feat.setGeometry(geomPoints)
            feat['type'] = 'within'
            feat['start'] = startPoint.toString()
            point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

            if include_bounds:
                upperBoundary = []
                lowerBoundary = []

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

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

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

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

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

        (line_sink,
         line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES,
                                              context, fields,
                                              QgsWkbTypes.MultiLineString,
                                              network.sourceCrs())
        if line_sink is not None:
            results[self.OUTPUT_LINES] = line_dest_id
            geom_lines = QgsGeometry.fromMultiPolylineXY(lines)
            feat.setGeometry(geom_lines)
            feat['type'] = 'lines'
            feat['start'] = startPoint.toString()
            line_sink.addFeature(feat, QgsFeatureSink.FastInsert)

        return results
Example #31
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoint = self.getParameterValue(self.START_POINT)
        endPoints = dataobjects.getObjectFromUri(
            self.getParameterValue(self.END_POINTS))
        strategy = self.getParameterValue(self.STRATEGY)

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

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

        feat = QgsFeature()
        feat.setFields(fields)

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

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

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

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

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

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

        progress.setInfo(self.tr('Loading end points...'))
        request = QgsFeatureRequest()
        request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes)
        features = vector.features(endPoints, request)
        count = len(features)

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

        progress.setInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, points)

        progress.setInfo(self.tr('Calculating shortest paths...'))
        graph = builder.graph()

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

        total = 100.0 / count
        for i in range(1, count + 1):
            idxEnd = graph.findVertex(snappedPoints[i])

            if tree[idxEnd] == -1:
                msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(startPoint.toString(), points[i].toString()))
                progress.setText(msg)
                ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, msg)
                continue

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

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

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

            route[:] = []

            progress.setPercentage(int(i * total))

        del writer
Example #32
0
    def testFromUnitToUnitFactor(self):
        """Test calculation of conversion factor between units"""

        expected = {
            QgsUnitTypes.DistanceMeters: {
                QgsUnitTypes.DistanceMeters: 1.0,
                QgsUnitTypes.DistanceKilometers: 0.001,
                QgsUnitTypes.DistanceFeet: 3.28083989501,
                QgsUnitTypes.DistanceYards: 1.0936133,
                QgsUnitTypes.DistanceMiles: 0.00062136931818182,
                QgsUnitTypes.DistanceDegrees: 0.00000898315,
                QgsUnitTypes.DistanceNauticalMiles: 0.000539957,
                QgsUnitTypes.DistanceMillimeters: 1000.0,
                QgsUnitTypes.DistanceCentimeters: 100.0
            },
            QgsUnitTypes.DistanceKilometers: {
                QgsUnitTypes.DistanceMeters: 1000.0,
                QgsUnitTypes.DistanceKilometers: 1.0,
                QgsUnitTypes.DistanceFeet: 3280.8398950,
                QgsUnitTypes.DistanceYards: 1093.6132983,
                QgsUnitTypes.DistanceMiles: 0.62137121212119317271,
                QgsUnitTypes.DistanceDegrees: 0.0089832,
                QgsUnitTypes.DistanceNauticalMiles: 0.53995682073432482717,
                QgsUnitTypes.DistanceMillimeters: 1000000.0,
                QgsUnitTypes.DistanceCentimeters: 100000.0
            },
            QgsUnitTypes.DistanceFeet: {
                QgsUnitTypes.DistanceMeters: 0.3048,
                QgsUnitTypes.DistanceKilometers: 0.0003048,
                QgsUnitTypes.DistanceFeet: 1.0,
                QgsUnitTypes.DistanceYards: 0.3333333,
                QgsUnitTypes.DistanceMiles: 0.00018939375,
                QgsUnitTypes.DistanceDegrees: 2.73806498599629E-06,
                QgsUnitTypes.DistanceNauticalMiles: 0.000164579,
                QgsUnitTypes.DistanceMillimeters: 304.8,
                QgsUnitTypes.DistanceCentimeters: 30.48
            },
            QgsUnitTypes.DistanceYards: {
                QgsUnitTypes.DistanceMeters: 0.9144,
                QgsUnitTypes.DistanceKilometers: 0.0009144,
                QgsUnitTypes.DistanceFeet: 3.0,
                QgsUnitTypes.DistanceYards: 1.0,
                QgsUnitTypes.DistanceMiles: 0.000568182,
                QgsUnitTypes.DistanceDegrees: 0.0000082,
                QgsUnitTypes.DistanceNauticalMiles: 0.0004937366590756,
                QgsUnitTypes.DistanceMillimeters: 914.4,
                QgsUnitTypes.DistanceCentimeters: 91.44
            },
            QgsUnitTypes.DistanceDegrees: {
                QgsUnitTypes.DistanceMeters: 111319.49079327358,
                QgsUnitTypes.DistanceKilometers: 111.3194908,
                QgsUnitTypes.DistanceFeet: 365221.4264871,
                QgsUnitTypes.DistanceYards: 121740.4754957,
                QgsUnitTypes.DistanceMiles: 69.1707247,
                QgsUnitTypes.DistanceDegrees: 1.0,
                QgsUnitTypes.DistanceNauticalMiles: 60.1077164,
                QgsUnitTypes.DistanceMillimeters: 111319490.79327358,
                QgsUnitTypes.DistanceCentimeters: 11131949.079327358
            },
            QgsUnitTypes.DistanceMiles: {
                QgsUnitTypes.DistanceMeters: 1609.3440000,
                QgsUnitTypes.DistanceKilometers: 1.6093440,
                QgsUnitTypes.DistanceFeet: 5280.0000000,
                QgsUnitTypes.DistanceYards: 1760.0000000,
                QgsUnitTypes.DistanceMiles: 1.0,
                QgsUnitTypes.DistanceDegrees: 0.0144570,
                QgsUnitTypes.DistanceNauticalMiles: 0.8689762,
                QgsUnitTypes.DistanceMillimeters: 1609344.0,
                QgsUnitTypes.DistanceCentimeters: 160934.4
            },
            QgsUnitTypes.DistanceNauticalMiles: {
                QgsUnitTypes.DistanceMeters: 1852.0,
                QgsUnitTypes.DistanceKilometers: 1.8520000,
                QgsUnitTypes.DistanceFeet: 6076.1154856,
                QgsUnitTypes.DistanceYards: 2025.3718285,
                QgsUnitTypes.DistanceMiles: 1.1507794,
                QgsUnitTypes.DistanceDegrees: 0.0166367990650,
                QgsUnitTypes.DistanceNauticalMiles: 1.0,
                QgsUnitTypes.DistanceMillimeters: 1852000.0,
                QgsUnitTypes.DistanceCentimeters: 185200.0
            },
            QgsUnitTypes.DistanceMillimeters: {
                QgsUnitTypes.DistanceMeters: 0.001,
                QgsUnitTypes.DistanceKilometers: 0.000001,
                QgsUnitTypes.DistanceFeet: 0.00328083989501,
                QgsUnitTypes.DistanceYards: 0.0010936133,
                QgsUnitTypes.DistanceMiles: 0.00000062136931818182,
                QgsUnitTypes.DistanceDegrees: 0.00000000898315,
                QgsUnitTypes.DistanceNauticalMiles: 0.000000539957,
                QgsUnitTypes.DistanceMillimeters: 1.0,
                QgsUnitTypes.DistanceCentimeters: 0.1
            },
            QgsUnitTypes.DistanceCentimeters: {
                QgsUnitTypes.DistanceMeters: 0.01,
                QgsUnitTypes.DistanceKilometers: 0.00001,
                QgsUnitTypes.DistanceFeet: 0.0328083989501,
                QgsUnitTypes.DistanceYards: 0.010936133,
                QgsUnitTypes.DistanceMiles: 0.0000062136931818182,
                QgsUnitTypes.DistanceDegrees: 0.0000000898315,
                QgsUnitTypes.DistanceNauticalMiles: 0.00000539957,
                QgsUnitTypes.DistanceMillimeters: 10.0,
                QgsUnitTypes.DistanceCentimeters: 1.0
            },
            QgsUnitTypes.DistanceUnknownUnit: {
                QgsUnitTypes.DistanceMeters: 1.0,
                QgsUnitTypes.DistanceKilometers: 1.0,
                QgsUnitTypes.DistanceFeet: 1.0,
                QgsUnitTypes.DistanceYards: 1.0,
                QgsUnitTypes.DistanceMiles: 1.0,
                QgsUnitTypes.DistanceDegrees: 1.0,
                QgsUnitTypes.DistanceNauticalMiles: 1.0,
                QgsUnitTypes.DistanceMillimeters: 1.0,
                QgsUnitTypes.DistanceCentimeters: 1.0
            },
        }

        for from_unit in list(expected.keys()):
            for to_unit in list(expected[from_unit].keys()):
                expected_factor = expected[from_unit][to_unit]
                res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit)
                self.assertAlmostEqual(
                    res,
                    expected_factor,
                    msg=
                    'got {:.7f}, expected {:.7f} when converting from {} to {}'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit),
                            QgsUnitTypes.toString(to_unit)))
                # test conversion to unknown units
                res = QgsUnitTypes.fromUnitToUnitFactor(
                    from_unit, QgsUnitTypes.DistanceUnknownUnit)
                self.assertAlmostEqual(
                    res,
                    1.0,
                    msg=
                    'got {:.7f}, expected 1.0 when converting from {} to unknown units'
                    .format(res, expected_factor,
                            QgsUnitTypes.toString(from_unit)))
Example #33
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context)

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

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

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

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

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

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

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Calculating service area…'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = set()
        points = []
        lines = []

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

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

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

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

        for i in vertices:
            points.append(graph.vertex(i).point())

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Writing results…'))

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

        feat = QgsFeature()
        feat.setFields(fields)

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

        results = {}

        if point_sink is not None:
            results[self.OUTPUT] = dest_id
            geomPoints = QgsGeometry.fromMultiPointXY(points)
            feat.setGeometry(geomPoints)
            feat['type'] = 'within'
            feat['start'] = startPoint.toString()
            point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

            if include_bounds:
                upperBoundary = []
                lowerBoundary = []

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

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

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

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

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

        (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context,
                                                         fields, QgsWkbTypes.MultiLineString, network.sourceCrs())
        if line_sink is not None:
            results[self.OUTPUT_LINES] = line_dest_id
            geom_lines = QgsGeometry.fromMultiPolylineXY(lines)
            feat.setGeometry(geom_lines)
            feat['type'] = 'lines'
            feat['start'] = startPoint.toString()
            line_sink.addFeature(feat, QgsFeatureSink.FastInsert)

        return results
Example #34
0
    def processEllipse(self, layer, outname, semimajorcol, semiminorcol,
                       orientcol, unitOfMeasure, defSemiMajor, defSemiMinor,
                       defOrientation):
        measureFactor = 1.0
        # The ellipse calculation is done in Nautical Miles. This converts
        # the semi-major and minor axis to nautical miles
        if unitOfMeasure == 2:  # Nautical Miles
            measureFactor = 1.0
        elif unitOfMeasure == 0:  # Kilometers
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters,
                QgsUnitTypes.DistanceNauticalMiles) * 1000.0
        elif unitOfMeasure == 1:  # Meters
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters,
                QgsUnitTypes.DistanceNauticalMiles)
        elif unitOfMeasure == 3:  # Miles
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceFeet,
                QgsUnitTypes.DistanceNauticalMiles) * 5280.0
        elif unitOfMeasure == 4:  # Feet
            measureFactor = QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceNauticalMiles)

        fields = layer.fields()

        self.polygonLayer = QgsVectorLayer(
            "Polygon?crs={}".format(self.outputCRS.authid()), outname,
            "memory")
        ppolygon = self.polygonLayer.dataProvider()
        ppolygon.addAttributes(fields)
        self.polygonLayer.updateFields()

        iter = layer.getFeatures()
        num_features = 0
        num_good = 0
        for feature in iter:
            num_features += 1
            try:
                if semimajorcol != -1:
                    semi_major = float(feature[semimajorcol])
                else:
                    semi_major = defSemiMajor
                if semiminorcol != -1:
                    semi_minor = float(feature[semiminorcol])
                else:
                    semi_minor = defSemiMinor
                if orientcol != -1:
                    orient = float(feature[orientcol])
                else:
                    orient = defOrientation
                pt = feature.geometry().asPoint()
                # make sure the coordinates are in EPSG:4326
                pt = self.transform.transform(pt.x(), pt.y())
                pts = LatLon.getEllipseCoords(pt.y(), pt.x(),
                                              semi_major * measureFactor,
                                              semi_minor * measureFactor,
                                              orient)

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

                featureout = QgsFeature()
                featureout.setGeometry(QgsGeometry.fromPolygonXY([pts]))
                featureout.setAttributes(feature.attributes())
                ppolygon.addFeatures([featureout])
                num_good += 1
            except:
                # Just skip any lines that are badly formed
                #traceback.print_exc()
                pass
        self.polygonLayer.updateExtents()
        QgsProject.instance().addMapLayer(self.polygonLayer)
        self.iface.messageBar().pushMessage(
            "",
            "{} Ellipses created from {} records".format(
                num_good, num_features),
            level=Qgis.Info,
            duration=3)