🇬🇧 English
This works like the space game: small steps, and after almost every one you run it and see something new.
You will use a class again — one Place, fourteen times, with different numbers. If you did the game, this will feel familiar fast.
You need Python first. If you do not have it, do Start Python on a Mac.
🇹🇭 ไทย
บทนี้ทำงานเหมือนเกมอวกาศ คือแบ่งเป็นขั้นเล็ก ๆ และหลังเกือบทุกขั้น คุณจะได้สั่งรันแล้วเห็นอะไรใหม่
คุณจะได้ใช้คลาสอีกครั้ง Place หนึ่งคลาส สร้างสิบสี่ครั้ง ด้วยตัวเลขต่างกัน ถ้าคุณทำเกมมาแล้ว จะคุ้นเร็วมาก
ต้องมี Python ก่อน ถ้ายังไม่มี ให้ทำ บทเริ่มต้น Python บน Mac
🇨🇳 中文
这一课的节奏和太空游戏一样:一小步一小步,几乎每步做完都能运行一下,看到新东西。
你会再次用到类 —— 一个 Place,用十四次,每次数字不同。做过那个游戏的话,很快就会觉得眼熟。
你需要先装好 Python。还没装就先做在 Mac 上开始学 Python。
0 Get ready · เตรียมตัว · 做好准备
🇬🇧 English
We use a library called folium. It makes a real map you can drag and zoom, and saves it as an HTML file. You open that file in your browser.
You do not need an account. You do not need a key. The map pictures come free from OpenStreetMap, which people all over the world draw together.
🇹🇭 ไทย
เราจะใช้ไลบรารีชื่อ folium มันสร้างแผนที่จริงที่ลากและซูมได้ แล้วบันทึกเป็นไฟล์ HTML คุณเปิดไฟล์นั้นในเบราว์เซอร์
ไม่ต้องสมัครบัญชี ไม่ต้องใช้คีย์ ภาพแผนที่มาจาก OpenStreetMap ฟรี ซึ่งคนทั่วโลกช่วยกันวาด
🇨🇳 中文
我们用一个叫 folium 的库。它能做出可以拖动、缩放的真实地图,并保存成一个 HTML 文件,你用浏览器打开它。
不需要注册账号,也不需要密钥。地图图像来自 OpenStreetMap,是全世界的人一起画出来的,免费。
pip3 install folium
mkdir ~/Documents/Code/maps
cd ~/Documents/Code/maps
vim chiang_mai_map.py
1 The entry point · จุดเริ่มต้นของโปรแกรม · 程序的入口
🇬🇧 English
The same start as always. Our work goes inside main, and the last two lines tell Python to run it.
If this looks familiar, good. Every Python program you write begins like this.
🇹🇭 ไทย
เริ่มเหมือนเดิมทุกครั้ง งานของเราอยู่ใน main และสองบรรทัดสุดท้ายบอก Python ให้รันมัน
ถ้ารู้สึกคุ้น ๆ ก็ดีแล้ว โปรแกรม Python ทุกตัวที่คุณเขียนเริ่มแบบนี้
🇨🇳 中文
还是一样的开头。我们的代码写在 main 里,最后两行告诉 Python 去运行它。
看着眼熟就对了。你写的每个 Python 程序都是这样开始的。
def main():
print("Making a map of Chiang Mai...")
if __name__ == "__main__":
main() python3 chiang_mai_map.py prints one line.
python3 chiang_mai_map.py จะพิมพ์ข้อความหนึ่งบรรทัด
python3 chiang_mai_map.py 打印一行字。
2 Two numbers find any place on earth · ตัวเลขสองตัวชี้ตำแหน่งได้ทั้งโลก · 两个数字就能找到地球上任何地方
🇬🇧 English
Before the map, the one idea you need.
Every place on earth has two numbers:
- latitude — how far north. 0 at the equator, 90 at the north pole, and minus below the equator.
- longitude — how far east. It goes up to 180 going east, and down to minus 180 going west.
Chiang Mai is at about 18.79 north and 98.99 east. Always in that order: lat first, lon second. Swap them and your map will show a spot in Africa.
Beijing is at 116.39 east — a bigger number, because it is further east than us. Casa Bonita, a restaurant in Colorado, is at -105.07. The minus means west. Everywhere in the Americas has a minus longitude.
The numbers after the dot matter. Four numbers after the dot is about 11 metres — enough to point at one building.
🇹🇭 ไทย
ก่อนจะทำแผนที่ มีแนวคิดเดียวที่ต้องรู้
ทุกที่บนโลกมีตัวเลขสองตัว
- ละติจูด — อยู่เหนือแค่ไหน 0 คือเส้นศูนย์สูตร 90 คือขั้วโลกเหนือ และติดลบเมื่ออยู่ใต้เส้นศูนย์สูตร
- ลองจิจูด — อยู่ตะวันออกแค่ไหน ไปทางตะวันออกได้ถึง 180 และไปทางตะวันตกได้ถึง ลบ 180
เชียงใหม่อยู่ราว ๆ 18.79 เหนือ และ 98.99 ตะวันออก เรียงลำดับแบบนี้เสมอ lat ก่อน lon ทีหลัง ถ้าสลับกัน แผนที่จะไปโผล่ที่แอฟริกา
ปักกิ่งอยู่ที่ 116.39 ตะวันออก ตัวเลขมากกว่าเรา เพราะอยู่ไปทางตะวันออกมากกว่า ส่วนคาซาโบนิต้า ร้านอาหารในรัฐโคโลราโด อยู่ที่ -105.07 เครื่องหมายลบแปลว่าตะวันตก ทุกที่ในทวีปอเมริกามีลองจิจูดติดลบ
ตัวเลขหลังจุดทศนิยมสำคัญมาก สี่ตำแหน่งหลังจุดคือประมาณ 11 เมตร พอที่จะชี้ไปที่อาคารหลังเดียวได้
🇨🇳 中文
做地图之前,先记住一个概念。
地球上每个地方都有两个数字:
- 纬度 —— 往北多远。赤道是 0,北极是 90,赤道以南是负数。
- 经度 —— 往东多远。向东最大到 180,向西到负 180。
清迈大约在北纬 18.79、东经 98.99。顺序永远是先纬度、后经度。写反了,你的地图会指到非洲去。
北京在东经 116.39 —— 数字比我们大,因为它更靠东。而美国科罗拉多州的餐厅 Casa Bonita 在 -105.07。负号表示西边。整个美洲的经度都是负的。
小数点后的位数很重要。小数点后四位大约是 11 米 —— 足够指到某一栋楼。
# lat, lon — always in this order
CENTRE = (18.7883, 98.9853) # the middle of the old city
# 18.7883, 98.9853 Chiang Mai -> north of the equator, east
# 39.9057, 116.3913 Beijing -> further east, so a bigger number
# 39.7419, -105.0710 Casa Bonita -> MINUS means west of the zero line
3 Make the map · สร้างแผนที่ · 生成地图
🇬🇧 English
Three lines make a real map.
zoom_start is how close you begin. 13 shows the whole city. 15 shows the old city. 18 shows one street.
The map does not appear on your screen. It is saved to a file. Open chiang_mai_map.html in your browser — you can drag it and zoom it like any map.
🇹🇭 ไทย
สามบรรทัดก็ได้แผนที่จริงแล้ว
zoom_start คือระดับการซูมตอนเริ่ม 13 เห็นทั้งเมือง 15 เห็นเมืองเก่า 18 เห็นถนนเส้นเดียว
แผนที่จะไม่โผล่บนหน้าจอทันที แต่ถูกบันทึกเป็นไฟล์ ให้เปิด chiang_mai_map.html ในเบราว์เซอร์ แล้วลากและซูมได้เหมือนแผนที่ทั่วไป
🇨🇳 中文
三行就能做出一张真地图。
zoom_start 是初始的缩放级别。13 能看到整座城市,15 是古城范围,18 就是一条街。
地图不会直接出现在屏幕上,而是保存成一个文件。用浏览器打开 chiang_mai_map.html,就能像用普通地图一样拖动和缩放。
from pathlib import Path
import folium
CENTRE = (18.7883, 98.9853)
OUT_FILE = Path(__file__).resolve().parent / "chiang_mai_map.html"
def main():
the_map = folium.Map(location=CENTRE, zoom_start=13, tiles="OpenStreetMap")
the_map.save(str(OUT_FILE))
print(f"Saved: {OUT_FILE}")
if __name__ == "__main__":
main() chiang_mai_map.html. You have a map of Chiang Mai.
สั่งรัน แล้วเปิด chiang_mai_map.html คุณได้แผนที่เชียงใหม่แล้ว
运行它,然后打开 chiang_mai_map.html。你有一张清迈地图了。
4 Your first pin · หมุดแรกของคุณ · 你的第一个图钉
🇬🇧 English
A Marker is a pin. Give it a place and it stands there.
tooltip shows when you hover. popup shows when you click.
🇹🇭 ไทย
Marker คือหมุด บอกตำแหน่งให้มัน แล้วมันจะไปปักตรงนั้น
tooltip จะขึ้นตอนเอาเมาส์ไปวาง ส่วน popup จะขึ้นตอนคลิก
🇨🇳 中文
Marker 就是一个图钉。告诉它位置,它就立在那儿。
鼠标悬停时显示 tooltip,点击时显示 popup。
folium.Marker(
location=[18.78776, 98.99327],
tooltip="Tha Phae Gate",
popup="The east gate of the old city",
).add_to(the_map) 5 A class for a place · สร้างคลาสสำหรับสถานที่ · 给地点写一个类
🇬🇧 English
Fourteen pins written out like that would be 70 lines, and you could not sort them or count them.
So we make a class. One Place holds everything about one spot: its names, its two numbers, what kind of place it is, and a note.
Then place.lat is the latitude of this place, and place.add_to(the_map) puts this place on the map. Same dot as always.
🇹🇭 ไทย
ถ้าเขียนหมุดสิบสี่อันแบบข้างบน จะยาวถึง 70 บรรทัด แถมเรียงลำดับหรือนับจำนวนก็ไม่ได้
เราจึงสร้าง คลาส ขึ้นมา Place หนึ่งตัวเก็บทุกอย่างของสถานที่หนึ่งแห่ง ทั้งชื่อ ตัวเลขสองตัว ประเภทของสถานที่ และคำอธิบาย
จากนั้น place.lat ก็คือ ละติจูดของสถานที่นี้ และ place.add_to(the_map) ก็คือเอาสถานที่นี้ไปวางบนแผนที่ จุดเดิมที่คุณรู้จักดี
🇨🇳 中文
照上面那样写十四个图钉要 70 行,而且没法排序、没法计数。
所以我们写一个类。一个 Place 装下一个地点的全部信息:名字、两个数字、属于哪一类、还有一句说明。
然后 place.lat 就是这个地点的纬度,place.add_to(the_map) 就是把这个地点放到地图上。还是那个点。
COLOURS = {
"temple": "purple",
"market": "orange",
"travel": "blue",
"landmark": "red",
"school": "green",
"nature": "darkgreen",
}
ICONS = {
"temple": "place-of-worship",
"market": "cart-shopping",
"travel": "plane",
"landmark": "landmark",
"school": "graduation-cap",
"nature": "tree",
}
class Place:
def __init__(self, name, thai, lat, lon, kind, note):
self.name = name # English name
self.thai = thai # Thai name
self.lat = lat # how far north
self.lon = lon # how far east
self.kind = kind # "temple", "market", "travel", ...
self.note = note # one line for the popup
def colour(self):
return COLOURS.get(self.kind, "gray")
def icon(self):
return ICONS.get(self.kind, "circle-info")
def popup(self):
return f"<b>{self.name}</b><br>{self.thai}<br><i>{self.note}</i>"
def add_to(self, the_map):
folium.Marker(
location=[self.lat, self.lon],
popup=folium.Popup(self.popup(), max_width=260),
tooltip=self.name,
icon=folium.Icon(color=self.colour(), icon=self.icon(), prefix="fa"),
).add_to(the_map)
6 Fourteen places, one loop · สิบสี่สถานที่ ลูปเดียว · 十四个地点,一个循环
🇬🇧 English
Here is the payoff, the same one as in the space game.
We wrote Place once. Now we make fourteen of them with different names, different numbers and different kinds. Then two lines put every one of them on the map.
Every coordinate below is real. They were all checked on OpenStreetMap.
🇹🇭 ไทย
นี่คือผลตอบแทน อันเดียวกับในเกมอวกาศ
เราเขียน Place ครั้งเดียว แล้วสร้างมันสิบสี่ตัว ด้วยชื่อ ตัวเลข และประเภทที่ต่างกัน จากนั้น สองบรรทัด ก็เอาทุกตัวขึ้นแผนที่
พิกัดทุกตัวข้างล่างเป็นของจริง ตรวจสอบกับ OpenStreetMap มาแล้วทั้งหมด
🇨🇳 中文
回报来了,和太空游戏里的那个一样。
我们只写了一次 Place,现在造出十四个,名字、数字、类别各不相同。然后两行就把它们全放上地图。
下面每一个坐标都是真的,全部在 OpenStreetMap 上核对过。
PLACES = [
Place("Wat Phra That Doi Suthep", "วัดพระธาตุดอยสุเทพ", 18.80501, 98.92218,
"temple", "On the mountain. 306 steps to the top."),
Place("Wat Phra Singh", "วัดพระสิงห์", 18.78821, 98.98138,
"temple", "The biggest temple inside the old city."),
Place("Wat Chedi Luang", "วัดเจดีย์หลวง", 18.78714, 98.98678,
"temple", "A huge old chedi, broken by an earthquake."),
Place("Wat Don Chan", "วัดดอนจั่น", 18.76021, 99.03257,
"temple", "Temple and school for children in Tha Sala."),
Place("Tha Phae Gate", "ประตูท่าแพ", 18.78776, 98.99327,
"landmark", "The east gate of the old city wall."),
Place("Three Kings Monument", "อนุสาวรีย์สามกษัตริย์", 18.79023, 98.98735,
"landmark", "The three kings who founded the city in 1296."),
Place("Warorot Market", "ตลาดวโรรส", 18.79024, 99.00053,
"market", "Big day market. Food, cloth, everything."),
# ... eight more in the finished file ...
]
# Two places nowhere near Chiang Mai. Same class, no changes needed.
FAR_AWAY = [
Place("Casa Bonita", "คาซาโบนิต้า", 39.74194, -105.07103,
"far", "A very large Mexican restaurant in Lakewood, Colorado."),
Place("Beijing", "ปักกิ่ง", 39.90571, 116.39130,
"far", "The capital of China. Almost the same latitude as Casa Bonita."),
] for place in PLACES:
place.add_to(the_map)
for place in FAR_AWAY:
place.add_to(the_map)
Place class holds all sixteen.
แผนที่เดิม ซูมออกจนสุด คาซาโบนิต้าในโคโลราโด ปักกิ่ง และหมุดเชียงใหม่ที่ซ้อนกันอยู่ในประเทศไทย คลาส Place เดียวเก็บได้ทั้งสิบหกแห่ง
同一张地图,缩到最小。科罗拉多的 Casa Bonita、北京,还有挤在泰国的那一堆清迈图钉。一个 Place 类装下了全部十六个。
7 Draw a shape — the old city · วาดรูปทรง — เมืองเก่า · 画一个形状 —— 古城
🇬🇧 English
Maps are not only pins. A Polygon joins points into a shape.
The old city is almost a square, with a moat around it. Four corners is enough.
Zoom in when you run this. The red square sits right on top of the moat road.
🇹🇭 ไทย
แผนที่ไม่ได้มีแต่หมุด Polygon เชื่อมจุดหลาย ๆ จุดให้เป็นรูปทรง
เมืองเก่าเกือบเป็นสี่เหลี่ยมจัตุรัส มีคูเมืองล้อมรอบ ใช้สี่มุมก็พอ
ลองซูมเข้าไปดูตอนรัน สี่เหลี่ยมสีแดงจะทาบอยู่บนถนนรอบคูเมืองพอดี
🇨🇳 中文
地图上不只有图钉。Polygon 把若干个点连成一个形状。
古城几乎是个正方形,四周有护城河。四个角就够了。
运行后放大看看,红色方框正好压在护城河那圈路上。
# The four corners of the old city moat. These are close, not exact.
OLD_CITY = [
(18.7949, 98.9791), # north west
(18.7949, 98.9933), # north east
(18.7807, 98.9933), # south east
(18.7807, 98.9791), # south west
]
def add_old_city(the_map):
folium.Polygon(
locations=OLD_CITY,
color="#b03030",
weight=3,
fill=True,
fill_opacity=0.08,
popup="The old city moat (roughly)",
).add_to(the_map)
8 How far is it, really? · ไกลแค่ไหนกันแน่ · 到底有多远?
🇬🇧 English
This is the part that makes it geography and not just drawing.
You cannot just subtract the numbers. The earth is a ball, so one degree of longitude is 111 km at the equator but only 105 km here in Chiang Mai. The lines get closer together as you go north.
The haversine formula does it properly. Copy it — nobody remembers it.
One honest warning. This gives the straight line, the way a bird flies. The road up to Doi Suthep bends all the way around the mountain, so the drive is about twice this number.
🇹🇭 ไทย
นี่คือส่วนที่ทำให้มันเป็น ภูมิศาสตร์ ไม่ใช่แค่การวาดรูป
คุณลบตัวเลขกันตรง ๆ ไม่ได้ เพราะโลกกลม ลองจิจูดหนึ่งองศาเท่ากับ 111 กม. ที่เส้นศูนย์สูตร แต่ที่เชียงใหม่เหลือแค่ 105 กม. ยิ่งขึ้นเหนือเส้นยิ่งชิดกัน
สูตร haversine คำนวณให้ถูกต้อง คัดลอกไปใช้ได้เลย ไม่มีใครจำสูตรนี้ได้หรอก
ข้อควรระวังที่ต้องบอกตามตรง สูตรนี้ให้ระยะเส้นตรง แบบที่นกบิน แต่ถนนขึ้นดอยสุเทพวนอ้อมภูเขา ระยะขับรถจริงจึงประมาณสองเท่าของตัวเลขนี้
🇨🇳 中文
这一部分才让它成为地理,而不只是画画。
你不能直接把数字相减。地球是个球,经度一度在赤道上是 111 公里,但在清迈只有 105 公里 —— 越往北,经线靠得越近。
haversine(半正矢)公式能算对。直接抄就行,没人背得下来。
一句老实话。这算的是直线距离,也就是鸟飞的路线。上素贴山的公路绕着山盘上去,实际开车大约是这个数字的两倍。
import math
def distance_km(a, b):
"""How far apart are two places, in kilometres?"""
radius = 6371.0 # the earth, in km
lat1, lon1, lat2, lon2 = map(math.radians, [a.lat, a.lon, b.lat, b.lon])
d_lat = lat2 - lat1
d_lon = lon2 - lon1
h = math.sin(d_lat / 2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin(d_lon / 2) ** 2
return 2 * radius * math.asin(math.sqrt(h))def find(name):
"""Get one place out of the list by its name."""
for place in PLACES:
if place.name == name:
return place
return None distance_km(find("Chiang Mai Airport"), find("Tha Phae Gate")). You get 3.8 km.
ลองพิมพ์ distance_km(find("Chiang Mai Airport"), find("Tha Phae Gate")) จะได้ 3.8 กม.
打印 distance_km(find("Chiang Mai Airport"), find("Tha Phae Gate")),得到 3.8 公里。
9 A line and a circle · เส้นและวงกลม · 一条线和一个圆
🇬🇧 English
PolyLine joins places in order — a walk, a bus route, a river.
Circle draws a real distance on the ground. radius=5000 means 5000 metres, and it stays 5 km wide however far you zoom in or out.
Notice the walk adds up its own length using distance_km. The map and the maths use the same numbers.
🇹🇭 ไทย
PolyLine เชื่อมสถานที่ตามลำดับ จะเป็นเส้นทางเดิน สายรถเมล์ หรือแม่น้ำก็ได้
Circle วาดระยะทางจริงบนพื้น radius=5000 หมายถึง 5000 เมตร และมันกว้าง 5 กม. เสมอ ไม่ว่าคุณจะซูมเข้าหรือออก
สังเกตว่าเส้นทางเดินคำนวณความยาวของตัวเองด้วย distance_km แผนที่กับการคำนวณใช้ตัวเลขชุดเดียวกัน
🇨🇳 中文
PolyLine 按顺序把地点连起来 —— 一条步行路线、一条公交线、一条河都行。
Circle 画的是地面上的真实距离。radius=5000 表示 5000 米,无论你怎么缩放,它始终是 5 公里宽。
注意那条步行路线是用 distance_km 自己算出总长的。地图和计算用的是同一组数字。
def add_temple_walk(the_map):
stops = ["Wat Phra Singh", "Wat Chedi Luang", "Tha Phae Gate"]
points = [(find(name).lat, find(name).lon) for name in stops]
folium.PolyLine(
locations=points,
color="#1e6660",
weight=5,
opacity=0.8,
tooltip="A short temple walk",
).add_to(the_map)
total = 0.0
for first, second in zip(stops, stops[1:]):
total += distance_km(find(first), find(second))
return total
def add_airport_circle(the_map):
airport = find("Chiang Mai Airport")
folium.Circle(
location=[airport.lat, airport.lon],
radius=5000, # metres
color="#2a6cb0",
weight=2,
fill=True,
fill_opacity=0.06,
popup="5 km from the airport",
).add_to(the_map) 10 Two map styles · สลับสไตล์แผนที่ · 两种地图样式
🇬🇧 English
The pictures under your pins are called tiles. You can have more than one set and switch between them.
show=False means the plain style is there but hidden at the start. LayerControl adds the little button at the top right.
🇹🇭 ไทย
ภาพที่อยู่ใต้หมุดของคุณเรียกว่า tiles คุณมีได้มากกว่าหนึ่งชุด แล้วสลับไปมาได้
show=False หมายความว่าสไตล์แบบเรียบมีอยู่ แต่ซ่อนไว้ตอนเริ่ม ส่วน LayerControl คือปุ่มเล็ก ๆ ที่มุมขวาบน
🇨🇳 中文
图钉下面那些图片叫做 瓦片(tiles)。你可以准备好几套,随时切换。
show=False 表示朴素样式已经加上了,但一开始不显示。LayerControl 就是右上角那个小按钮。
folium.TileLayer("CartoDB positron", name="Plain", show=False).add_to(the_map) folium.LayerControl().add_to(the_map)
11 The whole program · โปรแกรมทั้งหมด · 完整的程序
🇬🇧 English
Here is the finished file, with all fourteen places and everything joined up. Download it and compare it with yours.
It prints the distances too, and opens the map in your browser by itself.
🇹🇭 ไทย
นี่คือไฟล์ที่เสร็จแล้ว มีครบทั้งสิบสี่สถานที่และต่อทุกอย่างเข้าด้วยกัน ดาวน์โหลดไปเทียบกับของคุณได้
มันพิมพ์ระยะทางออกมาด้วย และเปิดแผนที่ในเบราว์เซอร์ให้เองเลย
🇨🇳 中文
这是完成后的文件,十四个地点齐全,所有部分都接好了。下载下来和你自己的对照。
它还会打印出距离,并自动在浏览器里打开地图。
cd ~/Documents/Code/maps
python3 chiang_mai_map.py
Put 14 places on the map.
The temple walk is 1.3 km.
Doi Suthep is 7.7 km from Tha Phae Gate
...but that is the straight line. The road up the mountain is much longer.
12 Now change it · ลองแก้ดู · 现在动手改它
🇬🇧 English
The best one is the first one: put your own house or school on the map.
Go to openstreetmap.org, find the spot, right-click it and choose Show address. The two numbers appear at the top left. Copy them into a new Place(...).
That is real mapping work. Somebody walked around your neighbourhood and drew it, so that you could do this.
🇹🇭 ไทย
ข้อที่ดีที่สุดคือข้อแรก เอาบ้านหรือโรงเรียนของคุณขึ้นแผนที่
ไปที่ openstreetmap.org หาตำแหน่งที่ต้องการ คลิกขวาแล้วเลือก Show address ตัวเลขสองตัวจะขึ้นที่มุมซ้ายบน คัดลอกมาใส่ใน Place(...) อันใหม่
นั่นคืองานทำแผนที่ของจริง มีคนเดินสำรวจแถวบ้านคุณแล้ววาดมันไว้ คุณถึงทำแบบนี้ได้
🇨🇳 中文
最值得做的是第一条:把你自己的家或学校放上地图。
打开 openstreetmap.org,找到那个位置,右键选 Show address,左上角就会出现那两个数字。抄进一个新的 Place(...) 里。
这就是真正的地图工作。有人走遍你家附近把它画了下来,你今天才能这么做。
| Try this | How | Level |
|---|---|---|
| Add your own school or house | One more Place(...) in the list. Get the numbers from OpenStreetMap: right-click the spot and choose Show address. | easy |
| Change the colours | Edit the COLOURS dictionary. Try "temple": "darkred". | easy |
| Start zoomed in | Change zoom_start=13 to 16. | easy |
| Make the circle 2 km | radius=5000 becomes radius=2000. | easy |
| Print the five closest places to your house | Use distance_km and sorted(PLACES, key=...). | harder |
| Add a market walk | Copy add_temple_walk, change the three stops to markets. | harder |
| Put a whole province on the map | Swap the list for towns in Chiang Mai province and change zoom_start to 9. | harder |