def calculate_transfer_nodes(self):
        '''
        calculate the position and weights of the initial transfer nodes
        '''
        # tbx settings
        inner_circle = self.distance
        mid_circle = inner_circle + 500
        outer_circle = inner_circle + self.outer_circle

        # calculate routes
        project_epsg = settings.EPSG
        otp_router = OTPRouter(distance=inner_circle, epsg=project_epsg)

        self.itineraries.table.truncate()

        for i, area in enumerate(self.areas):
            self.log(f'Suche Routen ausgehend von Teilfläche {area.name}...')
            connector = self.connectors.get(id_teilflaeche=area.id)
            qpoint = connector.geom.asPoint()
            source = Point(id=area.id, x=qpoint.x(), y=qpoint.y(),
                           epsg=project_epsg)

            # calculate segments around centroid
            inner_dest = otp_router.create_circle(
                source, dist=mid_circle, n_segments=self.n_segments)
            outer_dest = otp_router.create_circle(
                source, dist=outer_circle, n_segments=self.n_segments)
            destinations = np.concatenate([inner_dest, outer_dest])
            source.transform(otp_router.router_epsg)

            # calculate the routes to the segments
            for (x, y) in destinations:
                destination = Point(x, y, epsg=project_epsg)
                destination.transform(otp_router.router_epsg)
                otp_router.route(source, destination)
            self.set_progress(80 * (i + 1) / len(self.areas))

        otp_router.build_graph(distance=inner_circle)
        otp_router.remove_redundancies()

        self.log('Berechne Herkunfts-/Zielpunkte aus den Routen...')
        otp_router.transfer_nodes.calc_initial_weight()

        transfer_nodes_df = otp_router.get_transfer_node_features()
        self.transfer_nodes.table.truncate()
        transfer_nodes_df['fid'] = range(1, len(transfer_nodes_df) + 1)
        self.transfer_nodes.update_pandas(transfer_nodes_df)

        for transfer_node in otp_router.transfer_nodes.values():
            tn_idx = transfer_nodes_df['node_id'] == transfer_node.node_id
            tn_id = transfer_nodes_df[tn_idx]['fid'].values[0]
            for route in transfer_node.routes.values():
                points = [QgsPoint(node.x, node.y) for node in route.nodes]
                polyline = QgsGeometry.fromPolyline(points)
                self.itineraries.add(geom=polyline, route_id=route.route_id,
                                     transfer_node_id=tn_id)
