Dichtstbijzijnde faciliteit zoeken met Origin-Destination Matrix (QGIS3)

In de vorige handleiding, Basis netwerk visualisatie en routeren (QGIS3), leerden we hoe een netwerk te bouwen en het kortste pad tussen 2 punten te berekenen. We kunnen die techniek ook toepassen voor verschillende typen op netwerken gebaseerde analyses. Een van die toepassingen is om de Origin-Destination Matrix of OD Matrix te berekenen. Gegeven een set van punten van origine en een andere set voor bestemmingspunten kunnen we het kortste pad berekenen tussen elke paar van origine-bestemming en de reisafstand/tijd daartussen berekenen. Een dergelijke analyse is nuttig om de dichtstbijzijnde faciliteit tot een bepaald punt te lokaliseren. Een logistiek bedrijf zou, bijvoorbeeld, deze analyse kunnen gebruiken om de dichtstbijzijnde opslagplaats voor hun klanten te zoeken om bestelroutes te optimaliseren. Hier gebruiken we het algoritme Distance Matrix uit de plug-in QGIS Network Analysis Toolbox (QNEAT3) om de dichtstbijzijnde gezondheidsfaciliteit voor elk adres in de stad te zoeken.

Notitie

Deze handleiding laat zien hoe uw eigen gegevens voor een netwerk te gebruiken om een origin-destination matrix te berekenen. Als u geen gegevens heeft voor een eigen netwerk kunt u de ORS Tools Plugin en het algoritme ORS Tools ‣ Matrix ‣ Matrix from Layers gebruiken om een soortgelijke analyse uit te voeren met behulp van gegevens van OpenStreetMap. Bekijk Analyse Servicegebied met Openrouteservice (QGIS3) om te leren hoe de plug-in ORS Tools te gebruiken.

Overzicht van de taak

We zullen 2 lagen nemen voor Washington DC - een met punten die adressen weergeven en een andere met punten die faciliteiten voor geestelijke gezondheid weergeven - en de faciliteit zoeken met de minste reisafstand vanaf elk adres.

Andere vaardigheden die u zult leren

  • Een willekeurig monster uit een puntenlaag uitnemen.

  • Virtuele lagen gebruiken om een query van SQL uit te voeren op een laag van QGIS.

De gegevens ophalen

De overheid van het district of Columbia deelt gratis honderden gegevenssets in de Open Data Catalog.

Download de volgende gegevenslagen als Shapefiles.

Voor het gemak kunt u direct een kopie van de gegevensset downloaden vanaf de links hieronder:

Roadway_Block-shp.zip

Address_Points.zip

Adult_Mental_Health_Providers.zip

Gegevensbron: [DCOPENDATA]

Instellen

Ga naar Plug-ins ‣ Plug-ins beheren en installeren. Selecteer :guilabel:` Alles` om te zoeken naar de plug-in QNEAT3 en installeer die. Klik op Close.

../../_images/setup11.png

Procedure

  1. Zoek in het paneel Browser naar het bestand Roadway_Block-shp.zip. Vergroot het en sleep het bestand Roadway_Block.shp naar het kaartvenster. Zoek op dezelfde manier naar het bestand Adult_Mental_Health_Providers.zip, vergroot het en voeg Adult_Mental_Health_Providers.shp toe aan het kaartvenster.

../../_images/1103.png
  1. Zoek vervolgens naar het bestand Address_Points.zip, vergroot het en voeg het bestand Address_Points.shp toe. U zult heel veel punten zien in de stad. Elke punt geeft een geldig adres weer. We zullen nu 1000 willekeurige punten selecteren. Deze techniek wordt random sampling (willekeurige monsterneming) genoemd. Ga naar Processing ‣ Toolbox.

../../_images/260.png
  1. Zoek en lokaliseer het algoritme Vector selectie ‣ Willekeurig uitnemen.

../../_images/336.png
  1. Selecteer Address_Points als de Invoerlaag, Number of feature als de Methode en voer in 1000 in het Aantal/percentage objecten. In het veld Uitgenomen (willekeurig) kies de en klik Opslaan als bestand. Kies nu de map en voer als naam in address_point_subset.shp en klik op Uitvoeren.

../../_images/418.png

Notitie

