Upgraded refiner
All checks were successful
Build and push docker image / Build (pull_request) Successful in 3m8s
Build and release APK / Build APK (pull_request) Successful in 5m0s
Build web / Build Web (pull_request) Successful in 1m41s

This commit is contained in:
Helldragon67 2024-06-24 11:06:01 +02:00
parent 813c83a81d
commit 8d068c80a7
8 changed files with 1126 additions and 1135 deletions

View File

@ -15,7 +15,33 @@ SHOPPING = LandmarkType(landmark_type='shopping')
# Include the json here # Include the json here
# Create a list of all things to visit given some preferences and a city. Ready for the optimizer # Create a list of all things to visit given some preferences and a city. Ready for the optimizer
def generate_landmarks(preferences: Preferences, city_country: str = None, coordinates: Tuple[float, float] = None) -> Tuple[List[Landmark], List[Landmark]] : def generate_landmarks(preferences: Preferences, coordinates: Tuple[float, float]) :
l_sights, l_nature, l_shop = get_amenities()
L = []
# List for sightseeing
if preferences.sightseeing.score != 0 :
L1 = get_landmarks(l_sights, SIGHTSEEING, coordinates=coordinates)
correct_score(L1, preferences.sightseeing)
L += L1
# List for nature
if preferences.nature.score != 0 :
L2 = get_landmarks(l_nature, NATURE, coordinates=coordinates)
correct_score(L2, preferences.nature)
L += L2
# List for shopping
if preferences.shopping.score != 0 :
L3 = get_landmarks(l_shop, SHOPPING, coordinates=coordinates)
correct_score(L3, preferences.shopping)
L += L3
return remove_duplicates(L), take_most_important(L)
"""def generate_landmarks(preferences: Preferences, city_country: str = None, coordinates: Tuple[float, float] = None) -> Tuple[List[Landmark], List[Landmark]] :
l_sights, l_nature, l_shop = get_amenities() l_sights, l_nature, l_shop = get_amenities()
L = [] L = []
@ -39,8 +65,7 @@ def generate_landmarks(preferences: Preferences, city_country: str = None, coord
L += L3 L += L3
return remove_duplicates(L), take_most_important(L) return remove_duplicates(L), take_most_important(L)
"""
# Helper function to gather the amenities list # Helper function to gather the amenities list
def get_amenities() -> List[List[str]] : def get_amenities() -> List[List[str]] :
@ -199,7 +224,71 @@ def create_bbox(coordinates: Tuple[float, float], side_length: int) -> Tuple[flo
return min_lat, min_lon, max_lat, max_lon return min_lat, min_lon, max_lat, max_lon
def get_landmarks(list_amenity: list, landmarktype: LandmarkType, city_country: str = None, coordinates: Tuple[float, float] = None) -> List[Landmark] : def get_landmarks(list_amenity: list, landmarktype: LandmarkType, coordinates: Tuple[float, float]) -> List[Landmark] :
# Read the parameters from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/landmarks_manager.params', "r") as f :
parameters = json.loads(f.read())
tag_coeff = parameters['tag coeff']
park_coeff = parameters['park coeff']
church_coeff = parameters['church coeff']
radius = parameters['radius close to']
bbox_side = parameters['city bbox side']
# Create bbox around start location
bbox = create_bbox(coordinates, bbox_side)
# Initialize some variables
N = 0
L = []
overpass = Overpass()
for amenity in list_amenity :
query = overpassQueryBuilder(bbox=bbox, elementType=['way', 'relation'], selector=amenity, includeCenter=True, out='body')
result = overpass.query(query)
N += result.countElements()
for elem in result.elements():
name = elem.tag('name') # Add name
location = (elem.centerLat(), elem.centerLon()) # Add coordinates (lat, lon)
# skip if unprecise location
if name is None or location[0] is None:
continue
# skip if unused
if 'disused:leisure' in elem.tags().keys():
continue
# skip if part of another building
if 'building:part' in elem.tags().keys() and elem.tag('building:part') == 'yes':
continue
else :
osm_type = elem.type() # Add type : 'way' or 'relation'
osm_id = elem.id() # Add OSM id
elem_type = landmarktype # Add the landmark type as 'sightseeing
n_tags = len(elem.tags().keys()) # Add number of tags
# Add score of given landmark based on the number of surrounding elements. Penalty for churches as there are A LOT
if amenity == "'amenity'='place_of_worship'" :
score = int((count_elements_within_radius(location, radius) + n_tags*tag_coeff )*church_coeff)
elif amenity == "'leisure'='park'" :
score = int((count_elements_within_radius(location, radius) + n_tags*tag_coeff )*park_coeff)
else :
score = count_elements_within_radius(location, radius) + n_tags*tag_coeff
if score is not None :
# Generate the landmark and append it to the list
landmark = Landmark(name=name, type=elem_type, location=location, osm_type=osm_type, osm_id=osm_id, attractiveness=score, must_do=False, n_tags=n_tags)
L.append(landmark)
return L
"""def get_landmarks(list_amenity: list, landmarktype: LandmarkType, city_country: str = None, coordinates: Tuple[float, float] = None) -> List[Landmark] :
if city_country is None and coordinates is None : if city_country is None and coordinates is None :
raise ValueError("Either one of 'city_country' and 'coordinates' arguments must be specified") raise ValueError("Either one of 'city_country' and 'coordinates' arguments must be specified")
@ -277,3 +366,4 @@ def get_landmarks(list_amenity: list, landmarktype: LandmarkType, city_country:
L.append(landmark) L.append(landmark)
return L return L
"""

View File

@ -1,6 +1,6 @@
from optimizer import solve_optimization from optimizer import solve_optimization
from refiner import refine_optimization
from landmarks_manager import generate_landmarks from landmarks_manager import generate_landmarks
from structs.landmarks import LandmarkTest
from structs.landmarks import Landmark from structs.landmarks import Landmark
from structs.landmarktype import LandmarkType from structs.landmarktype import LandmarkType
from structs.preferences import Preferences, Preference from structs.preferences import Preferences, Preference
@ -12,35 +12,45 @@ app = FastAPI()
# Assuming frontend is calling like this : # Assuming frontend is calling like this :
#"http://127.0.0.1:8000/process?param1={param1}&param2={param2}" #"http://127.0.0.1:8000/process?param1={param1}&param2={param2}"
@app.post("/optimizer_coords/{latitude}/{longitude}/{city_country}") @app.post("/optimizer_coords/{start_lat}/{start_lon}/{finish_lat}/{finish_lon}")
def main1(preferences: Preferences = Body(...), latitude: float = None, longitude: float = None, city_country: str = None) -> List[Landmark]: def main1(start_lat: float, start_lon: float, preferences: Preferences = Body(...), finish_lat: float = None, finish_lon: float = None) -> List[Landmark]:
if preferences is None : if preferences is None :
raise ValueError("Please provide preferences in the form of a 'Preference' BaseModel class.") raise ValueError("Please provide preferences in the form of a 'Preference' BaseModel class.")
elif latitude is None and longitude is None and city_country is None : if bool(start_lat) ^ bool(start_lon) :
raise ValueError("Please provide GPS coordinates or a 'city_country' string.") raise ValueError("Please provide both latitude and longitude for the starting point")
elif latitude is not None and longitude is not None and city_country is not None : if bool(finish_lat) ^ bool(finish_lon) :
raise ValueError("Please provide EITHER GPS coordinates or a 'city_country' string.") raise ValueError("Please provide both latitude and longitude for the finish point")
start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(start_lat, start_lon), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
# From frontend get longitude, latitude and prefence list if bool(finish_lat) and bool(finish_lon) :
if city_country is None : finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(finish_lat, finish_lon), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
coordinates = tuple((latitude, longitude)) else :
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(start_lat, start_lon), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
[], landmarks_short = generate_landmarks(preferences=preferences, city_country=city_country, coordinates=coordinates)
start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.8375946, 2.2949904), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.8375946, 2.2949904), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8375946, 2.2949904), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8375946, 2.2949904), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
# Generate the landmarks from the start location
landmarks, landmarks_short = generate_landmarks(preferences=preferences, coordinates=start.location)
# insert start and finish to the landmarks list
landmarks_short.insert(0, start) landmarks_short.insert(0, start)
landmarks_short.append(finish) landmarks_short.append(finish)
# TODO use these parameters in another way
max_walking_time = 4 # hours max_walking_time = 4 # hours
detour = 30 # minutes
visiting_list = solve_optimization(landmarks_short, max_walking_time*60, True) # First stage optimization
base_tour = solve_optimization(landmarks_short, max_walking_time*60, True)
return visiting_list # Second stage optimization
refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True)
return refined_tour

