border tweak

This commit is contained in:
33333-33333 2026-05-26 16:56:18 +09:00
commit 71b58cf033
7 changed files with 514 additions and 68 deletions

View file

@ -1,9 +1,11 @@
import { CELL_SIZE, MAP_H, MAP_W, clamp, fbm, indexOf, valueNoise } from "./mapUtils.js";
import { CELL_SIZE, MAP_H, MAP_W, clamp, indexOf } from "./mapUtils.js";
const segmentVectorCache = new WeakMap();
const pathVectorCache = new WeakMap();
const coastlineCache = new WeakMap();
const baseImageCache = new WeakMap();
const MAX_BASE_CACHE_IMAGES = 4;
function pointKey(p) {
return `${p[0]},${p[1]}`;
@ -423,7 +425,25 @@ function discreteColor(map, x, y, mode) {
return blendOutside(color, Boolean(map.prefectureMask[i]));
}
function drawBase(ctx, map, mode, continuousTerrain) {
function baseCacheKey(mode, continuousTerrain) {
const continuousModes = ["terrain", "development", "all"];
if (continuousTerrain && continuousModes.includes(mode)) {
return `continuous:${mode === "all" ? "terrain" : mode}`;
}
return `discrete:${mode}`;
}
function getCachedBaseImage(ctx, map, mode, continuousTerrain) {
let cache = baseImageCache.get(map);
if (!cache) {
cache = new Map();
baseImageCache.set(map, cache);
}
const key = baseCacheKey(mode, continuousTerrain);
let image = cache.get(key);
if (image) return image;
const width = MAP_W * CELL_SIZE;
const height = MAP_H * CELL_SIZE;
const img = ctx.createImageData(width, height);
@ -460,7 +480,13 @@ function drawBase(ctx, map, mode, continuousTerrain) {
}
}
}
ctx.putImageData(img, 0, 0);
cache.set(key, img);
if (cache.size > MAX_BASE_CACHE_IMAGES) cache.delete(cache.keys().next().value);
return img;
}
function drawBase(ctx, map, mode, continuousTerrain) {
ctx.putImageData(getCachedBaseImage(ctx, map, mode, continuousTerrain), 0, 0);
}
function drawRiverPath(ctx, map, path, color, widthFn, alpha = 1) {
@ -838,8 +864,9 @@ export function drawMap(canvas, map, options) {
}
if (!showPrefectureRegions) {
drawVectorSegments(ctx, map.prefectureBorder, "rgba(255, 255, 255, 0.95)", 5.0, false, { iterations: 2, tolerance: 0.06, offsetX: -0.5, offsetY: -0.5 });
drawVectorSegments(ctx, map.prefectureBorder, "rgba(110, 90, 110, 1)", 2.2, true, { iterations: 2, tolerance: 0.06, offsetX: -0.5, offsetY: -0.5 });
const finalPrefectureBorders = (map.regionalPrefectureBorders && map.regionalPrefectureBorders.length) ? map.regionalPrefectureBorders : map.prefectureBorder;
drawVectorSegments(ctx, finalPrefectureBorders, "rgba(255, 255, 255, 0.95)", 5.0, false, { iterations: 2, tolerance: 0.06, offsetX: -0.5, offsetY: -0.5 });
drawVectorSegments(ctx, finalPrefectureBorders, "rgba(110, 90, 110, 1)", 2.2, true, { iterations: 2, tolerance: 0.06, offsetX: -0.5, offsetY: -0.5 });
}
if (!showFeatures) return;
@ -896,7 +923,10 @@ export function drawMap(canvas, map, options) {
if (showModern) {
for (const p of map.stations) dot(ctx, p, 2.5, "#fff", "#444");
const allLayerTowns = mode === "all"
? (map.markets || []).filter((p) => (p.population || 0) >= 25000 && !(map.modernCities || []).some((c) => c.x === p.x && c.y === p.y))
? [
...(map.markets || []).filter((p) => (p.population || 0) >= 5000),
...(map.villages || []).filter((p) => (p.population || 0) >= 5000),
].filter((p) => !(map.modernCities || []).some((c) => c.x === p.x && c.y === p.y))
: [];
for (const p of allLayerTowns) dot(ctx, p, 3.1, "rgba(244, 164, 118, 0.92)", "rgba(255,255,255,0.88)");
for (const p of map.modernCities) {
@ -906,6 +936,7 @@ export function drawMap(canvas, map, options) {
else if (p.isRegionalCapital) dot(ctx, p, popRadius + 2.4, "transparent", "rgba(190,95,95,0.62)");
}
for (const p of map.interchanges || []) dot(ctx, p, 2.7, "rgba(250, 250, 245, 0.95)", "rgba(95, 125, 95, 0.95)");
for (const p of map.logisticsParks || []) dot(ctx, p, 2.4, "rgba(235, 238, 230, 0.95)", "rgba(105, 125, 105, 0.88)");
if (mode === "admin-debug" || mode === "borders-debug") {
for (const p of map.externalGateways || []) dot(ctx, p, 5.5, "rgba(255,255,255,0.95)", "rgba(40,80,170,0.95)");
for (const p of map.transportDebug?.missingRequiredNodes || []) dot(ctx, p, 6.5, "rgba(255,80,80,0.95)", "rgba(80,20,20,0.95)");
@ -925,15 +956,21 @@ export function drawMap(canvas, map, options) {
return;
}
const allLayerTowns = mode === "all"
? (map.markets || []).filter((p) => (p.population || 0) >= 25000 && !(map.modernCities || []).some((c) => c.x === p.x && c.y === p.y)).map((p) => ({ ...p, labelPriorityBase: 120 }))
? [
...(map.markets || []).filter((p) => (p.population || 0) >= 5000),
...(map.villages || []).filter((p) => (p.population || 0) >= 5000),
]
.filter((p) => !(map.modernCities || []).some((c) => c.x === p.x && c.y === p.y))
.map((p) => ({ ...p, forceAllLayerTownLabel: true, labelPriorityBase: p.kind === "Village" || p.kind === "Valley Village" || p.kind === "Coastal Village" ? 75 : 135 }))
: [];
const important = [
...prefectureLabels,
...map.modernCities,
...map.ports,
...(map.logisticsParks || []).map((p) => ({ ...p, labelPriorityBase: 60 })),
...(map.satelliteCities || []),
...allLayerTowns,
].filter((p) => p.insidePrefecture || p.isRegionalCapital || p.kind === "External Gateway" || (p.population || 0) >= 25000);
].filter((p) => p.forceAllLayerTownLabel || p.insidePrefecture || p.isRegionalCapital || p.kind === "External Gateway" || (p.population || 0) >= 5000);
drawLabels(ctx, important, mode === "all" ? 85 : 60);
}
drawScaleBar(ctx);