Omdat het algoritme 1000 willekeurige punten uit zal nemen uit de verstrekte gegevensset, om de exacte punten te repliceren voor deze oefening, kunt u hier address_point_subset.zip het bestand met de subset downloaden die we bij het uitvoeren van het algoritme hebben verkregen. Laad, na het downloaden, de laag address_point_subset.shp in QGIS.

  1. Een nieuwe laag address_point_subset zal worden toegevoegd aan het paneel Lagen, u kunt de zichtbaarheid voor de laag met adrespunten Address_Points uitschakelen.

../../_images/519.png
  1. Klik met rechts op de laag address_point_subset en selecteer Laag hernoemen.

../../_images/619.png
  1. Laten we deze laag hernoemen naar origin_points. Hernoem op soortgelijke manier de laag Adult_Mental_Health_Providers die de faciliteiten voor geestelijke gezondheid weergeeft als destination_points. Het op deze manier hernoemen van de lagen maakt het eenvoudiger om ze te identificeren in de aansluitende verwerking.

../../_images/718.png
  1. Zoek naar het algoritme QNEAT3 ‣ Distance matrices ‣ OD Matrix from Layers as Line (m:n). Als u dit algoritme niet ziet in de Toolbox, overtuig u er dan van dat u de plug-in QNEAT3 hebt geïnstalleerd.

../../_images/818.png
  1. Dit algoritme helpt bij het zoeken naar de afstanden langs het netwerk tussen geselecteerde lagen voor origine en bestemming. Selecteer Roadway_Block als de Network layer. Selecteer origin_points als de From-Points layer en OBJECTID als de Unique Point ID field. Stel op dezelfde manier destination_points in als de To-Points Layer en OBJECTID_1 als het Unique Point ID field. Stel Optimization Criterion in op Shortest Path (distance optimization).

../../_images/918.png
  1. Omdat veel straten in het netwerk een-richting zijn, moeten we de Advanced parameters instellen om de richting te specificeren. Bekijk Basis netwerk visualisatie en routeren (QGIS3) voor meer details over hoe deze attributen zijn gestructureerd. Kies SUMMARYDIR als het Direction field. Voer OB als de waarde voor Value for forward direction en IB als die voor Value for backward direction, en BD als de Value for the both direction. Stel de Topology tolerance in op 0.0000150. Laat de andere waarden op hun standaardwaarden staan en klik op Uitvoeren.

../../_images/1020.png
  1. Een nieuwe tabellaag, genaamd Output OD Matrix, zal worden toegevoegd aan het paneel Lagen. Klik met rechts en selecteer Attributentabel openen. U zult zien dat de tabel 13000 rijen bevat. We hadden 13 punten van origine en 1000 bestemmingspunten - dus de uitvoer bevat 13x1000 = 13000 paren voor origine en bestemming. De kolom total_cost bevat de afstand in meters tussen elk punt van origine tot elke bestemmingspunt.

../../_images/1123.png
  1. Voor deze handleiding zijn we alleen geïnteresseerd in het bestemmingspunt met de kortste afstand. We kunnen een query voor SQL maken om de bestemming met de minste total_cost uit alle bestemmingen te kiezen. Ga naar Processing ‣ Toolbox

../../_images/1221.png
  1. Zoek naar en selecteer het algoritme Vector algemeen ‣ SQL uitvoeren, selecteer in Aanvullende databronnen voor invoer, selecteer de Output OD Matrix en klik op OK. Klik nu op Expressie onder SQL query.

../../_images/1320.png
  1. Voer de volgende query in het dialoogvenster SQL-query in. Voer geometry in als het Geometrie-veld en selecteer LineString als het Geometry type. Klik op Uitvoeren.

select origin_id, destination_id, min(total_cost) as shortest_distance, geometry
from input1 group by origin_id
../../_images/1418.png
  1. Een nieuwe virtuele laag SQL-uitvoer zal worden toegevoegd aan het paneel Lagen. Deze laag bevat de resultaten van onze analyse. Het dichtstbijzijnde centrum voor geestelijke gezondheid voor elk van de 1000 punten van origine. Laten we eens een paar verschillende manieren proberen om deze resultaten te visualiseren en te valideren.

../../_images/1517.png
  1. Laten we, om dit te valideren, het Kortste pad bouwen. Het punt (OBJECTID_1 = 853046) is visueel gelegen nabij het gezondheidscentrum (OBJECTID = 3), maar vanuit de SQL-query is het verbonden met het gezondsheidscentrum (OBJECTID = 9). Laten we dit valideren door de feitelijke afstand te zoeken tussen deze twee origines en bestemming. Laten we eerst het algoritme Korste pad uitoeren op 1 paar. Zoek naar het algoritme QNEAT3 ‣ Routing ‣ Shortest path (point to point) en start het.

