mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-29 11:35:42 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cc05cf6e9 | ||
|
|
aeb9e09924 |
@@ -3,8 +3,8 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Berkorszag",
|
||||
"centroid_x": 1757.8,
|
||||
"centroid_y": 1231.9,
|
||||
"centroid_x": 1737.0,
|
||||
"centroid_y": 1296.0,
|
||||
"area": 247272,
|
||||
"orientation": -20.1884829564446,
|
||||
"principal_length": 873.5,
|
||||
@@ -14,8 +14,8 @@
|
||||
{
|
||||
"id": 27,
|
||||
"name": "Chapellia",
|
||||
"centroid_x": 3076.8,
|
||||
"centroid_y": 508.9,
|
||||
"centroid_x": 3077.0,
|
||||
"centroid_y": 509.0,
|
||||
"area": 37546,
|
||||
"orientation": -70.52505264723656,
|
||||
"principal_length": 297.6,
|
||||
@@ -25,8 +25,8 @@
|
||||
{
|
||||
"id": 28,
|
||||
"name": "Kezonoria",
|
||||
"centroid_x": 2204.7,
|
||||
"centroid_y": 1263.1,
|
||||
"centroid_x": 2195.0,
|
||||
"centroid_y": 1226.0,
|
||||
"area": 126885,
|
||||
"orientation": -35.386786918677814,
|
||||
"principal_length": 753.6,
|
||||
@@ -36,7 +36,7 @@
|
||||
{
|
||||
"id": 29,
|
||||
"name": "Mesh",
|
||||
"centroid_x": 2832.3,
|
||||
"centroid_x": 2832.0,
|
||||
"centroid_y": 1017.0,
|
||||
"area": 197788,
|
||||
"orientation": -26.173956537897066,
|
||||
@@ -47,8 +47,8 @@
|
||||
{
|
||||
"id": 36,
|
||||
"name": "Pemeria",
|
||||
"centroid_x": 2839.4,
|
||||
"centroid_y": 1290.4,
|
||||
"centroid_x": 2835.0,
|
||||
"centroid_y": 1282.0,
|
||||
"area": 36356,
|
||||
"orientation": -44.16012147839107,
|
||||
"principal_length": 457.1,
|
||||
@@ -58,8 +58,8 @@
|
||||
{
|
||||
"id": 37,
|
||||
"name": "Yuetia",
|
||||
"centroid_x": 896.1,
|
||||
"centroid_y": 1227.1,
|
||||
"centroid_x": 902.0,
|
||||
"centroid_y": 1132.0,
|
||||
"area": 362211,
|
||||
"orientation": 0.6747576339005641,
|
||||
"principal_length": 1261.0,
|
||||
@@ -69,8 +69,8 @@
|
||||
{
|
||||
"id": 39,
|
||||
"name": "Kojaria",
|
||||
"centroid_x": 3233.1,
|
||||
"centroid_y": 678.6,
|
||||
"centroid_x": 3234.0,
|
||||
"centroid_y": 678.0,
|
||||
"area": 37489,
|
||||
"orientation": -25.04939634407932,
|
||||
"principal_length": 301.9,
|
||||
@@ -80,8 +80,8 @@
|
||||
{
|
||||
"id": 43,
|
||||
"name": "Chia",
|
||||
"centroid_x": 1134.5,
|
||||
"centroid_y": 1519.3,
|
||||
"centroid_x": 1172.0,
|
||||
"centroid_y": 1499.0,
|
||||
"area": 75627,
|
||||
"orientation": -35.91298964206631,
|
||||
"principal_length": 441.6,
|
||||
@@ -91,8 +91,8 @@
|
||||
{
|
||||
"id": 18,
|
||||
"name": "Alah",
|
||||
"centroid_x": 3057.6,
|
||||
"centroid_y": 1330.3,
|
||||
"centroid_x": 3056.0,
|
||||
"centroid_y": 1330.0,
|
||||
"area": 35076,
|
||||
"orientation": -25.515287772906877,
|
||||
"principal_length": 285.6,
|
||||
@@ -102,8 +102,8 @@
|
||||
{
|
||||
"id": 34,
|
||||
"name": "Turton",
|
||||
"centroid_x": 2586.7,
|
||||
"centroid_y": 1506.5,
|
||||
"centroid_x": 2598.0,
|
||||
"centroid_y": 1500.0,
|
||||
"area": 37458,
|
||||
"orientation": -89.27834794069042,
|
||||
"principal_length": 295.6,
|
||||
@@ -113,8 +113,8 @@
|
||||
{
|
||||
"id": 41,
|
||||
"name": "Parnia",
|
||||
"centroid_x": 397.9,
|
||||
"centroid_y": 962.3,
|
||||
"centroid_x": 398.0,
|
||||
"centroid_y": 963.0,
|
||||
"area": 184733,
|
||||
"orientation": 80.31028460303715,
|
||||
"principal_length": 816.0,
|
||||
@@ -124,8 +124,8 @@
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Oryslia",
|
||||
"centroid_x": 2494.9,
|
||||
"centroid_y": 1104.4,
|
||||
"centroid_x": 2476.0,
|
||||
"centroid_y": 1058.0,
|
||||
"area": 108679,
|
||||
"orientation": 53.601133897917535,
|
||||
"principal_length": 673.2,
|
||||
@@ -135,7 +135,7 @@
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Soria",
|
||||
"centroid_x": 611.2,
|
||||
"centroid_x": 611.0,
|
||||
"centroid_y": 587.0,
|
||||
"area": 37567,
|
||||
"orientation": 73.04044050523646,
|
||||
@@ -146,7 +146,7 @@
|
||||
{
|
||||
"id": 26,
|
||||
"name": "Reigia",
|
||||
"centroid_x": 1538.6,
|
||||
"centroid_x": 1538.0,
|
||||
"centroid_y": 824.0,
|
||||
"area": 105738,
|
||||
"orientation": -56.461232070203295,
|
||||
@@ -157,8 +157,8 @@
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Sigkarl",
|
||||
"centroid_x": 1776.1,
|
||||
"centroid_y": 688.7,
|
||||
"centroid_x": 1776.0,
|
||||
"centroid_y": 688.0,
|
||||
"area": 52475,
|
||||
"orientation": -80.26596706568765,
|
||||
"principal_length": 411.4,
|
||||
@@ -168,8 +168,8 @@
|
||||
{
|
||||
"id": 42,
|
||||
"name": "Grytrand",
|
||||
"centroid_x": 1064.1,
|
||||
"centroid_y": 369.5,
|
||||
"centroid_x": 1056.0,
|
||||
"centroid_y": 373.0,
|
||||
"area": 37511,
|
||||
"orientation": 61.866124085696136,
|
||||
"principal_length": 315.1,
|
||||
@@ -179,8 +179,8 @@
|
||||
{
|
||||
"id": 13,
|
||||
"name": "Al Raala",
|
||||
"centroid_x": 3164.8,
|
||||
"centroid_y": 1142.9,
|
||||
"centroid_x": 3165.0,
|
||||
"centroid_y": 1142.0,
|
||||
"area": 64624,
|
||||
"orientation": 1.6109698686653782,
|
||||
"principal_length": 417.0,
|
||||
@@ -190,8 +190,8 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Laufarvia",
|
||||
"centroid_x": 770.1,
|
||||
"centroid_y": 437.8,
|
||||
"centroid_x": 770.0,
|
||||
"centroid_y": 437.0,
|
||||
"area": 37521,
|
||||
"orientation": -42.64914861683819,
|
||||
"principal_length": 253.6,
|
||||
@@ -201,7 +201,7 @@
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Atfordia",
|
||||
"centroid_x": 2473.6,
|
||||
"centroid_x": 2474.0,
|
||||
"centroid_y": 527.0,
|
||||
"area": 78637,
|
||||
"orientation": -15.123132625107454,
|
||||
@@ -212,8 +212,8 @@
|
||||
{
|
||||
"id": 33,
|
||||
"name": "Usvol",
|
||||
"centroid_x": 939.2,
|
||||
"centroid_y": 417.9,
|
||||
"centroid_x": 939.0,
|
||||
"centroid_y": 418.0,
|
||||
"area": 37617,
|
||||
"orientation": 72.87731176765703,
|
||||
"principal_length": 329.4,
|
||||
@@ -223,8 +223,8 @@
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Bolve",
|
||||
"centroid_x": 1554.3,
|
||||
"centroid_y": 567.8,
|
||||
"centroid_x": 1554.0,
|
||||
"centroid_y": 568.0,
|
||||
"area": 37519,
|
||||
"orientation": -28.254514479055615,
|
||||
"principal_length": 297.1,
|
||||
@@ -234,8 +234,8 @@
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Hofolen",
|
||||
"centroid_x": 1193.4,
|
||||
"centroid_y": 496.5,
|
||||
"centroid_x": 1192.0,
|
||||
"centroid_y": 497.0,
|
||||
"area": 37530,
|
||||
"orientation": -40.73421792639953,
|
||||
"principal_length": 321.3,
|
||||
@@ -245,8 +245,8 @@
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Pieksa",
|
||||
"centroid_x": 3373.6,
|
||||
"centroid_y": 752.0,
|
||||
"centroid_x": 3372.0,
|
||||
"centroid_y": 753.0,
|
||||
"area": 37474,
|
||||
"orientation": -42.30480488812397,
|
||||
"principal_length": 302.7,
|
||||
@@ -256,8 +256,8 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Shumal",
|
||||
"centroid_x": 2841.2,
|
||||
"centroid_y": 1426.4,
|
||||
"centroid_x": 2841.0,
|
||||
"centroid_y": 1426.0,
|
||||
"area": 35197,
|
||||
"orientation": -26.08271079122629,
|
||||
"principal_length": 286.9,
|
||||
@@ -267,8 +267,8 @@
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Musland",
|
||||
"centroid_x": 2776.1,
|
||||
"centroid_y": 685.8,
|
||||
"centroid_x": 2776.0,
|
||||
"centroid_y": 686.0,
|
||||
"area": 88353,
|
||||
"orientation": -67.33176588364896,
|
||||
"principal_length": 410.3,
|
||||
@@ -278,8 +278,8 @@
|
||||
{
|
||||
"id": 19,
|
||||
"name": "Hella",
|
||||
"centroid_x": 809.4,
|
||||
"centroid_y": 600.1,
|
||||
"centroid_x": 810.0,
|
||||
"centroid_y": 600.0,
|
||||
"area": 37632,
|
||||
"orientation": -29.964829271657674,
|
||||
"principal_length": 292.4,
|
||||
@@ -289,7 +289,7 @@
|
||||
{
|
||||
"id": 24,
|
||||
"name": "Tatoros",
|
||||
"centroid_x": 2452.8,
|
||||
"centroid_x": 2453.0,
|
||||
"centroid_y": 1508.0,
|
||||
"area": 37547,
|
||||
"orientation": 64.24404335610743,
|
||||
@@ -300,8 +300,8 @@
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Vovimaria",
|
||||
"centroid_x": 608.9,
|
||||
"centroid_y": 818.4,
|
||||
"centroid_x": 613.0,
|
||||
"centroid_y": 807.0,
|
||||
"area": 37474,
|
||||
"orientation": 42.325246247463234,
|
||||
"principal_length": 451.9,
|
||||
@@ -311,8 +311,8 @@
|
||||
{
|
||||
"id": 14,
|
||||
"name": "Onmaa",
|
||||
"centroid_x": 3464.3,
|
||||
"centroid_y": 864.9,
|
||||
"centroid_x": 3465.0,
|
||||
"centroid_y": 876.0,
|
||||
"area": 48302,
|
||||
"orientation": -33.08899725807026,
|
||||
"principal_length": 465.4,
|
||||
@@ -323,7 +323,7 @@
|
||||
"id": 32,
|
||||
"name": "Ingia",
|
||||
"centroid_x": 445.0,
|
||||
"centroid_y": 614.2,
|
||||
"centroid_y": 615.0,
|
||||
"area": 37475,
|
||||
"orientation": 40.330942997303495,
|
||||
"principal_length": 270.3,
|
||||
@@ -333,8 +333,8 @@
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Garholtia",
|
||||
"centroid_x": 768.3,
|
||||
"centroid_y": 805.8,
|
||||
"centroid_x": 768.0,
|
||||
"centroid_y": 807.0,
|
||||
"area": 37509,
|
||||
"orientation": 73.25523522382795,
|
||||
"principal_length": 275.4,
|
||||
@@ -344,8 +344,8 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Motcia",
|
||||
"centroid_x": 2989.1,
|
||||
"centroid_y": 672.1,
|
||||
"centroid_x": 2989.0,
|
||||
"centroid_y": 674.0,
|
||||
"area": 37541,
|
||||
"orientation": 71.01019565314077,
|
||||
"principal_length": 340.1,
|
||||
@@ -355,8 +355,8 @@
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Elekes",
|
||||
"centroid_x": 2354.4,
|
||||
"centroid_y": 1346.4,
|
||||
"centroid_x": 2355.0,
|
||||
"centroid_y": 1346.0,
|
||||
"area": 37570,
|
||||
"orientation": -4.693928802826447,
|
||||
"principal_length": 300.8,
|
||||
@@ -366,8 +366,8 @@
|
||||
{
|
||||
"id": 16,
|
||||
"name": "Oscasland",
|
||||
"centroid_x": 2033.5,
|
||||
"centroid_y": 740.9,
|
||||
"centroid_x": 2033.0,
|
||||
"centroid_y": 741.0,
|
||||
"area": 92595,
|
||||
"orientation": -7.875650568974214,
|
||||
"principal_length": 519.3,
|
||||
@@ -377,8 +377,8 @@
|
||||
{
|
||||
"id": 30,
|
||||
"name": "Tegrot",
|
||||
"centroid_x": 1736.5,
|
||||
"centroid_y": 1018.5,
|
||||
"centroid_x": 1736.0,
|
||||
"centroid_y": 1018.0,
|
||||
"area": 122426,
|
||||
"orientation": -20.247381662688625,
|
||||
"principal_length": 568.2,
|
||||
@@ -388,8 +388,8 @@
|
||||
{
|
||||
"id": 40,
|
||||
"name": "Faluria",
|
||||
"centroid_x": 976.7,
|
||||
"centroid_y": 744.3,
|
||||
"centroid_x": 976.0,
|
||||
"centroid_y": 746.0,
|
||||
"area": 80344,
|
||||
"orientation": -62.2520755175581,
|
||||
"principal_length": 494.3,
|
||||
@@ -399,8 +399,8 @@
|
||||
{
|
||||
"id": 25,
|
||||
"name": "Fluria",
|
||||
"centroid_x": 1245.7,
|
||||
"centroid_y": 835.6,
|
||||
"centroid_x": 1245.0,
|
||||
"centroid_y": 836.0,
|
||||
"area": 155157,
|
||||
"orientation": -66.31259041323624,
|
||||
"principal_length": 561.7,
|
||||
@@ -410,8 +410,8 @@
|
||||
{
|
||||
"id": 35,
|
||||
"name": "Tumala",
|
||||
"centroid_x": 3211.2,
|
||||
"centroid_y": 1409.8,
|
||||
"centroid_x": 3210.0,
|
||||
"centroid_y": 1409.0,
|
||||
"area": 25474,
|
||||
"orientation": 33.16003147165417,
|
||||
"principal_length": 283.2,
|
||||
@@ -421,8 +421,8 @@
|
||||
{
|
||||
"id": 31,
|
||||
"name": "Nikemi",
|
||||
"centroid_x": 3200.5,
|
||||
"centroid_y": 882.0,
|
||||
"centroid_x": 3200.0,
|
||||
"centroid_y": 881.0,
|
||||
"area": 40737,
|
||||
"orientation": 57.09128390939083,
|
||||
"principal_length": 378.6,
|
||||
@@ -432,8 +432,8 @@
|
||||
{
|
||||
"id": 22,
|
||||
"name": "Chipingia",
|
||||
"centroid_x": 2206.4,
|
||||
"centroid_y": 580.2,
|
||||
"centroid_x": 2209.0,
|
||||
"centroid_y": 588.0,
|
||||
"area": 40656,
|
||||
"orientation": -48.11179717863961,
|
||||
"principal_length": 286.5,
|
||||
@@ -443,8 +443,8 @@
|
||||
{
|
||||
"id": 23,
|
||||
"name": "Eivikia",
|
||||
"centroid_x": 1359.5,
|
||||
"centroid_y": 506.6,
|
||||
"centroid_x": 1360.0,
|
||||
"centroid_y": 506.0,
|
||||
"area": 37555,
|
||||
"orientation": -49.357592556477876,
|
||||
"principal_length": 285.3,
|
||||
@@ -454,8 +454,8 @@
|
||||
{
|
||||
"id": 38,
|
||||
"name": "Wichel",
|
||||
"centroid_x": 2399.6,
|
||||
"centroid_y": 792.4,
|
||||
"centroid_x": 2395.0,
|
||||
"centroid_y": 781.0,
|
||||
"area": 122281,
|
||||
"orientation": -26.154786547398853,
|
||||
"principal_length": 627.0,
|
||||
@@ -465,8 +465,8 @@
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Pozia",
|
||||
"centroid_x": 2950.6,
|
||||
"centroid_y": 338.6,
|
||||
"centroid_x": 2960.0,
|
||||
"centroid_y": 395.0,
|
||||
"area": 56289,
|
||||
"orientation": -65.77001402153415,
|
||||
"principal_length": 522.5,
|
||||
@@ -474,4 +474,4 @@
|
||||
"curvature": -9.3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ Usage:
|
||||
python generate_map.py --analyze # Analyze current map, show province sizes
|
||||
python generate_map.py --generate # Generate new equalized map
|
||||
python generate_map.py --visualize # Generate visualization of current vs new
|
||||
python generate_map.py --update-centroids # Update label positions in centroids.json
|
||||
"""
|
||||
|
||||
import argparse
|
||||
@@ -89,6 +90,39 @@ def load_province_data() -> dict[int, dict]:
|
||||
return provinces
|
||||
|
||||
|
||||
def find_label_position(mask: np.ndarray) -> tuple[float, float]:
|
||||
"""Find the best label position for a province.
|
||||
|
||||
Finds all pixels with at least 70% of the province's maximum possible
|
||||
clearance from edges, then picks the one closest to the geometric centroid.
|
||||
This guarantees good distance from borders/coastlines while keeping labels
|
||||
as visually centered as possible.
|
||||
|
||||
Returns (x, y) in pixel coordinates.
|
||||
"""
|
||||
# Geometric centroid (visual center of mass)
|
||||
y_coords, x_coords = np.where(mask)
|
||||
mean_x = np.mean(x_coords)
|
||||
mean_y = np.mean(y_coords)
|
||||
|
||||
# Distance from nearest edge for every province pixel
|
||||
dist = ndimage.distance_transform_edt(mask)
|
||||
max_clearance = np.max(dist)
|
||||
|
||||
# Require at least 70% of the best possible clearance
|
||||
candidates = dist >= max_clearance * 0.7
|
||||
|
||||
if np.any(candidates):
|
||||
cand_ys, cand_xs = np.where(candidates)
|
||||
dists_to_centroid = (cand_xs - mean_x)**2 + (cand_ys - mean_y)**2
|
||||
best = np.argmin(dists_to_centroid)
|
||||
return float(cand_xs[best]), float(cand_ys[best])
|
||||
|
||||
# Fallback: pole of inaccessibility
|
||||
max_idx = np.unravel_index(np.argmax(dist), dist.shape)
|
||||
return float(max_idx[1]), float(max_idx[0])
|
||||
|
||||
|
||||
def analyze_provinces(raw_gray: np.ndarray, province_data: dict) -> list[Province]:
|
||||
"""Calculate centroid and area for each province."""
|
||||
provinces = []
|
||||
@@ -102,10 +136,7 @@ def analyze_provinces(raw_gray: np.ndarray, province_data: dict) -> list[Provinc
|
||||
print(f"Warning: Province {province_id} ({data['name']}) has no pixels")
|
||||
continue
|
||||
|
||||
# Calculate centroid (center of mass)
|
||||
y_coords, x_coords = np.where(mask)
|
||||
centroid_x = np.mean(x_coords)
|
||||
centroid_y = np.mean(y_coords)
|
||||
centroid_x, centroid_y = find_label_position(mask)
|
||||
|
||||
provinces.append(Province(
|
||||
id=province_id,
|
||||
@@ -530,26 +561,85 @@ def generate_visualization(
|
||||
|
||||
|
||||
def save_centroids(provinces: list[Province], output_path: Path):
|
||||
"""Save province centroids to JSON for Unity label positioning."""
|
||||
data = {
|
||||
"provinces": [
|
||||
{
|
||||
"id": int(p.id),
|
||||
"name": p.name,
|
||||
"centroid_x": float(p.centroid[0]),
|
||||
"centroid_y": float(p.centroid[1]),
|
||||
"area": int(p.area)
|
||||
}
|
||||
for p in provinces
|
||||
]
|
||||
}
|
||||
"""Save province centroids to JSON for Unity label positioning.
|
||||
|
||||
Preserves hand-tuned fields (orientation, principal_length, etc.)
|
||||
from existing centroids.json if present.
|
||||
"""
|
||||
# Load existing data to preserve hand-tuned fields
|
||||
existing_by_id = {}
|
||||
for candidate in [output_path, UNITY_ASSETS / "centroids.json"]:
|
||||
if candidate.exists():
|
||||
with open(candidate, 'r') as f:
|
||||
existing_by_id = {p['id']: p for p in json.load(f)['provinces']}
|
||||
break
|
||||
|
||||
province_list = []
|
||||
for p in provinces:
|
||||
entry = {
|
||||
"id": int(p.id),
|
||||
"name": p.name,
|
||||
"centroid_x": round(float(p.centroid[0]), 1),
|
||||
"centroid_y": round(float(p.centroid[1]), 1),
|
||||
"area": int(p.area)
|
||||
}
|
||||
# Preserve hand-tuned fields from existing file
|
||||
if p.id in existing_by_id:
|
||||
for field in ("orientation", "principal_length", "perpendicular_width", "curvature"):
|
||||
if field in existing_by_id[p.id]:
|
||||
entry[field] = existing_by_id[p.id][field]
|
||||
province_list.append(entry)
|
||||
|
||||
data = {"provinces": province_list}
|
||||
|
||||
with open(output_path, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
f.write('\n')
|
||||
|
||||
print(f"Saved centroids to {output_path}")
|
||||
|
||||
|
||||
def update_centroids(raw_gray: np.ndarray, province_data: dict):
|
||||
"""Update centroids.json with pole-of-inaccessibility positions.
|
||||
|
||||
Only updates centroid_x and centroid_y, preserving all hand-tuned fields
|
||||
(orientation, principal_length, perpendicular_width, curvature).
|
||||
"""
|
||||
centroids_path = UNITY_ASSETS / "centroids.json"
|
||||
|
||||
with open(centroids_path, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
existing_by_id = {p['id']: p for p in data['provinces']}
|
||||
|
||||
updated = 0
|
||||
for province_id, pdata in province_data.items():
|
||||
mask = raw_gray == province_id
|
||||
area = np.sum(mask)
|
||||
if area == 0:
|
||||
print(f"Warning: Province {province_id} ({pdata['name']}) has no pixels")
|
||||
continue
|
||||
|
||||
lx, ly = find_label_position(mask)
|
||||
new_x = round(lx, 1)
|
||||
new_y = round(ly, 1)
|
||||
|
||||
if province_id in existing_by_id:
|
||||
entry = existing_by_id[province_id]
|
||||
old_x, old_y = entry['centroid_x'], entry['centroid_y']
|
||||
if old_x != new_x or old_y != new_y:
|
||||
print(f" {pdata['name']:20s}: ({old_x}, {old_y}) -> ({new_x}, {new_y})")
|
||||
entry['centroid_x'] = new_x
|
||||
entry['centroid_y'] = new_y
|
||||
updated += 1
|
||||
|
||||
with open(centroids_path, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
f.write('\n')
|
||||
|
||||
print(f"Updated {updated} centroids in {centroids_path}")
|
||||
|
||||
|
||||
def save_raw_gray(province_map: np.ndarray, output_path: Path, compress: bool = True):
|
||||
"""Save province map as raw bytes (optionally gzip compressed)."""
|
||||
# Flip for Unity (bottom-left origin)
|
||||
@@ -572,6 +662,8 @@ def main():
|
||||
parser.add_argument('--analyze', action='store_true', help='Analyze current map')
|
||||
parser.add_argument('--generate', action='store_true', help='Generate new equalized map')
|
||||
parser.add_argument('--visualize', action='store_true', help='Generate visualization')
|
||||
parser.add_argument('--update-centroids', action='store_true',
|
||||
help='Update centroid positions in centroids.json (preserves hand-tuned fields)')
|
||||
parser.add_argument('--target-ratio', type=float, default=0.5,
|
||||
help='Target minimum province size as ratio of average (default: 0.5)')
|
||||
parser.add_argument('--output-dir', type=Path, default=SCRIPT_DIR / 'output',
|
||||
@@ -579,7 +671,7 @@ def main():
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not any([args.analyze, args.generate, args.visualize]):
|
||||
if not any([args.analyze, args.generate, args.visualize, args.update_centroids]):
|
||||
args.analyze = True # Default to analyze
|
||||
|
||||
print("Loading province data...")
|
||||
@@ -590,6 +682,11 @@ def main():
|
||||
raw_gray = load_raw_gray()
|
||||
print(f"Map dimensions: {raw_gray.shape[1]} x {raw_gray.shape[0]}")
|
||||
|
||||
if args.update_centroids:
|
||||
print("Updating centroids with pole-of-inaccessibility positions...")
|
||||
update_centroids(raw_gray, province_data)
|
||||
return
|
||||
|
||||
print("Analyzing provinces...")
|
||||
provinces = analyze_provinces(raw_gray, province_data)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user