Example #2
0
    def calculate_distances(self, progress_start=0, progress_end=100):
        '''
        calculate distances between settlement points and markets and
        write them to the database
        '''

        # calculate bounding box
        bbox = get_bbox(self.cells.table)
        epsg = self.project.settings.EPSG
        routing = DistanceRouting(target_epsg=epsg, resolution=300)
        destinations = []
        for cell in self.cells:
            pnt = cell.geom.asPoint()
            destinations.append(Point(pnt.x(), pnt.y(), id=cell.id, epsg=epsg))
        already_calculated = np.unique(self.relations.values('id_markt'))
        self.markets.reset()
        n_markets = len(self.markets)
        progress_step = (progress_end - progress_start) / n_markets
        i = 1
        results = {}
        for market in self.markets:
            self.log(f' - {market.name} ({i}/{n_markets})')
            if market.id not in already_calculated:
                self.log('  wird berechnet')
                pnt = market.geom.asPoint()
                origin = Point(pnt.x(), pnt.y(), id=market.id, epsg=epsg)
                try:
                    distances, beelines = routing.get_distances(
                        origin, destinations, bbox)
                    if (distances >= 0).sum() == 0:
                        self.message.emit(
                            'Der Markt ist nicht erreichbar. Er liegt entweder '
                            'weit außerhalb des Betrachtungsraums oder konnte '
                            'nicht an das Straßennetz angebunden werden.')
                except Exception as e:
                    self.error.emit(str(e))
                    return
                results[market.id] = destinations, distances, beelines
                #self.distances_to_db(market.id, destinations, distances,
                #beelines)
            else:
                self.log('  bereits berechnet, wird übersprungen')
            self.set_progress(progress_start + (i * progress_step))
            i += 1
        # workaround: ogr crashes when setting relations in loop
        if len(results) > 0:
            self.message.emit('Speichere Distanzen...')
        for market_id, (destinations, distances, beelines) in results.items():
            self.distances_to_db(market_id, destinations, distances, beelines)
    def write_centers_stops(self):
        '''
        get centers in radius around project centroid, write their closest
        stops and the stops near the project to the db
        '''
        # truncate tables, will be filled in progress
        self.haltestellen.delete()
        self.zentrale_orte.delete()

        centroid = self.project_frame.geom.asPoint()
        df_central = self.project.basedata.get_table(
            'Zentrale_Orte', 'Basisdaten_deutschland').to_pandas()
        df_oz = df_central[df_central['OZ'] == 1]
        df_mz = df_central[df_central['OZ'] == 0]

        oz_points = [p.asPoint() for p in df_oz['geom'].values]
        mz_points = [p.asPoint() for p in df_mz['geom'].values]
        oz_points, oz_within = points_within(centroid, oz_points, radius=70000)
        mz_points, mz_within = points_within(centroid, mz_points, radius=30000)
        df_oz_within = df_oz[oz_within]
        df_mz_within = df_mz[mz_within]

        def get_closest_stops(points):
            stops = []
            for point in points:
                t_p = Point(point[0], point[1],
                            epsg=settings.EPSG)
                t_p.transform(4326)
                stops_near = self.query.stops_near((t_p.x, t_p.y), n=1)
                if len(stops_near) > 0:
                    closest = stops_near[0]
                    stops.append(closest)
            return stops

        oz_stops = get_closest_stops(oz_points)
        mz_stops = get_closest_stops(mz_points)
        if (len(oz_stops) + len(mz_stops)) == 0:
            return

        df_oz_within['id_haltestelle'] = [s.id for s in oz_stops]
        df_mz_within['id_haltestelle'] = [s.id for s in mz_stops]

        df_within = pd.concat([df_oz_within, df_mz_within])
        df_within['name'] = df_within['GEN']
        df_within['id_zentraler_ort'] = df_within['fid']

        del df_within['fid']
        self.zentrale_orte.update_pandas(df_within)

        p_centroid = Point(centroid.x(), centroid.y(),
                           epsg=settings.EPSG)
        p_centroid.transform(4326)
        tfl_stops = self.query.stops_near((p_centroid.x, p_centroid.y), n=10)

        self._stops_to_db(oz_stops)
        self._stops_to_db(mz_stops)
        self._stops_to_db(tfl_stops, is_project_stop=1)
 def route_transfer_nodes(self):
     '''
     routing between transfer nodes and area connectors
     '''
     self.links.table.truncate()
     project_epsg = settings.EPSG
     #route_ids = {}
     otp_router = OTPRouter(epsg=project_epsg)
     transform = QgsCoordinateTransform(
         QgsCoordinateReferenceSystem(OTPRouter.router_epsg),
         QgsCoordinateReferenceSystem(project_epsg),
         QgsProject.instance()
     )
     for i, area in enumerate(self.areas):
         self.log(f'Suche Routen zwischen Teilfläche {area.name} und den '
                  'Herkunfts-/Zielpunkten...')
         connector = self.connectors.get(id_teilflaeche=area.id)
         qpoint = connector.geom.asPoint()
         pcon = Point(id=area.id, x=qpoint.x(), y=qpoint.y(),
                      epsg=project_epsg)
         pcon.transform(OTPRouter.router_epsg)
         for transfer_node in self.transfer_nodes:
             qpoint = transfer_node.geom.asPoint()
             pnode = Point(id=transfer_node.id, x=qpoint.x(), y=qpoint.y(),
                           epsg=project_epsg)
             pnode.transform(otp_router.router_epsg)
             out_route = otp_router.route(pcon, pnode)
             in_route = otp_router.route(pnode, pcon)
             for route in out_route, in_route:
                 if not route:
                     continue
                 for link in route.links:
                     geom = QgsGeometry()
                     from_id = link.from_node.node_id
                     to_id = link.to_node.node_id
                     lg = link.get_geom()
                     if from_id == to_id or not lg:
                         continue
                     geom.fromWkb(lg.ExportToWkb())
                     geom.transform(transform)
                     self.links.add(from_node_id=from_id, to_node_id=to_id,
                                    transfer_node_id=transfer_node.id,
                                    area_id=area.id, geom=geom)
         self.set_progress(80 * (i + 1) / len(self.areas))
 def get_closest_stops(points):
     stops = []
     for point in points:
         t_p = Point(point[0], point[1],
                     epsg=settings.EPSG)
         t_p.transform(4326)
         stops_near = self.query.stops_near((t_p.x, t_p.y), n=1)
         if len(stops_near) > 0:
             closest = stops_near[0]
             stops.append(closest)
     return stops