../../_images/1616.png
  1. Selecteer Roadway_Block als de Network layer. We dienen een begin- en eindpunt te kiezen. U kunt klikken op de knop naast het Start point en klik op het punt van origine (OBJECTID_1 = 853046) in het kaartvenster. Selecteer op dezelfde manier het bestemmingspunt (OBJECTID = 3) als het End point. Behoud het Optimization Criterion als Shortest Path (distance optimization). Vergroot het gedeelte Gevorderde parameters. Kies SUMMARYDIR als het Direction field. Voer OB in als de Value for forward direction en IB als de Value for backward direction. Stel de Topology tolerance in als 0.000015. Laat de andere waarden op hun standaardwaarden staan en klik op Uitvoeren. Wijzig nu het bestemmingspunt naar (OBJECTID = 9) in End point en klik op Uitvoeren

../../_images/1717.png
  1. Twee nieuwe lagen Shortest Path Layer zullen worden toegevoegd aan het paneel Lagen. U zult zien dat hoewel het bestemmingspunt (OBJECTID = 9) visueel dichter bij het punt van origine is, de feitelijke afstand langer is dan vergeleken met het bestemmingspunt (OBJECTID = 3).

../../_images/1815.png
  1. Onthoud dat hoewel de lijnen het punt van origine en de bestemming verbinden met een rechte lijn, de bestemming werd gevonden met de afstand langs het netwerk. Het zal veel nuttiger zijn als de visualisatie het feitelijke kortste pad weergeeft tussen elk punt van origine en bestemming. Vanaf hier is er geen eenvoudige manier om het kortste pad te maken tussen meerdere paren origine-bestemming op de manier waarop we de afstandsmatrix hebben gemaakt. Maar ik zal een manier demonstreren om wat scripten voor Python te gebruiken om deze visualisatie te maken. Laten we eerst het algoritme voor het kortste pad uitvoeren op 1 paar. Zoek naar het algoritme QNEAT3 ‣ Routing ‣ Shortest path (point to point) en start het.

../../_images/1914.png
  1. Selecteer, in het dialoogvenster Shortest Path (Point to Point), Roadway_Block als de Network layer. Behoud het Optimization criterion als Shortest Path (distance optimization). Vervolgens dienen we een begin- en eindpunt te kiezen. U kunt op de knop klikken naast Start point en op het punt van origine in het kaartvenster klikken. Selecteer op dezelfde manier het bestemmingspunt als het End point. Vergroot het gedeelte Gevorderde parameters. Kies SUMMARYDIR als het Direction field. Voer OB in als de Value for forward direction en IB als de Value for backward direction. Voer in Topology tollerance in 0.000015. Laat de andere waarden op hun standaardwaarden staan en klik op Uitvoeren.

../../_images/2011.png
  1. Een nieuwe laag Shortest Path Layer zal worden toegevoegd aan het paneel Lagen. U zult zien dat dit pad het netwerk volgt in plaats van het punt van origine en bestemming te verbinden met een rechte lijn. De reden dat we het algoritme uitvoerden op 1 paar is om eenvoudig de waarden voor de parameters te identificeren die we in ons script kunnen gebruiken. Selecteer Shortest Path Layer, klik met rechts en selecteer Laag verwijderen. Klik op de knop Geschiedenis in de Toolbox van Processing.

../../_images/2115.png
  1. Selecteer, in het dialoogvenster Geschiedenis, de laatste opdracht (opdracht die is gebruikt voor Shortest path). Deze opdracht geeft alle parameters en hun waarden weer die we hebben gebruikt. We kunnen nu deze waarden gebruiken en ze in een script zetten dat ons in staat stelt deze opdracht uit te voeren op veel paren origine-bestemming. Klik op Close.

../../_images/2214.png
  1. Klik, in de Toolbox van Processing, op de knop Scripts en selecteer Nieuw script maken.

../../_images/2313.png
  1. In Processing Script bewerken, kopieer/plak de onderstaande code. Sla het bestand op als get_routes_from_matrix.py. Sluit nu Processing Script bewerken. Als u een andere gegevensset gebruikt dan die we gebruiken voor deze handleiding dient u het script bij te werken met de waarden van de parameters uit stap 22.

