Adding features to find public toilets and shopping streets #41
| @@ -7,6 +7,7 @@ from sklearn.decomposition import PCA | |||||||
| import matplotlib.pyplot as plt | import matplotlib.pyplot as plt | ||||||
| from pydantic import BaseModel | from pydantic import BaseModel | ||||||
| from OSMPythonTools.overpass import Overpass, overpassQueryBuilder | from OSMPythonTools.overpass import Overpass, overpassQueryBuilder | ||||||
|  | from OSMPythonTools.cachingStrategy import CachingStrategy, JSON | ||||||
| from math import sin, cos, sqrt, atan2, radians | from math import sin, cos, sqrt, atan2, radians | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -177,7 +178,7 @@ def fit_lines(points, labels): | |||||||
|         else : |         else : | ||||||
|             loc = ShoppingLocation( |             loc = ShoppingLocation( | ||||||
|                 type='street', |                 type='street', | ||||||
|                 centroid=tuple(centroid), |                 centroid=tuple((centroid[1], centroid[0])), | ||||||
|                 importance = len(cluster_points), |                 importance = len(cluster_points), | ||||||
|                 start=start_point, |                 start=start_point, | ||||||
|                 end=end_point |                 end=end_point | ||||||
| @@ -199,24 +200,13 @@ def create_landmark(shopping_location: ShoppingLocation): | |||||||
|  |  | ||||||
|     # Define the bounding box for a given radius around the coordinates |     # Define the bounding box for a given radius around the coordinates | ||||||
|     lat, lon = shopping_location.centroid |     lat, lon = shopping_location.centroid | ||||||
|     bbox = ("around:500", str(lat), str(lon)) |     bbox = ("around:1000", str(lat), str(lon)) | ||||||
|      |      | ||||||
|     overpass = Overpass() |     overpass = Overpass() | ||||||
|  |     # CachingStrategy.use(JSON, cacheDir=OSM_CACHE_DIR) | ||||||
|  |  | ||||||
|     # Query neighborhoods and shopping malls |     # Query neighborhoods and shopping malls | ||||||
|     query = overpassQueryBuilder( |     selectors = ['"place"~"^(suburb|neighborhood|city_block)$"', '"shop"="mall"'] | ||||||
|         bbox = bbox, |  | ||||||
|         elementType = ['node'], |  | ||||||
|         selector = ['"place"="suburb"'], |  | ||||||
|         includeCenter = True, |  | ||||||
|         out = 'body' |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|     try: |  | ||||||
|         result = overpass.query(query) |  | ||||||
|         print(f'query OK with {len(result.elements())} elements') |  | ||||||
|     except Exception as e: |  | ||||||
|         raise Exception("query unsuccessful") |  | ||||||
|  |  | ||||||
|     min_dist = float('inf') |     min_dist = float('inf') | ||||||
|     new_name = 'Shopping Area' |     new_name = 'Shopping Area' | ||||||
| @@ -224,21 +214,45 @@ def create_landmark(shopping_location: ShoppingLocation): | |||||||
|     osm_id = 0 |     osm_id = 0 | ||||||
|     osm_type = 'node' |     osm_type = 'node' | ||||||
|  |  | ||||||
|     for elem in result.elements(): |     for sel in selectors :  | ||||||
|         location = (elem.centerLat(), elem.centerLon()) |         query = overpassQueryBuilder( | ||||||
|         print(f"Distance : {get_distance(shopping_location.centroid, location)}") |             bbox = bbox, | ||||||
|         if get_distance(shopping_location.centroid, location) < min_dist : |             elementType = ['node', 'way', 'relation'], | ||||||
|             new_name = elem.tag('name') |             selector = sel, | ||||||
|             osm_type = elem.type()              # Add type: 'way' or 'relation' |             includeCenter = True, | ||||||
|             osm_id = elem.id()                  # Add OSM id  |             out = 'body' | ||||||
|  |         ) | ||||||
|  |  | ||||||
|             print("closer thing found") |         try: | ||||||
|  |             result = overpass.query(query) | ||||||
|  |             # print(f'query OK with {len(result.elements())} elements') | ||||||
|  |         except Exception as e: | ||||||
|  |             raise Exception("query unsuccessful") | ||||||
|  |  | ||||||
|             # add english name if it exists |         for elem in result.elements(): | ||||||
|             try : |  | ||||||
|                 new_name_en = elem.tag('name:en') |             location = (elem.lat(), elem.lon()) | ||||||
|             except: |  | ||||||
|                 pass  |             if location[0] is None :  | ||||||
|  |                 location = (elem.centerLat(), elem.centerLon()) | ||||||
|  |                 if location[0] is None :  | ||||||
|  |                     continue | ||||||
|  |  | ||||||
|  |             # print(f"Distance : {get_distance(shopping_location.centroid, location)}") | ||||||
|  |             d = get_distance(shopping_location.centroid, location) | ||||||
|  |             if  d < min_dist : | ||||||
|  |                 min_dist = d | ||||||
|  |                 new_name = elem.tag('name') | ||||||
|  |                 osm_type = elem.type()              # Add type: 'way' or 'relation' | ||||||
|  |                 osm_id = elem.id()                  # Add OSM id  | ||||||
|  |  | ||||||
|  |                 # print("closer thing found") | ||||||
|  |  | ||||||
|  |                 # add english name if it exists | ||||||
|  |                 try : | ||||||
|  |                     new_name_en = elem.tag('name:en') | ||||||
|  |                 except: | ||||||
|  |                     pass  | ||||||
|  |  | ||||||
|     return Landmark( |     return Landmark( | ||||||
|         name=new_name, |         name=new_name, | ||||||
| @@ -253,7 +267,9 @@ def create_landmark(shopping_location: ShoppingLocation): | |||||||
|  |  | ||||||
|  |  | ||||||
| # Extract points | # Extract points | ||||||
| points = extract_points('lyon_data.json') | points = extract_points('newyork_data.json') | ||||||
|  |  | ||||||
|  | # print(len(points)) | ||||||
|  |  | ||||||
| ######## Create a figure with 1 row and 3 columns for side-by-side plots | ######## Create a figure with 1 row and 3 columns for side-by-side plots | ||||||
| fig, axes = plt.subplots(1, 3, figsize=(15, 5)) | fig, axes = plt.subplots(1, 3, figsize=(15, 5)) | ||||||
| @@ -280,6 +296,7 @@ axes[1].set_title('DBSCAN Clusters') | |||||||
| axes[1].scatter(clustered_points[:, 0], clustered_points[:, 1], c=clustered_labels, cmap='rainbow', s=20) | axes[1].scatter(clustered_points[:, 0], clustered_points[:, 1], c=clustered_labels, cmap='rainbow', s=20) | ||||||
| axes[1].scatter(noise_points[:, 0], noise_points[:, 1], c='blue', s=7, label='Noise') | axes[1].scatter(noise_points[:, 0], noise_points[:, 1], c='blue', s=7, label='Noise') | ||||||
|  |  | ||||||
|  | # Keep the 5 biggest clusters | ||||||
| clustered_points, clustered_labels = filter_clusters(clustered_points, clustered_labels) | clustered_points, clustered_labels = filter_clusters(clustered_points, clustered_labels) | ||||||
|  |  | ||||||
| # Fit lines | # Fit lines | ||||||
| @@ -289,26 +306,26 @@ corners, locations = fit_lines(clustered_points, clustered_labels) | |||||||
|  |  | ||||||
| ######## Plot clustered points in normal size and noise points separately | ######## Plot clustered points in normal size and noise points separately | ||||||
| axes[2].scatter(clustered_points[:, 0], clustered_points[:, 1], c=clustered_labels, cmap='rainbow', s=30) | axes[2].scatter(clustered_points[:, 0], clustered_points[:, 1], c=clustered_labels, cmap='rainbow', s=30) | ||||||
|  | axes[2].set_title('PCA Fitted Lines on Clusters') | ||||||
|  |  | ||||||
| # Create a list of Landmarks for the shopping things | # Create a list of Landmarks for the shopping things | ||||||
| shopping_landmarks = [] | shopping_landmarks = [] | ||||||
| for loc in locations : | for loc in locations : | ||||||
|  |     axes[2].scatter(loc.centroid[0], loc.centroid[1], color='lime', marker='x', s=200, linewidth=3) | ||||||
|     landmark = create_landmark(loc) |     landmark = create_landmark(loc) | ||||||
|     shopping_landmarks.append(landmark) |     shopping_landmarks.append(landmark) | ||||||
|     print(f"{landmark.name} is a shopping area with a score of {landmark.attractiveness}") |      | ||||||
|      |      | ||||||
|  |  | ||||||
| ####### Plot the detected lines in the final plot ####### | ####### Plot the detected lines in the final plot ####### | ||||||
| for loc in locations: | # for loc in locations: | ||||||
|     if loc.type == 'street' : | #     if loc.type == 'street' : | ||||||
|         line_x = loc.start | #         line_x = loc.start | ||||||
|         line_y = loc.end | #         line_y = loc.end | ||||||
|         axes[2].plot(line_x, line_y, color='lime', linewidth=3) | #         axes[2].plot(line_x, line_y, color='lime', linewidth=3) | ||||||
|     else : | #     else : | ||||||
|         axes[2].scatter(loc.centroid[0], loc.centroid[1], color='None', edgecolors='lime', s=200, linewidth=3) |  | ||||||
|  |  | ||||||
| axes[2].set_title('PCA Fitted Lines on Clusters') |  | ||||||
|  |  | ||||||
| axes[0].set_xlim(xmin-0.01, xmax+0.01) | axes[0].set_xlim(xmin-0.01, xmax+0.01) | ||||||
| axes[0].set_ylim(ymin-0.01, ymax+0.01) | axes[0].set_ylim(ymin-0.01, ymax+0.01) | ||||||
| @@ -319,5 +336,11 @@ axes[1].set_ylim(ymin-0.01, ymax+0.01) | |||||||
| axes[2].set_xlim(xmin-0.01, xmax+0.01) | axes[2].set_xlim(xmin-0.01, xmax+0.01) | ||||||
| axes[2].set_ylim(ymin-0.01, ymax+0.01) | axes[2].set_ylim(ymin-0.01, ymax+0.01) | ||||||
|  |  | ||||||
| # plt.tight_layout() |  | ||||||
| # plt.show() | print("\n\n\n") | ||||||
|  | for landmark in shopping_landmarks : | ||||||
|  |     print(f"{landmark.name} is a shopping area with a score of {landmark.attractiveness}") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | plt.tight_layout() | ||||||
|  | plt.show() | ||||||
|   | |||||||
							
								
								
									
										42085
									
								
								backend/src/sandbox/newyork_data.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42085
									
								
								backend/src/sandbox/newyork_data.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user