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)
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
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)
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)