mirror of
https://github.com/marvinscham/masterthesis-playground.git
synced 2026-03-22 00:12:42 +01:00
117 lines
3.6 KiB
Python
117 lines
3.6 KiB
Python
# bali_map.py
|
|
# Creates an interactive HTML map of Bali (and nearby islands) with readable, always-visible labels.
|
|
|
|
import folium
|
|
|
|
DESTINATIONS = {
|
|
"Sacred Monkey Forest": (
|
|
-8.5187511,
|
|
115.2585973,
|
|
), # :contentReference[oaicite:0]{index=0}
|
|
"Uluwatu Temple": (
|
|
-8.8291432,
|
|
115.0849069,
|
|
), # :contentReference[oaicite:1]{index=1}
|
|
"Sanur Beach": (-8.673889, 115.263611), # :contentReference[oaicite:2]{index=2}
|
|
"Tanah Lot Temple": (
|
|
-8.618786,
|
|
115.086733,
|
|
), # :contentReference[oaicite:3]{index=3}
|
|
"Seminyak Beach": (-8.6925, 115.158611), # :contentReference[oaicite:4]{index=4}
|
|
"Nusa Dua": (-8.791918, 115.225375), # :contentReference[oaicite:5]{index=5}
|
|
"Bali Zoo": (-8.59128, 115.26456), # :contentReference[oaicite:6]{index=6}
|
|
"Mount Batur": (-8.23889, 115.37750), # :contentReference[oaicite:7]{index=7}
|
|
"Ulun Danu Bratan": (
|
|
-8.275177,
|
|
115.1668487,
|
|
), # :contentReference[oaicite:8]{index=8}
|
|
"Tirta Gangga": (-8.411944, 115.5875), # :contentReference[oaicite:9]{index=9}
|
|
"Pandawa Beach": (-8.84586, 115.18417), # :contentReference[oaicite:10]{index=10}
|
|
"Jimbaran Bay": (-8.79093, 115.16006), # :contentReference[oaicite:11]{index=11}
|
|
"Double Six Beach": (
|
|
-8.6975074,
|
|
115.1610332,
|
|
), # :contentReference[oaicite:12]{index=12}
|
|
"Devil Tears": (-8.6905650, 115.4302884), # :contentReference[oaicite:13]{index=13}
|
|
"Kelingking Beach": (
|
|
-8.750644,
|
|
115.474693,
|
|
), # :contentReference[oaicite:14]{index=14}
|
|
"Lempuyang Temple": (
|
|
-8.395195,
|
|
115.647885,
|
|
), # :contentReference[oaicite:15]{index=15}
|
|
"Canggu Beach": (-8.639877, 115.140172), # :contentReference[oaicite:16]{index=16}
|
|
"Mount Agung": (-8.340686, 115.503622), # :contentReference[oaicite:17]{index=17}
|
|
}
|
|
|
|
# --- Map base ---
|
|
m = folium.Map(
|
|
location=(-8.45, 115.20),
|
|
zoom_start=9,
|
|
tiles="CartoDB positron",
|
|
control_scale=True,
|
|
zoom_snap=0.1,
|
|
zoom_delta=0.1,
|
|
max_zoom=18,
|
|
)
|
|
|
|
# --- Label styling (readable, always visible) ---
|
|
LABEL_STYLE = """
|
|
padding: 3px 6px;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #111;
|
|
white-space: nowrap;
|
|
"""
|
|
|
|
# Per-label pixel offsets (x, y). Positive y moves the label down.
|
|
LABEL_OFFSETS = {
|
|
"Nusa Dua": (0, 20),
|
|
"Double Six Beach": (0, 20),
|
|
}
|
|
|
|
|
|
def add_point_with_label(name: str, lat: float, lon: float):
|
|
# Small dot at the exact coordinate
|
|
folium.CircleMarker(
|
|
location=(lat, lon),
|
|
radius=4,
|
|
weight=2,
|
|
fill=True,
|
|
fill_opacity=1.0,
|
|
tooltip=name, # still useful on hover
|
|
).add_to(m)
|
|
|
|
# Slightly offset label so it doesn't sit directly on the dot
|
|
offset_x, offset_y = LABEL_OFFSETS.get(name, (0, 0))
|
|
base_anchor_x, base_anchor_y = (-8, 12)
|
|
folium.Marker(
|
|
location=(lat, lon),
|
|
icon=folium.DivIcon(
|
|
icon_size=(1, 1),
|
|
icon_anchor=(
|
|
base_anchor_x + offset_x,
|
|
base_anchor_y - offset_y,
|
|
), # pixel offset: left/up relative to point
|
|
html=f'<div style="{LABEL_STYLE}">{name}</div>',
|
|
),
|
|
).add_to(m)
|
|
|
|
|
|
# Add all destinations
|
|
lats, lons = [], []
|
|
for name, (lat, lon) in DESTINATIONS.items():
|
|
add_point_with_label(name, lat, lon)
|
|
lats.append(lat)
|
|
lons.append(lon)
|
|
|
|
# Fit map bounds to include Nusa Penida / Lembongan as well
|
|
pad = 0.005
|
|
m.fit_bounds([[min(lats) - pad, min(lons) - pad], [max(lats) + pad, max(lons) + pad]])
|
|
|
|
# Output
|
|
out_file = "bali_destinations_labeled.html"
|
|
m.save(out_file)
|
|
print(f"Saved: {out_file}")
|