View File

@ -141,19 +141,19 @@ def get_distance(p1: Tuple[float, float], p2: Tuple[float, float], detour: float
else: else:
dist = 6371.01 * acos(sin(radians(p1[0]))*sin(radians(p2[0])) + cos(radians(p1[0]))*cos(radians(p2[0]))*cos(radians(p1[1]) - radians(p2[1]))) dist = 6371.01 * acos(sin(radians(p1[0]))*sin(radians(p2[0])) + cos(radians(p1[0]))*cos(radians(p2[0]))*cos(radians(p1[1]) - radians(p2[1])))
# Consider the detour factor for average city # Consider the detour factor for average cityto deterline walking distance (in km)
wdist = dist*detour walk_dist = dist*detour
# Time to walk this distance (in minutes) # Time to walk this distance (in minutes)
wtime = wdist/speed*60 walk_time = walk_dist/speed*60
if wtime > 15 : if walk_time > 15 :
wtime = 5*round(wtime/5) walk_time = 5*round(walk_time/5)
else : else :
wtime = round(wtime) walk_time = round(walk_time)
return round(wdist, 1), wtime return round(walk_dist, 1), walk_time
# Initialize A and c. Compute the distances from all landmarks to each other and store attractiveness # Initialize A and c. Compute the distances from all landmarks to each other and store attractiveness
@ -291,23 +291,23 @@ def respect_order(N: int, A_eq, b_eq):
# Computes the path length given path matrix (dist_table) and a result # Computes the path length given path matrix (dist_table) and a result
def add_time_to_reach(order: List[Landmark], landmarks: List[Landmark])->List[Landmark] : def add_time_to_reach(order: List[int], landmarks: List[Landmark])->List[Landmark] :
j = 0
L = []
# Read the parameters from the file # Read the parameters from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f : with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
parameters = json.loads(f.read()) parameters = json.loads(f.read())
detour = parameters['detour factor'] detour_factor = parameters['detour factor']
speed = parameters['average walking speed'] speed = parameters['average walking speed']
j = 0
L = []
prev = landmarks[0] prev = landmarks[0]
while(len(L) != len(order)) : while(len(L) != len(order)) :
elem = landmarks[order[j]] elem = landmarks[order[j]]
if elem != prev : if elem != prev :
elem.time_to_reach = get_distance(elem.location, prev.location, detour, speed)[1] elem.time_to_reach = get_distance(elem.location, prev.location, detour_factor, speed)[1]
elem.must_do = True elem.must_do = True
L.append(elem) L.append(elem)
prev = elem prev = elem
@ -315,6 +315,26 @@ def add_time_to_reach(order: List[Landmark], landmarks: List[Landmark])->List[La
return L return L
def add_time_to_reach_simple(ordered_visit: List[Landmark])-> List[Landmark] :
# Read the parameters from the file
with open (os.path.dirname(os.path.abspath(__file__)) + '/parameters/optimizer.params', "r") as f :
parameters = json.loads(f.read())
detour_factor = parameters['detour factor']
speed = parameters['average walking speed']
L = []
prev = ordered_visit[0]
L.append(prev)
for elem in ordered_visit[1:] :
elem.time_to_reach = get_distance(elem.location, prev.location, detour_factor, speed)[1]
elem.must_do = True
L.append(elem)
prev = elem
return L
# Main optimization pipeline # Main optimization pipeline
def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_details: bool) : def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_details: bool) :
@ -356,7 +376,7 @@ def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_deta
# Add the times to reach and stop optimizing # Add the times to reach and stop optimizing
L = add_time_to_reach(order, landmarks) L = add_time_to_reach(order, landmarks)
break break
print(i) #print(i)
i += 1 i += 1
if i == timeout : if i == timeout :

