hmm?
This commit is contained in:
parent
ea0067dc0a
commit
112e6bf86b
11 changed files with 1586 additions and 1253 deletions
150
rectContext.js
Normal file
150
rectContext.js
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
import { clamp } from "./mapUtils.js";
|
||||
|
||||
export function createRectContext(options = {}) {
|
||||
const originX = Math.floor(Number.isFinite(options.originX) ? options.originX : 0);
|
||||
const originY = Math.floor(Number.isFinite(options.originY) ? options.originY : 0);
|
||||
const width = Math.max(1, Math.floor(Number.isFinite(options.width) ? options.width : 1));
|
||||
const height = Math.max(1, Math.floor(Number.isFinite(options.height) ? options.height : 1));
|
||||
return {
|
||||
originX,
|
||||
originY,
|
||||
width,
|
||||
height,
|
||||
size: width * height,
|
||||
name: options.name || "rect",
|
||||
};
|
||||
}
|
||||
|
||||
export function rectIndexOf(ctx, x, y) {
|
||||
return y * ctx.width + x;
|
||||
}
|
||||
|
||||
export function rectXyOf(ctx, i) {
|
||||
return [i % ctx.width, Math.floor(i / ctx.width)];
|
||||
}
|
||||
|
||||
export function rectInside(ctx, x, y) {
|
||||
return !!ctx && x >= 0 && y >= 0 && x < ctx.width && y < ctx.height;
|
||||
}
|
||||
|
||||
export function rectWorldX(ctx, x) {
|
||||
return ctx.originX + x;
|
||||
}
|
||||
|
||||
export function rectWorldY(ctx, y) {
|
||||
return ctx.originY + y;
|
||||
}
|
||||
|
||||
export function rectWorldCoord(ctx, x, y) {
|
||||
return { x: ctx.originX + x, y: ctx.originY + y };
|
||||
}
|
||||
|
||||
export function rectLocalCoord(ctx, worldX, worldY) {
|
||||
return { x: Math.round(worldX - ctx.originX), y: Math.round(worldY - ctx.originY) };
|
||||
}
|
||||
|
||||
export function rectWorldIndex(ctx, worldX, worldY) {
|
||||
const x = Math.round(worldX - ctx.originX);
|
||||
const y = Math.round(worldY - ctx.originY);
|
||||
return rectInside(ctx, x, y) ? rectIndexOf(ctx, x, y) : -1;
|
||||
}
|
||||
|
||||
export function rectFromBounds(bounds, name = "rect") {
|
||||
const x0 = Math.floor(Math.min(bounds.x0, bounds.x1));
|
||||
const y0 = Math.floor(Math.min(bounds.y0, bounds.y1));
|
||||
const x1 = Math.ceil(Math.max(bounds.x0, bounds.x1));
|
||||
const y1 = Math.ceil(Math.max(bounds.y0, bounds.y1));
|
||||
return createRectContext({ originX: x0, originY: y0, width: Math.max(1, x1 - x0), height: Math.max(1, y1 - y0), name });
|
||||
}
|
||||
|
||||
export function rectBounds(ctx) {
|
||||
return { x0: ctx.originX, y0: ctx.originY, x1: ctx.originX + ctx.width, y1: ctx.originY + ctx.height };
|
||||
}
|
||||
|
||||
export function clampRectToBounds(rect, bounds) {
|
||||
const x0 = Math.max(bounds.x0 ?? 0, Math.floor(rect.x0));
|
||||
const y0 = Math.max(bounds.y0 ?? 0, Math.floor(rect.y0));
|
||||
const x1 = Math.min(bounds.x1 ?? Infinity, Math.ceil(rect.x1));
|
||||
const y1 = Math.min(bounds.y1 ?? Infinity, Math.ceil(rect.y1));
|
||||
return { x0, y0, x1: Math.max(x0, x1), y1: Math.max(y0, y1) };
|
||||
}
|
||||
|
||||
export function expandRectBounds(rect, margin, bounds = null) {
|
||||
const expanded = {
|
||||
x0: Math.floor(rect.x0) - margin,
|
||||
y0: Math.floor(rect.y0) - margin,
|
||||
x1: Math.ceil(rect.x1) + margin,
|
||||
y1: Math.ceil(rect.y1) + margin,
|
||||
};
|
||||
return bounds ? clampRectToBounds(expanded, bounds) : expanded;
|
||||
}
|
||||
|
||||
export function rectNeighbors8(ctx, x, y) {
|
||||
const out = [];
|
||||
for (let dy = -1; dy <= 1; dy++) {
|
||||
for (let dx = -1; dx <= 1; dx++) {
|
||||
if (!dx && !dy) continue;
|
||||
const nx = x + dx;
|
||||
const ny = y + dy;
|
||||
if (rectInside(ctx, nx, ny)) out.push([nx, ny]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function rectDistanceToEdge(ctx, x, y) {
|
||||
return Math.min(x, y, ctx.width - 1 - x, ctx.height - 1 - y);
|
||||
}
|
||||
|
||||
export function createRectTerrainFields(ctx) {
|
||||
const size = ctx.size;
|
||||
const flowTo = new Int32Array(size);
|
||||
flowTo.fill(-1);
|
||||
return {
|
||||
elevation: new Float32Array(size),
|
||||
moisture: new Float32Array(size),
|
||||
slope: new Float32Array(size),
|
||||
sea: new Uint8Array(size),
|
||||
ocean: new Uint8Array(size),
|
||||
lake: new Uint8Array(size),
|
||||
river: new Float32Array(size),
|
||||
floodplain: new Float32Array(size),
|
||||
plain: new Float32Array(size),
|
||||
agriculture: new Float32Array(size),
|
||||
ridgeField: new Float32Array(size),
|
||||
valleyField: new Float32Array(size),
|
||||
basinField: new Float32Array(size),
|
||||
coastalLowland: new Float32Array(size),
|
||||
flowAccum: new Float32Array(size),
|
||||
erosionField: new Float32Array(size),
|
||||
depositionField: new Float32Array(size),
|
||||
arcSpineField: new Float32Array(size),
|
||||
branchRidgeField: new Float32Array(size),
|
||||
depositionalLowland: new Float32Array(size),
|
||||
alluvialFanField: new Float32Array(size),
|
||||
deltaField: new Float32Array(size),
|
||||
naturalBarrierScore: new Float32Array(size),
|
||||
flowTo,
|
||||
portSuitability: new Float32Array(size),
|
||||
crossingSuitability: new Float32Array(size),
|
||||
passSuitability: new Float32Array(size),
|
||||
visibleRavineField: new Float32Array(size),
|
||||
surfaceTextureField: new Float32Array(size),
|
||||
watershedId: (() => { const a = new Int32Array(size); a.fill(-1); return a; })(),
|
||||
naturalCompartmentId: (() => { const a = new Int32Array(size); a.fill(-1); return a; })(),
|
||||
regionId: (() => { const a = new Int32Array(size); a.fill(-1); return a; })(),
|
||||
};
|
||||
}
|
||||
|
||||
export function isRectCellField(value, ctx) {
|
||||
return ArrayBuffer.isView(value) && typeof value.length === "number" && value.length === ctx.size;
|
||||
}
|
||||
|
||||
export function rectQuantile(values, q) {
|
||||
const arr = Array.from(values).filter(Number.isFinite).sort((a, b) => a - b);
|
||||
if (!arr.length) return 0;
|
||||
const p = clamp(q) * (arr.length - 1);
|
||||
const i = Math.floor(p);
|
||||
const f = p - i;
|
||||
return arr[i] + (arr[Math.min(arr.length - 1, i + 1)] - arr[i]) * f;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue