"""GSHHG locator geometry retained; labels adapted for the H01 reader.
Derivative geometry provenance and LGPL texts accompany each package.
This is physical geography, not a reconstruction of historic boundaries.
"""
from pathlib import Path
from html import escape
import json, math
from shapely.geometry import Polygon, box
from c01_visuals import arrow
ROOT=Path(__file__).resolve().parents[1]
LAND='#e4e5ca'; SEA='#e6f0ee'; INK='#29473f'; MUTED='#617369'
COAST=json.loads((ROOT/'research/g01-geometry/coast-asia.json').read_text())
POLYS=[]
for item in COAST:
p=Polygon(item['coordinates'])
if not p.is_valid:p=p.buffer(0)
POLYS.append((p,item['type']))
PLACES={'Nara':(135.805,34.685),'Kyoto':(135.769,35.011),'Kamakura':(139.55,35.32),'Osaka':(135.502,34.69),'Edo / Tokyo':(139.752,35.685),'Hakata':(130.414,33.600),'Nagasaki':(129.875,32.744),'Shuri':(127.719,26.217)}
def label(x,y,s,size=33,anchor='start'):
return f'{escape(s)}'
class Map:
def __init__(self,description,bounds,w=640,h=620):
self.bounds=bounds; self.w=w; self.h=h
l,b,r,t=bounds; self.cos=math.cos(math.radians((b+t)/2))
self.scale=min((w-56)/((r-l)*self.cos),(h-56)/(t-b))
self.ox=(w-(r-l)*self.cos*self.scale)/2;self.oy=(h-(t-b)*self.scale)/2
self.parts=[f''
def build():
out={}
m=Map('Five clusters in a physical archipelago: west-central Honshu, eastern Honshu, Kyushu, Hokkaido and the Ryukyu chain. No state borders.',(121,23,147,46),640,720)
for lon,lat,n,x,y in [(135.76,34.9,1,362,371),(139.65,35.5,2,545,357),(130.4,33.5,3,157,390),(142.4,43.1,4,530,89),(127.719,26.217,5,124,607)]:m.number(lon,lat,n,x,y)
out['clusters']=m.finish()
m=Map('The Korean peninsula lies across the straits from southwestern Japan. China lies farther west; the Pacific Ocean is east and southeast of Japan.',(118,24,147,47),640,630)
m.tag(127.5,37.4,'Korean',35,120,lines=2).add(35,159,'peninsula').add(55,360,'China',36).tag(138.5,36,'Japan',412,352,36).add(360,489,'Pacific Ocean',34)
out['asia']=m.finish()
m=Map('Four largest islands: Hokkaido to the north, long Honshu, Shikoku south of western Honshu, Kyushu farther southwest.',(128,30,147,46.2),640,650)
m.tag(142.4,43.2,'Hokkaido',334,87,34).tag(138.2,37,'Honshu',403,308,35).tag(133.6,33.7,'Shikoku',285,547,35).tag(130.65,32.4,'Kyushu',28,612,35)
out['islands']=m.finish()
m=Map('City dots form two clusters: Osaka, Kyoto and Nara in the west; Kamakura and Edo/Tokyo farther east. No region borders.',(134,33,141,37.6),640,455)
for name,n,x,y in [('Osaka',1,65,314),('Kyoto',2,190,70),('Nara',3,220,383),('Kamakura',4,453,334),('Edo / Tokyo',5,553,177)]:m.number(*PLACES[name],n,x,y)
out['regions']=m.finish()
m=Map('Nara is inland east of Osaka Bay and south of Kyoto. Three distinct dots preserve the neighbouring cities rather than merging them.',(134.8,33.7,136.6,35.55),640,615)
m.tag(*PLACES['Nara'],'Nara',429,411,38).tag(*PLACES['Kyoto'],'Kyoto',342,129,35).tag(*PLACES['Osaka'],'Osaka',40,261,35).tag(135.15,34.5,'Osaka Bay',38,463,33,dot=False)
out['nara']=m.finish()
m=Map('Kyoto is west and inland; Kamakura is far east, on the southern coast of the Kanto area. Both centres can matter at the same time.',(134,33.1,141,37.4),640,450)
m.tag(*PLACES['Kyoto'],'Kyoto',66,101,36).tag(*PLACES['Kamakura'],'Kamakura',382,381,36)
out['kamakura']=m.finish()
m=Map('Osaka lies beside its bay. Kyoto is upstream to the northeast. The Seto Inland Sea extends west between Honshu and Shikoku.',(131.6,33.2,136.4,35.6),640,510)
m.tag(*PLACES['Osaka'],'Osaka',520,280,35).tag(*PLACES['Kyoto'],'Kyoto',424,70,35).add(230,110,'Honshu',35).add(196,424,'Shikoku',35).tag(133.3,34.1,'Seto Inland',28,186,32,lines=2,dot=False).add(28,225,'Sea',32).tag(135.2,34.5,'Osaka Bay',416,412,32,dot=False)
out['osaka']=m.finish()
m=Map('A single dot near the head of Tokyo Bay marks Edo, renamed Tokyo in 1868. The name changes; the geographical location does not.',(138.95,34.8,140.45,36.13),640,565)
m.tag(*PLACES['Edo / Tokyo'],'Edo / Tokyo',34,130,37).add(*m.xy(139.85,35.46),'Bay',32,'middle')
out['edo']=m.finish()
m=Map('Hakata is on northern Kyushu. Nagasaki is southwest of it on the western coast. They are different ports, not interchangeable names.',(128.7,30.8,132.5,34.35),640,560)
m.tag(*PLACES['Hakata'],'Hakata',285,102,36).tag(*PLACES['Nagasaki'],'Nagasaki',28,357,36).add(358,435,'Kyushu',37)
out['kyushu']=m.finish()
m=Map('Hokkaido stands between northern Honshu and Sakhalin. Ainu communities participated in a wider northern world; coastlines here do not mark fixed ethnic or state borders.',(138,40,146.7,50),640,680)
m.tag(142.4,43.3,'Hokkaido',234,394,36).tag(142.3,48,'Sakhalin',33,104,36).tag(140.7,40.45,'Honshu',35,641,36)
out['north']=m.finish()
m=Map('The Ryukyu island chain extends southwest from Kyushu toward Taiwan. Shuri lies on Okinawa Island. No historic kingdom boundary is drawn.',(120,23,133,33.6),640,680)
m.tag(130.8,32.5,'Kyushu',389,86,36).tag(121,23.9,'Taiwan',26,595,36).tag(*PLACES['Shuri'],'Shuri',432,498,35).add(432,541,'Okinawa',32).add(140,236,'Ryukyu Islands',34)
out['south']=m.finish()
return out