View File

@ -1,4 +1,4 @@
{ {
"detour factor" : 10, "detour factor" : 1.4,
"average walking speed" : 27.5 "average walking speed" : 4.8
} }

View File

@ -1,9 +1,10 @@
from shapely import buffer, LineString, Point, Polygon from shapely import buffer, LineString, Point, Polygon, MultiPoint, convex_hull, concave_hull, LinearRing
from typing import List from typing import List
from math import pi from math import pi
from structs.landmarks import Landmark from structs.landmarks import Landmark
from landmarks_manager import take_most_important from landmarks_manager import take_most_important
from optimizer import solve_optimization, add_time_to_reach_simple, print_res
def create_corridor(landmarks: List[Landmark], width: float) : def create_corridor(landmarks: List[Landmark], width: float) :
@ -34,10 +35,78 @@ def is_in_area(area: Polygon, coordinates) -> bool :
def get_minor_landmarks(all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] : def get_minor_landmarks(all_landmarks: List[Landmark], visited_landmarks: List[Landmark], width: float) -> List[Landmark] :
second_order_landmarks = [] second_order_landmarks = []
visited_names = []
area = create_corridor(visited_landmarks, width) area = create_corridor(visited_landmarks, width)
for visited in visited_landmarks :
visited_names.append(visited.name)
for landmark in all_landmarks : for landmark in all_landmarks :
if is_in_area(area, landmark.location) and landmark not in visited_landmarks: if is_in_area(area, landmark.location) and landmark.name not in visited_names:
second_order_landmarks.append(landmark) second_order_landmarks.append(landmark)
return take_most_important(second_order_landmarks) return take_most_important(second_order_landmarks)
"""def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, print_infos: bool) -> List[Landmark] :
minor_landmarks = get_minor_landmarks(landmarks, base_tour, 200)
if print_infos : print("There are " + str(len(minor_landmarks)) + " minor landmarks around the predicted path")
full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish)
full_set.append(base_tour[-1]) # add finish back
new_route = solve_optimization(full_set, max_time, print_infos)
return new_route"""
def refine_optimization(landmarks: List[Landmark], base_tour: List[Landmark], max_time: int, print_infos: bool) -> List[Landmark] :
minor_landmarks = get_minor_landmarks(landmarks, base_tour, 200)
if print_infos : print("There are " + str(len(minor_landmarks)) + " minor landmarks around the predicted path")
# full set of visitable landmarks
full_set = base_tour[:-1] + minor_landmarks # create full set of possible landmarks (without finish)
full_set.append(base_tour[-1]) # add finish back
# get a new route
new_route = solve_optimization(full_set, max_time, False)
coords = [] # Coordinates of the new route
coords_dict = {} # maps the location of an element to the element itself. Used to access the elements back once we get the geometry
# Iterate through the new route without finish
for elem in new_route[:-1] :
coords.append(Point(elem.location))
coords_dict[elem.location] = elem # if start = goal, only finish remains
# Create a concave polygon using the coordinates
better_route_poly = concave_hull(MultiPoint(coords)) # Create concave hull with "core" of route leaving out start and finish
xs, ys = better_route_poly.exterior.xy
better_route = [] # List of ordered visit
name_index = {} # Maps the name of a landmark to its index in the concave polygon
# Loop through the polygon and generate the better (ordered) route
for i,x in enumerate(xs[:-1]) :
better_route.append(coords_dict[tuple((x,ys[i]))])
name_index[coords_dict[tuple((x,ys[i]))].name] = i
# Scroll the list to have start in front again
start_index = name_index['start']
better_route = better_route[start_index:] + better_route[:start_index]
# Append the finish back and correct the time to reach
better_route.append(new_route[-1])
better_route = add_time_to_reach_simple(better_route)
if print_infos :
print("\nRefined tour (result of second stage optimization): ")
print_res(better_route, len(better_route))
return better_route