Example #6
0
    def work(self):
        self.einrichtungen.delete()
        query = GeoserverQuery()
        radius = self.radius * 1000
        centroid = self.project_frame.geom.asPoint()
        epsg = settings.EPSG
        centroid = Point(centroid.x(), centroid.y(), epsg=epsg)
        self.log('Frage Geoserver an...')
        features = query.get_features(centroid, radius, self.categories, epsg)
        self.log(f'Schreibe {len(features)} Einrichtungen in die Datenbank...')

        for feat in features:
            self.einrichtungen.add(name=feat.name,
                                   projektcheck_category=feat.category,
                                   geom=feat.geom)
    def work(self):
        mode, walk_speed = self.modes[self.modus]
        self.log(f'Ermittle die Isochronen für den Modus "{self.modus}"')
        conn_id = self.connector.id if self.connector else -1
        self.isochronen.filter(modus=self.modus, id_connector=conn_id)
        self.isochronen.delete()
        self.isochronen.reset()
        point = self.connector.geom.asPoint() if self.connector \
            else self.project_frame.geom.asPoint()

        epsg = settings.EPSG
        point = Point(point.x(), point.y(), epsg=epsg)
        cutoff_step = self.cutoff_sec / self.n_steps
        for i in reversed(range(self.n_steps)):
            sec = int(cutoff_step * (i + 1))
            self.log(f'...maximale Reisezeit von {sec} Sekunden')
            json_res = self._get_isochrone(point, mode, sec, walk_speed)
            if not json_res:
                continue
            iso_poly = ogr.CreateGeometryFromJson(json.dumps(json_res))
            geom = QgsGeometry.fromWkt(iso_poly.ExportToWkt())
            tr = QgsCoordinateTransform(
                QgsCoordinateReferenceSystem('epsg:4326'),
                QgsCoordinateReferenceSystem(f'epsg:{epsg}'),
                QgsProject.instance())
            geom.transform(tr)
            # the router sometimes returns broken geometries
            if not geom.isGeosValid():
                geom = geom.makeValid()
                # the junk is appended to a collection, discard it
                if geom.wkbType() == QgsWkbTypes.GeometryCollection:
                    geom = geom.asGeometryCollection()[0]
            self.isochronen.add(modus=self.modus,
                                sekunden=sec,
                                minuten=round(sec / 60, 1),
                                geom=geom,
                                id_connector=conn_id)
            self.set_progress(100 * (self.n_steps - i + 1) / self.n_steps)
Example #8
0
    def work(self):
        # get markets in minimal bounding polygon
        communities = Centers.features(project=self.project).filter(
            auswahl__ne=0, nutzerdefiniert=-1)
        geometries = [f.geom for f in communities]
        multi_poly = minimal_bounding_poly(geometries)
        multi_poly = multi_poly.buffer(self.buffer, 1)
        if self.truncate:
            osm_markets = Markets.features(project=self.project).filter(
                is_osm=True)
            n = len(osm_markets)
            if n > 0:
                self.log('Lösche vorhandene OSM-Märkte...')
                osm_markets.delete()
                self.log(f'{n} OSM-Märkte gelöscht')
            else:
                self.log('Keine OSM-Märkte vorhanden.')

        self.log('Sende Standortanfrage an Geoserver...')
        reader = OSMShopsReader(epsg=self.epsg)
        markets = []
        for poly in multi_poly.asGeometryCollection():
            # minimal bounding geometry shouldn't contain holes, so it is safe
            # take the first one (all have length = 1)
            polygon = [
                Point(p.x(), p.y(), epsg=self.epsg)
                for p in poly.asPolygon()[0]
            ]
            m = reader.get_shops(polygon, count=self._max_count - len(markets))
            markets += m

        self.set_progress(30)
        self.log(f'{len(markets)} Märkte gefunden')
        self.log('Verschneide gefundene Märkte...')

        communities = Centers.features(project=self.project).filter(
            nutzerdefiniert=-1, auswahl__ne=0)
        in_com_ids = intersect(markets,
                               communities,
                               input_fields=['id'],
                               epsg=self.epsg,
                               buffer=self.buffer)
        in_com_ids = [str(i['id']) for i in in_com_ids]
        markets_in_com = [m for m in markets if str(m.id) in in_com_ids]

        self.set_progress(50)
        self.log(f'Schreibe {len(markets_in_com)} Märkte in die Datenbank...')
        parsed = self.parse_meta(markets_in_com)

        self.markets_to_db(
            parsed,
            truncate=False,  # already truncated osm markets
            is_osm=True)

        self.set_progress(60)
        osm_markets = Markets.features(project=self.project).filter(is_osm=1)
        n = remove_duplicates(osm_markets, match_field='id_kette', distance=50)
        self.log(f'{n} Duplikate entfernt...')
        self.set_progress(80)
        self.log('Ermittle die AGS der Märkte...')
        self.set_ags(osm_markets)