import requests
import processing
from PyQt5.QtCore import QCoreApplication
from qgis.core import (QgsProcessing, QgsProcessingAlgorithm, 
    QgsProcessingParameterFeatureSource, QgsProcessingParameterFeatureSink,
    QgsFeatureSink)


class MatrixToRoutes(QgsProcessingAlgorithm):
    """Creats Routes from Distance Matrix"""
    NETWORK = 'NETWORK'
    MATRIX = 'MATRIX'
    OUTPUT = 'OUTPUT'

    
    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterFeatureSource(
                'NETWORK',
                self.tr('Network Layer'),
                types=[QgsProcessing.TypeVectorLine]
            )
        )
        
        self.addParameter(
            QgsProcessingParameterFeatureSource(
                'MATRIX',
                self.tr('Distance Matrix Layer'),
                types=[QgsProcessing.TypeVectorLine]
            )
        )
        
        
        self.addParameter(
            QgsProcessingParameterFeatureSink(
                self.OUTPUT,
                'Network Routes',
                QgsProcessing.TypeVectorLine
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsString(parameters, self.NETWORK, context)
        matrix = self.parameterAsSource(parameters, self.MATRIX, context)
        
        sink, dest_id = self.parameterAsSink(
            parameters,
            self.OUTPUT,
            context,
            matrix.fields(),
            matrix.wkbType(),
            matrix.sourceCrs()
            )
        
        # Compute the number of steps to display within the progress bar and
        # get features from source
        total = 100.0 / matrix.featureCount() if matrix.featureCount() else 0
        features = matrix.getFeatures()
        
        coordinate_list = []
        for current, f in enumerate(features):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break
            line = f.geometry().asPolyline()
            origin_coords = line[0].x(), line[0].y()
            destination_coords = line[1].x(), line[1].y()

            feedback.setProgress(int(current * total))

            params = {
            'INPUT':network,
            'START_POINT':'{},{}'.format(origin_coords[0], origin_coords[1]),
            'END_POINT':'{},{}'.format(destination_coords[0], destination_coords[1]),
            'STRATEGY':0,
            'ENTRY_COST_CALCULATION_METHOD':0,
            'DIRECTION_FIELD':'SUMMARYDIR',
            'VALUE_FORWARD':'OB',
            'VALUE_BACKWARD':'IB',
            'VALUE_BOTH':'',
            'DEFAULT_DIRECTION':2,
            'SPEED_FIELD':None,
            'DEFAULT_SPEED':5,
            'TOLERANCE':0,
            'OUTPUT':'memory:'}
            
            route_layer = processing.run("qneat3:shortestpathpointtopoint", params)['OUTPUT']
            
            if route_layer:
                # We expect only 1 feature in the output, so use next() to get the first item
                route_f = next(route_layer.getFeatures())
                output_geom = route_f.geometry()
                f.setGeometry(output_geom)
                sink.addFeature(f, QgsFeatureSink.FastInsert)
            feedback.setProgressText('Processed feature {}'.format(current))

  
        return {self.OUTPUT: sink} 

    def name(self):
        return 'routes_from_matrix'

    def displayName(self):
        return self.tr('Get Routes from Matrix')
        
    def shortHelpString(self):
        return self.tr('Creates Route Layer from the result of Distance Matrix algorithm')

    def group(self):
        return self.tr(self.groupId())

    def groupId(self):
        return ''

    def tr(self, string):
        return QCoreApplication.translate('Processing', string)

    def createInstance(self):
        return MatrixToRoutes()
../../_images/2411.png
  1. Nu kunnen we het script testen. Selecteer een aantal verbindingen uit de laag SQL-uitvoer waarvoor u de feitelijke routes wilt hebben berekend. In de Toolbox van Processing zal een nieuwe keuzelijst Scripts worden toegevoegd. Klik er op en selecteer Get Routes from Matrix.

../../_images/2510.png

Notitie

Dit script moet de netwerkgrafiek berekenen voor elke doorloop en is dus vrij traag. Wanneer u veel paren origine-bestemming hebt, kan het lang duren.

  1. In Network Layer selecteer Roadway_Block en in Distance Matrix Layer selecteer SQL-uitvoer, en selecteer dan Alleen geselecteerde objecten. Klik op Uitvoeren.

../../_images/269.png
  1. Een nieuwe laag Network Routes zal worden toegevoegd aan het paneel Lagen. Die zal de feitelijke routes naar de bestemming bevatten.

../../_images/279.png
comments powered by Disqus