View File

@ -5,7 +5,7 @@ from landmarks_manager import generate_landmarks
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from optimizer import solve_optimization from optimizer import solve_optimization
from refiner import get_minor_landmarks from refiner import refine_optimization
from structs.landmarks import Landmark from structs.landmarks import Landmark
from structs.landmarktype import LandmarkType from structs.landmarktype import LandmarkType
from structs.preferences import Preferences, Preference from structs.preferences import Preferences, Preference
@ -80,38 +80,32 @@ def test4(coordinates: tuple[float, float]) -> List[Landmark]:
type=LandmarkType(landmark_type='shopping'), type=LandmarkType(landmark_type='shopping'),
score = 5)) score = 5))
city_country = None
landmarks, landmarks_short = generate_landmarks(preferences=preferences, city_country=city_country, coordinates=coordinates) # Create start and finish
start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=coordinates, osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=coordinates, osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
# Generate the landmarks from the start location
landmarks, landmarks_short = generate_landmarks(preferences=preferences, coordinates=start.location)
#write_data(landmarks, "landmarks.txt") #write_data(landmarks, "landmarks.txt")
# Insert start and finish to the landmarks list
landmarks_short.insert(0, start)
landmarks_short.append(finish)
start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.8375946, 2.2949904), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0) # TODO use these parameters in another way
finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8375946, 2.2949904), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
test = landmarks_short
test.insert(0, start)
test.append(finish)
max_walking_time = 4 # hours max_walking_time = 4 # hours
detour = 30 # minutes detour = 30 # minutes
visited_list = solve_optimization(test, max_walking_time*60, True) # First stage optimization
#visited_list = [Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.8375946, 2.2949904), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags=0, time_to_reach=0), Landmark(name='Palais du Louvre', type=LandmarkType(landmark_type='sightseeing'), location=(48.8614768, 2.3351677), osm_type='relation', osm_id=3262297, attractiveness=32, must_do=False, n_tags=32, time_to_reach=85), Landmark(name='Musée du Louvre', type=LandmarkType(landmark_type='sightseeing'), location=(48.8611474, 2.3358637), osm_type='relation', osm_id=7515426, attractiveness=34, must_do=False, n_tags=33, time_to_reach=1), Landmark(name='Bourse de Commerce — Pinault Collection', type=LandmarkType(landmark_type='sightseeing'), location=(48.8628167, 2.3428183), osm_type='way', osm_id=19856722, attractiveness=32, must_do=False, n_tags=32, time_to_reach=12), Landmark(name='Centre Georges Pompidou', type=LandmarkType(landmark_type='sightseeing'), location=(48.8605235, 2.3524395), osm_type='way', osm_id=55503397, attractiveness=43, must_do=False, n_tags=43, time_to_reach=15), Landmark(name='Tour Saint-Jacques', type=LandmarkType(landmark_type='sightseeing'), location=(48.8579983, 2.3489178), osm_type='way', osm_id=20326709, attractiveness=33, must_do=False, n_tags=31, time_to_reach=8), Landmark(name='Hôtel de Ville', type=LandmarkType(landmark_type='sightseeing'), location=(48.8564265, 2.352527), osm_type='relation', osm_id=284089, attractiveness=34, must_do=False, n_tags=32, time_to_reach=7), Landmark(name='Cathédrale Notre-Dame de Paris', type=LandmarkType(landmark_type='sightseeing'), location=(48.8529372, 2.3498701), osm_type='way', osm_id=201611261, attractiveness=55, must_do=False, n_tags=54, time_to_reach=9), Landmark(name='Sainte-Chapelle', type=LandmarkType(landmark_type='sightseeing'), location=(48.8553966, 2.3450136), osm_type='relation', osm_id=3344870, attractiveness=57, must_do=False, n_tags=54, time_to_reach=10), Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8375946, 2.2949904), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags=0, time_to_reach=90)] base_tour = solve_optimization(landmarks_short, max_walking_time*60, True)
# Second stage optimization
refined_tour = refine_optimization(landmarks, base_tour, max_walking_time*60+detour, True)
return refined_tour
minor_landmarks = get_minor_landmarks(landmarks, visited_list, 200) #test4(tuple((48.8344400, 2.3220540))) # Café Chez César
#write_data(minor_landmarks, 'minor_landmarks.txt') test4(tuple((48.8375946, 2.2949904))) # Point random
print("There are " + str(len(minor_landmarks)) + " minor landmarks around the predicted path")
full_set = visited_list[:-1] + minor_landmarks[:30]
full_set.append(finish)
new_route = solve_optimization(full_set, max_walking_time*60+detour, True)
return new_route
test4(tuple((48.8795156, 2.3660204)))
#test3('Vienna, Austria') #test3('Vienna, Austria')

