import geopandas as gpd import folium from shapely.geometry import Point def extract_endpoints(geometry): """ Extracts the start and end points of a LineString or MultiLineString. """ points = [] if geometry.type == 'LineString': points.append(Point(geometry.coords[0])) points.append(Point(geometry.coords[-1])) elif geometry.type == 'MultiLineString': for line in geometry: points.append(Point(line.coords[0])) points.append(Point(line.coords[-1])) return points # Load the shapefile drop_cable_gdf = gpd.read_file('drop_cable.shp') # Check and transform CRS to EPSG:4326 if needed if drop_cable_gdf.crs is not None and drop_cable_gdf.crs.to_epsg() != 4326: drop_cable_gdf = drop_cable_gdf.to_crs(epsg=4326) # Extract endpoints and create a list of points endpoint_list = [] for geom in drop_cable_gdf.geometry: endpoint_list.extend(extract_endpoints(geom)) # Create a GeoDataFrame for endpoints endpoints_gdf = gpd.GeoDataFrame(geometry=endpoint_list, crs="EPSG:4326") # Convert GeoDataFrames to GeoJSON drop_cable_geojson = drop_cable_gdf.to_json() endpoints_geojson = endpoints_gdf.to_json() # Create a Folium map m = folium.Map(location=[drop_cable_gdf.geometry.iloc[0].centroid.y, drop_cable_gdf.geometry.iloc[0].centroid.x], zoom_start=12) # Add GeoJSON layers to the map folium.GeoJson(drop_cable_geojson, name="Drop Cables", style_function=lambda x: {'color': 'blue', 'weight': 2}).add_to(m) folium.GeoJson(endpoints_geojson, name="Endpoints", style_function=lambda x: {'color': 'red', 'fillColor': 'red'}).add_to(m) # Add layer control to toggle layers folium.LayerControl().add_to(m) # Save the map to an HTML file m.save('map.html')