db_query / utils /kml_creator.py
DavMelchi's picture
add KML generation options
cbbcd31
import io
import math
import numpy as np
import pandas as pd
import simplekml
def create_sector(kml: simplekml.Kml, row, arc_angle=65):
"""Create a sector shape for the telecom antenna in KML with sector details."""
code, name, azimuth, lon, lat, size, color = (
row["code"],
row["name"],
row["Azimut"],
row["Longitude"],
row["Latitude"],
row["size"],
row["color"],
)
num_points = 20 # Number of points for smooth arc
start_angle = azimuth - (arc_angle / 2)
end_angle = azimuth + (arc_angle / 2)
coords = [(lon, lat)] # Start with the site location (center point)
# Generate points for the sector arc
for angle in np.linspace(start_angle, end_angle, num_points):
angle_rad = math.radians(angle)
arc_lon = lon + (size / 111320) * math.sin(angle_rad)
arc_lat = lat + (size / 111320) * math.cos(angle_rad)
coords.append((arc_lon, arc_lat))
coords.append((lon, lat)) # Close the polygon
# Create the sector polygon
pol = kml.newpolygon(name=name, outerboundaryis=coords)
# Dynamically create the description from all DataFrame columns
description = "<b>Sector Details:</b><br>"
for column, value in row.items():
description += f"<b>{column}:</b> {value}<br>"
pol.description = description
pol.style.polystyle.color = color # Set color from DataFrame
pol.style.polystyle.outline = 1 # Outline enabled
pol.style.linestyle.color = "ff000000" # Black outline
def generate_kml_from_df(df: pd.DataFrame):
"""Generate a KML file from a Pandas DataFrame for telecom sectors."""
kml = simplekml.Kml()
site_added = set() # Keep track of sites already added to avoid duplicates
# Sort the DataFrame to ensure 900 MHz (smaller) is drawn last (on top)
df_sorted = df.sort_values(
by="size", ascending=False
) # Larger first, smaller on top
for _, row in df_sorted.iterrows():
code, lon, lat = row["code"], row["Longitude"], row["Latitude"]
# Add site name as a point only once
if code not in site_added:
pnt = kml.newpoint(name=code, coords=[(lon, lat)])
pnt.style.iconstyle.icon.href = (
"http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png"
)
pnt.style.labelstyle.scale = 1.2 # Adjust label size
pnt.description = f"Site: {code}<br>Location: {lat}, {lon}"
site_added.add(code)
create_sector(kml, row)
kml_data = io.BytesIO()
kml_str = kml.kml() # Get KML as string
kml_data.write(kml_str.encode("utf-8")) # Write KML to BytesIO
kml_data.seek(0) # Move to beginning of BytesIO
return kml_data