File diff suppressed because it is too large Load Diff

View File

@ -16,86 +16,198 @@
"time_to_reach":0 "time_to_reach":0
}, },
"1":{ "1":{
"name":"Musée d'art et d'histoire du Judaïsme", "name":"Musée de Cluny",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
}, },
"location":[ "location":[
48.8612656, 48.8506604,
2.355418 2.3437398
], ],
"osm_type":"way", "osm_type":"way",
"osm_id":56687783, "osm_id":56640163,
"attractiveness":9,
"must_do":false,
"n_tags":8,
"time_to_reach":0
},
"2":{
"name":"Musée Ernest-Hébert (en travaux)",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8473326,
2.3227159
],
"osm_type":"way",
"osm_id":64314872,
"attractiveness":10,
"must_do":false,
"n_tags":9,
"time_to_reach":0
},
"3":{
"name":"Crypte Archéologique du Parvis Notre-Dame",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8535851,
2.3480846
],
"osm_type":"way",
"osm_id":159896046,
"attractiveness":18, "attractiveness":18,
"must_do":false, "must_do":false,
"n_tags":18, "n_tags":18,
"time_to_reach":0 "time_to_reach":0
}, },
"4":{ "2":{
"name":"Jardin Catherine Labouré", "name":"Musée du Luxembourg",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
}, },
"location":[ "location":[
48.8510562, 48.8485965,
2.320532 2.3340156
], ],
"osm_type":"way", "osm_type":"way",
"osm_id":148481812, "osm_id":170226810,
"attractiveness":8, "attractiveness":15,
"must_do":false, "must_do":false,
"n_tags":8, "n_tags":15,
"time_to_reach":0
},
"3":{
"name":"Musée national Eugène Delacroix",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8546662,
2.3353836
],
"osm_type":"way",
"osm_id":395785603,
"attractiveness":15,
"must_do":false,
"n_tags":15,
"time_to_reach":0
},
"4":{
"name":"Hôtel de Sully",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.854635,
2.3638126
],
"osm_type":"relation",
"osm_id":403146,
"attractiveness":14,
"must_do":false,
"n_tags":13,
"time_to_reach":0 "time_to_reach":0
}, },
"5":{ "5":{
"name":"Arc de Triomphe du Carrousel", "name":"Hôtel de la Monnaie",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
}, },
"location":[ "location":[
48.8617276, 48.856403,
2.3329082 2.3388625
], ],
"osm_type":"way", "osm_type":"relation",
"osm_id":227483542, "osm_id":967664,
"attractiveness":16, "attractiveness":11,
"must_do":false, "must_do":false,
"n_tags":11, "n_tags":11,
"time_to_reach":0 "time_to_reach":0
}, },
"6":{ "6":{
"name":"Musée Bourdelle",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8432078,
2.3186583
],
"osm_type":"relation",
"osm_id":1212876,
"attractiveness":23,
"must_do":false,
"n_tags":23,
"time_to_reach":0
},
"7":{
"name":"Musée Carnavalet",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8576819,
2.3627147
],
"osm_type":"relation",
"osm_id":2405955,
"attractiveness":25,
"must_do":false,
"n_tags":25,
"time_to_reach":0
},
"8":{
"name":"Pont Neuf",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8565248,
2.3408132
],
"osm_type":"way",
"osm_id":53574149,
"attractiveness":16,
"must_do":false,
"n_tags":15,
"time_to_reach":0
},
"9":{
"name":"Jardin du Luxembourg",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8467137,
2.3363649
],
"osm_type":"way",
"osm_id":128206209,
"attractiveness":35,
"must_do":false,
"n_tags":23,
"time_to_reach":0
},
"10":{
"name":"Cathédrale Notre-Dame de Paris",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8529372,
2.3498701
],
"osm_type":"way",
"osm_id":201611261,
"attractiveness":55,
"must_do":false,
"n_tags":54,
"time_to_reach":0
},
"11":{
"name":"Maison à l'enseigne du Faucheur",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8558553,
2.3568266
],
"osm_type":"way",
"osm_id":1123456865,
"attractiveness":13,
"must_do":false,
"n_tags":11,
"time_to_reach":0
},
"12":{
"name":"Maison à l'enseigne du Mouton",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8558431,
2.3568914
],
"osm_type":"way",
"osm_id":1123456866,
"attractiveness":13,
"must_do":false,
"n_tags":11,
"time_to_reach":0
},
"13":{
"name":"Palais de Justice de Paris", "name":"Palais de Justice de Paris",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
@ -111,7 +223,23 @@
"n_tags":24, "n_tags":24,
"time_to_reach":0 "time_to_reach":0
}, },
"7":{ "14":{
"name":"Mémorial des Martyrs de la Déportation",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8517365,
2.3524734
],
"osm_type":"relation",
"osm_id":9396191,
"attractiveness":21,
"must_do":false,
"n_tags":21,
"time_to_reach":0
},
"15":{
"name":"Fontaine des Innocents", "name":"Fontaine des Innocents",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
@ -127,7 +255,39 @@
"n_tags":15, "n_tags":15,
"time_to_reach":0 "time_to_reach":0
}, },
"8":{ "16":{
"name":"Hôtel de Sens",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8535257,
2.3588733
],
"osm_type":"way",
"osm_id":55541122,
"attractiveness":21,
"must_do":false,
"n_tags":20,
"time_to_reach":0
},
"17":{
"name":"Hôtel d'Ourscamp",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8555465,
2.3571206
],
"osm_type":"way",
"osm_id":55620201,
"attractiveness":10,
"must_do":false,
"n_tags":9,
"time_to_reach":0
},
"18":{
"name":"Hôtel de Choiseul-Praslin", "name":"Hôtel de Choiseul-Praslin",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
@ -143,23 +303,7 @@
"n_tags":12, "n_tags":12,
"time_to_reach":0 "time_to_reach":0
}, },
"9":{ "19":{
"name":"Hôtel de Cassini",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8519819,
2.3209847
],
"osm_type":"way",
"osm_id":68571376,
"attractiveness":13,
"must_do":false,
"n_tags":13,
"time_to_reach":0
},
"10":{
"name":"Chapelle Notre-Dame-des-Anges", "name":"Chapelle Notre-Dame-des-Anges",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
@ -175,7 +319,7 @@
"n_tags":16, "n_tags":16,
"time_to_reach":0 "time_to_reach":0
}, },
"11":{ "20":{
"name":"Fontaine du Palmier", "name":"Fontaine du Palmier",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
@ -191,103 +335,39 @@
"n_tags":14, "n_tags":14,
"time_to_reach":0 "time_to_reach":0
}, },
"12":{ "21":{
"name":"Colonne Médicis", "name":"Église Saint-Séverin",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
}, },
"location":[ "location":[
48.8625255, 48.8520913,
2.3429926 2.3457237
], ],
"osm_type":"way", "osm_type":"way",
"osm_id":942543401, "osm_id":19740659,
"attractiveness":15, "attractiveness":15,
"must_do":false, "must_do":false,
"n_tags":13, "n_tags":25,
"time_to_reach":0 "time_to_reach":0
}, },
"13":{ "22":{
"name":"Noviciat des Dominicains", "name":"Église Orthodoxe Roumaine des Saints Archanges",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
}, },
"location":[ "location":[
48.8561352, 48.849488,
2.3284496 2.3471975
],
"osm_type":"relation",
"osm_id":1002118,
"attractiveness":8,
"must_do":false,
"n_tags":8,
"time_to_reach":0
},
"14":{
"name":"Hôtel de Matignon",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8544393,
2.320661
],
"osm_type":"relation",
"osm_id":1076880,
"attractiveness":13,
"must_do":false,
"n_tags":13,
"time_to_reach":0
},
"15":{
"name":"Ligne de Petite Ceinture",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8597838,
2.3341775
],
"osm_type":"relation",
"osm_id":1536589,
"attractiveness":8,
"must_do":false,
"n_tags":8,
"time_to_reach":0
},
"16":{
"name":"Bateau Daphné",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8520929,
2.3494633
], ],
"osm_type":"way", "osm_type":"way",
"osm_id":618750321, "osm_id":55366403,
"attractiveness":6, "attractiveness":10,
"must_do":false, "must_do":false,
"n_tags":6, "n_tags":16,
"time_to_reach":0 "time_to_reach":0
}, },
"17":{ "23":{
"name":"Église Saint-Leu - Saint-Gilles",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8628813,
2.3500683
],
"osm_type":"way",
"osm_id":53933240,
"attractiveness":14,
"must_do":false,
"n_tags":23,
"time_to_reach":0
},
"18":{
"name":"Église Saint-Merri", "name":"Église Saint-Merri",
"type":{ "type":{
"landmark_type":"sightseeing" "landmark_type":"sightseeing"
@ -303,87 +383,23 @@
"n_tags":26, "n_tags":26,
"time_to_reach":0 "time_to_reach":0
}, },
"19":{
"name":"Église Saint-Joseph des Carmes",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8485199,
2.3302805
],
"osm_type":"way",
"osm_id":63370983,
"attractiveness":7,
"must_do":false,
"n_tags":11,
"time_to_reach":0
},
"20":{
"name":"Église Orthodoxe Saint-Séraphin de Sarov",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8426176,
2.3045363
],
"osm_type":"way",
"osm_id":80237345,
"attractiveness":7,
"must_do":false,
"n_tags":11,
"time_to_reach":0
},
"21":{
"name":"Fontaine des quatre évêques",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.85087,
2.3332776
],
"osm_type":"way",
"osm_id":40068036,
"attractiveness":8,
"must_do":false,
"n_tags":8,
"time_to_reach":0
},
"22":{
"name":"La fontaine de la Vierge",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8525605,
2.3513841
],
"osm_type":"way",
"osm_id":948654101,
"attractiveness":6,
"must_do":false,
"n_tags":6,
"time_to_reach":0
},
"23":{
"name":"Square Jean Chérioux",
"type":{
"landmark_type":"nature"
},
"location":[
48.8401918,
2.3006179
],
"osm_type":"way",
"osm_id":14334838,
"attractiveness":9,
"must_do":false,
"n_tags":5,
"time_to_reach":0
},
"24":{ "24":{
"name":"Église Saint-Germain des Prés",
"type":{
"landmark_type":"sightseeing"
},
"location":[
48.8539667,
2.334463
],
"osm_type":"way",
"osm_id":62287173,
"attractiveness":12,
"must_do":false,
"n_tags":21,
"time_to_reach":0
},
"25":{
"name":"Square de la Tour Saint-Jacques", "name":"Square de la Tour Saint-Jacques",
"type":{ "type":{
"landmark_type":"nature" "landmark_type":"nature"
@ -399,7 +415,7 @@
"n_tags":12, "n_tags":12,
"time_to_reach":0 "time_to_reach":0
}, },
"25":{ "26":{
"name":"Square Jean XXIII", "name":"Square Jean XXIII",
"type":{ "type":{
"landmark_type":"nature" "landmark_type":"nature"
@ -415,52 +431,36 @@
"n_tags":15, "n_tags":15,
"time_to_reach":0 "time_to_reach":0
}, },
"26":{
"name":"Jardinet place du lieutenant Henri-Karcher",
"type":{
"landmark_type":"nature"
},
"location":[
48.8632971,
2.3399434
],
"osm_type":"way",
"osm_id":53826866,
"attractiveness":8,
"must_do":false,
"n_tags":5,
"time_to_reach":0
},
"27":{ "27":{
"name":"Square de l'Abbé Esquerré", "name":"Square Félix Desruelles",
"type":{ "type":{
"landmark_type":"nature" "landmark_type":"nature"
}, },
"location":[ "location":[
48.8503173, 48.8536974,
2.3136601 2.3345069
], ],
"osm_type":"way", "osm_type":"way",
"osm_id":103344111, "osm_id":62287123,
"attractiveness":11, "attractiveness":12,
"must_do":false, "must_do":false,
"n_tags":7, "n_tags":7,
"time_to_reach":0 "time_to_reach":0
}, },
"28":{ "28":{
"name":"Jardin Nelson Mandela", "name":"Jardin des Rosiers Joseph-Migneret",
"type":{ "type":{
"landmark_type":"nature" "landmark_type":"nature"
}, },
"location":[ "location":[
48.8626235, 48.8572946,
2.344487 2.3602516
], ],
"osm_type":"way", "osm_type":"way",
"osm_id":159103475, "osm_id":365878540,
"attractiveness":23, "attractiveness":14,
"must_do":false, "must_do":false,
"n_tags":15, "n_tags":8,
"time_to_reach":0 "time_to_reach":0
}, },
"29":{ "29":{