Adding features to find public toilets and shopping streets #41
| @@ -7,6 +7,7 @@ from sklearn.decomposition import PCA | ||||
| import matplotlib.pyplot as plt | ||||
| from pydantic import BaseModel | ||||
| from OSMPythonTools.overpass import Overpass, overpassQueryBuilder | ||||
| from OSMPythonTools.cachingStrategy import CachingStrategy, JSON | ||||
| from math import sin, cos, sqrt, atan2, radians | ||||
|  | ||||
|  | ||||
| @@ -177,7 +178,7 @@ def fit_lines(points, labels): | ||||
|         else : | ||||
|             loc = ShoppingLocation( | ||||
|                 type='street', | ||||
|                 centroid=tuple(centroid), | ||||
|                 centroid=tuple((centroid[1], centroid[0])), | ||||
|                 importance = len(cluster_points), | ||||
|                 start=start_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 | ||||
|     lat, lon = shopping_location.centroid | ||||
|     bbox = ("around:500", str(lat), str(lon)) | ||||
|     bbox = ("around:1000", str(lat), str(lon)) | ||||
|      | ||||
|     overpass = Overpass() | ||||
|     # CachingStrategy.use(JSON, cacheDir=OSM_CACHE_DIR) | ||||
|  | ||||
|     # Query neighborhoods and shopping malls | ||||
|     query = overpassQueryBuilder( | ||||
|         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") | ||||
|     selectors = ['"place"~"^(suburb|neighborhood|city_block)$"', '"shop"="mall"'] | ||||
|  | ||||
|     min_dist = float('inf') | ||||
|     new_name = 'Shopping Area' | ||||
| @@ -224,21 +214,45 @@ def create_landmark(shopping_location: ShoppingLocation): | ||||
|     osm_id = 0 | ||||
|     osm_type = 'node' | ||||
|  | ||||
|     for elem in result.elements(): | ||||
|         location = (elem.centerLat(), elem.centerLon()) | ||||
|         print(f"Distance : {get_distance(shopping_location.centroid, location)}") | ||||
|         if get_distance(shopping_location.centroid, location) < min_dist : | ||||
|             new_name = elem.tag('name') | ||||
|             osm_type = elem.type()              # Add type: 'way' or 'relation' | ||||
|             osm_id = elem.id()                  # Add OSM id  | ||||
|     for sel in selectors :  | ||||
|         query = overpassQueryBuilder( | ||||
|             bbox = bbox, | ||||
|             elementType = ['node', 'way', 'relation'], | ||||
|             selector = sel, | ||||
|             includeCenter = True, | ||||
|             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 | ||||
|             try : | ||||
|                 new_name_en = elem.tag('name:en') | ||||
|             except: | ||||
|                 pass  | ||||
|         for elem in result.elements(): | ||||
|  | ||||
|             location = (elem.lat(), elem.lon()) | ||||
|  | ||||
|             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( | ||||
|         name=new_name, | ||||
| @@ -253,7 +267,9 @@ def create_landmark(shopping_location: ShoppingLocation): | ||||
|  | ||||
|  | ||||
| # 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 | ||||
| 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(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) | ||||
|  | ||||
| # Fit lines | ||||
| @@ -289,26 +306,26 @@ corners, locations = fit_lines(clustered_points, clustered_labels) | ||||
|  | ||||
| ######## 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].set_title('PCA Fitted Lines on Clusters') | ||||
|  | ||||
| # Create a list of Landmarks for the shopping things | ||||
| shopping_landmarks = [] | ||||
| 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) | ||||
|     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 ####### | ||||
| for loc in locations: | ||||
|     if loc.type == 'street' : | ||||
|         line_x = loc.start | ||||
|         line_y = loc.end | ||||
|         axes[2].plot(line_x, line_y, color='lime', linewidth=3) | ||||
|     else : | ||||
|         axes[2].scatter(loc.centroid[0], loc.centroid[1], color='None', edgecolors='lime', s=200, linewidth=3) | ||||
| # for loc in locations: | ||||
| #     if loc.type == 'street' : | ||||
| #         line_x = loc.start | ||||
| #         line_y = loc.end | ||||
| #         axes[2].plot(line_x, line_y, color='lime', linewidth=3) | ||||
| #     else : | ||||
|  | ||||
|  | ||||
| axes[2].set_title('PCA Fitted Lines on Clusters') | ||||
|  | ||||
| axes[0].set_xlim(xmin-0.01, xmax+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_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