agentscript
Version:
AgentScript Model in Model/View architecture
1,625 lines (1,622 loc) • 1.46 MB
JavaScript
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// src/utils.js
var utils_exports = {};
__export(utils_exports, {
AsyncFunction: () => AsyncFunction,
PI: () => PI,
RESTapi: () => RESTapi,
addCssLink: () => addCssLink,
addCssStyle: () => addCssStyle,
arrayExtent: () => arrayExtent,
arrayLast: () => arrayLast,
arrayMax: () => arrayMax,
arrayMin: () => arrayMin,
arrayToMatrix: () => arrayToMatrix,
arraysDiff: () => arraysDiff,
arraysEqual: () => arraysEqual,
arraysToString: () => arraysToString,
blobToData: () => blobToData,
blobsEqual: () => blobsEqual,
checkArg: () => checkArg,
checkArgs: () => checkArgs,
clamp: () => clamp,
classHasStartup: () => classHasStartup,
clearCtx: () => clearCtx,
cloneCanvas: () => cloneCanvas,
concatArrays: () => concatArrays,
convertArrayType: () => convertArrayType,
createCanvas: () => createCanvas,
createCtx: () => createCtx,
cssTrace: () => cssTrace,
ctxImageColors: () => ctxImageColors,
ctxImageData: () => ctxImageData,
ctxImagePixels: () => ctxImagePixels,
degToHeading: () => degToHeading,
degToRad: () => degToRad,
degreesEqual: () => degreesEqual,
degreesTowardXY: () => degreesTowardXY,
difference: () => difference,
distance: () => distance,
distance3: () => distance3,
downloadBlob: () => downloadBlob,
downloadCanvas: () => downloadCanvas,
downloadJson: () => downloadJson,
downloadJsonModule: () => downloadJsonModule,
drawText: () => drawText,
dump: () => dump,
fetchCssStyle: () => fetchCssStyle,
fetchData: () => fetchData,
fetchImage: () => fetchImage,
fetchImageBitmap: () => fetchImageBitmap,
fetchJson: () => fetchJson,
fetchText: () => fetchText,
fillCtxWithImage: () => fillCtxWithImage,
floatRamp: () => floatRamp,
forLoop: () => forLoop,
fps: () => fps,
getEventXY: () => getEventXY,
getQueryString: () => getQueryString,
grep: () => grep,
hasCanvas: () => hasCanvas,
headingAngleToRad: () => headingAngleToRad,
headingToDeg: () => headingToDeg,
headingToRad: () => headingToRad,
headingTowardXY: () => headingTowardXY,
headingsEq: () => headingsEq,
identityFcn: () => identityFcn,
imagePromise: () => imagePromise,
imageToCanvas: () => imageToCanvas,
imageToCtx: () => imageToCtx,
inCone: () => inCone,
inDeno: () => inDeno,
inMain: () => inMain,
inNode: () => inNode,
inWorker: () => inWorker,
integerRamp: () => integerRamp,
intersection: () => intersection,
isArray: () => isArray,
isArrayLike: () => isArrayLike,
isBetween: () => isBetween,
isCanvas: () => isCanvas,
isColorLikeArray: () => isColorLikeArray,
isDataSet: () => isDataSet,
isFloatArray: () => isFloatArray,
isFunction: () => isFunction,
isImage: () => isImage,
isImageable: () => isImageable,
isIntArray: () => isIntArray,
isInteger: () => isInteger,
isLittleEndian: () => isLittleEndian,
isNumber: () => isNumber,
isObject: () => isObject,
isOneOfTypes: () => isOneOfTypes,
isOofA: () => isOofA,
isPowerOf2: () => isPowerOf2,
isString: () => isString,
isType: () => isType,
isTypedArray: () => isTypedArray,
isUintArray: () => isUintArray,
lerp: () => lerp,
lerpScale: () => lerpScale,
logAll: () => logAll,
logOnce: () => logOnce,
matrixToArray: () => matrixToArray,
mod: () => mod,
mod180180: () => mod180180,
mod2pi: () => mod2pi,
mod360: () => mod360,
nestedProperty: () => nestedProperty,
nextPowerOf2: () => nextPowerOf2,
noopFcn: () => noopFcn,
objectLength: () => objectLength,
objectToString: () => objectToString,
objectsEqual: () => objectsEqual,
oneKeyOf: () => oneKeyOf,
oneOf: () => oneOf,
oneValOf: () => oneValOf,
oofaBuffers: () => oofaBuffers,
oofaObject: () => oofaObject,
otherOneOf: () => otherOneOf,
parseQueryString: () => parseQueryString,
pause: () => pause,
pps: () => pps,
precision: () => precision,
printToPage: () => printToPage,
propFcn: () => propFcn,
radToDeg: () => radToDeg,
radToHeading: () => radToHeading,
radToHeadingAngle: () => radToHeadingAngle,
radiansTowardXY: () => radiansTowardXY,
radsEqual: () => radsEqual,
randomCentered: () => randomCentered,
randomFloat: () => randomFloat,
randomFloat2: () => randomFloat2,
randomInt: () => randomInt,
randomInt2: () => randomInt2,
randomNormal: () => randomNormal,
randomSeed: () => randomSeed,
range: () => range,
removeArrayItem: () => removeArrayItem,
repeat: () => repeat,
resizeCtx: () => resizeCtx,
runModel: () => runModel,
sampleModel: () => sampleModel,
setCanvasSize: () => setCanvasSize,
setCtxImage: () => setCtxImage,
setIdentity: () => setIdentity,
setTextProperties: () => setTextProperties,
shuffle: () => shuffle,
sortNums: () => sortNums,
sortObjs: () => sortObjs,
sqDistance: () => sqDistance,
sqDistance3: () => sqDistance3,
step: () => step,
stringMetrics: () => stringMetrics,
subtractDegrees: () => subtractDegrees,
subtractHeadings: () => subtractHeadings,
subtractRadians: () => subtractRadians,
timeit: () => timeit,
timeoutLoop: () => timeoutLoop,
toAofO: () => toAofO,
toDataURL: () => toDataURL,
toDeg: () => toDeg,
toJSON: () => toJSON,
toOofA: () => toOofA,
toRad: () => toRad,
toWindow: () => toWindow,
typeOf: () => typeOf,
union: () => union,
waitUntilDone: () => waitUntilDone,
warn: () => warn,
wrap: () => wrap
});
function inMain() {
return globalThis.document !== void 0;
}
function inWorker() {
return globalThis.WorkerGlobalScope !== void 0;
}
function inNode() {
return typeof globalThis.require !== "undefined";
}
function inDeno() {
return typeof globalThis.Deno !== "undefined";
}
function hasCanvas() {
return globalThis.canvas !== "undefined";
}
function AsyncFunction(argsArray, fcnBody) {
const ctor = Object.getPrototypeOf(async function() {
}).constructor;
const asyncFcn = new ctor(...argsArray, fcnBody);
return asyncFcn;
}
function blobToData(blob, type = "dataURL") {
type = type[0].toUpperCase() + type.slice(1);
const types = ["Text", "ArrayBuffer", "DataURL"];
if (!types.includes(type))
throw Error("blobToData: data must be one of " + types.toString());
const reader = new FileReader();
return new Promise((resolve, reject) => {
reader.addEventListener("load", () => resolve(reader.result));
reader.addEventListener("error", (e) => reject(e));
reader["readAs" + type](blob);
});
}
async function fetchData(url2, type = "blob") {
const types = ["arrayBuffer", "blob", "json", "text"];
if (!types.includes(type))
throw Error("fetchData: data must be one of " + types.toString());
return fetch(url2).then((res) => res[type]());
}
async function fetchJson(url2) {
return fetchData(url2, "json");
}
async function fetchText(url2) {
return fetchData(url2, "text");
}
function toDataURL(data, type = void 0) {
if (data.toDataURL) return data.toDataURL(type, type);
if (!type) type = "text/plain;charset=US-ASCII";
return `data:${type};base64,${btoa(data)}}`;
}
async function blobsEqual(blob0, blob1) {
const text0 = await blob0.text();
const text1 = await blob1.text();
return text0 === text1;
}
function pause(ms = 1e3) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function timeoutLoop(fcn, steps = -1, ms = 0) {
let i = 0;
while (i++ !== steps) {
fcn(i - 1);
await pause(ms);
}
}
function waitUntilDone(done, ms = 10) {
return new Promise((resolve) => {
function waitOnDone() {
if (done()) return resolve();
else setTimeout(waitOnDone, ms);
}
waitOnDone();
});
}
function checkArg(arg, type = "number", name = "Function") {
}
function checkArgs(argsArray, type = "number", name = "Function") {
}
var logOnceMsgSet = /* @__PURE__ */ new Set();
function logOnce(msg, useWarn = false) {
if (!logOnceMsgSet.has(msg)) {
if (useWarn) {
console.warn(msg);
} else {
console.log(msg);
}
logOnceMsgSet.add(msg);
}
}
function warn(msg) {
logOnce(msg, true);
}
function timeit(f, runs = 1e5, name = "test") {
name = name + "-" + runs;
console.time(name);
for (let i = 0; i < runs; i++) f(i);
console.timeEnd(name);
}
function fps() {
const timer = typeof performance === "undefined" ? Date : performance;
const start = timer.now();
let steps = 0;
function perf() {
steps++;
const ms = timer.now() - start;
const fps2 = parseFloat((steps / (ms / 1e3)).toFixed(2));
Object.assign(perf, { fps: fps2, ms, start, steps });
}
perf.steps = 0;
return perf;
}
function pps(obj, title = "") {
if (title) console.log(title);
let count = 1;
let str = "";
while (obj) {
if (typeof obj === "function") {
str = obj.constructor.toString();
} else {
const okeys = Object.keys(obj);
str = okeys.length > 0 ? `[${okeys.join(", ")}]` : `[${obj.constructor.name}]`;
}
console.log(`[${count++}]: ${str}`);
obj = Object.getPrototypeOf(obj);
}
}
function logAll(obj) {
Object.keys(obj).forEach((key) => console.log(" ", key, obj[key]));
}
function cssTrace(elementName, names = ["position", "cursor", "display", "width", "height"]) {
let element = document.querySelector(elementName);
while (element) {
const styles = window.getComputedStyle(element);
console.log("element:", element);
console.log("tag:", element.tagName);
names.forEach((name) => console.log(name + ":", styles[name]));
console.log("------------------------");
element = element.parentElement;
}
}
var PI = Math.PI;
function randomInt(max) {
return Math.floor(Math.random() * max);
}
function randomInt2(min, max) {
return min + Math.floor(Math.random() * (max - min));
}
function randomFloat(max) {
return Math.random() * max;
}
function randomFloat2(min, max) {
return min + Math.random() * (max - min);
}
function randomCentered(r) {
return randomFloat2(-r / 2, r / 2);
}
function randomNormal(mean = 0, sigma = 1) {
const [u1, u2] = [1 - Math.random(), Math.random()];
const norm = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * PI * u2);
return norm * sigma + mean;
}
function randomSeed(seed = 123456) {
seed = seed % 2147483647;
Math.random = () => {
seed = seed * 16807 % 2147483647;
return (seed - 1) / 2147483646;
};
}
function precision(num, digits = 4) {
if (Math.abs(num) === 0) return 0;
if (Array.isArray(num)) return num.map((val) => precision(val, digits));
const mult = 10 ** digits;
return Math.round(num * mult) / mult;
}
var isPowerOf2 = (num) => (num & num - 1) === 0;
var nextPowerOf2 = (num) => Math.pow(2, Math.ceil(Math.log2(num)));
function mod(v, n) {
return (v % n + n) % n;
}
var wrap = (v, min, max) => min + mod(v - min, max - min);
function clamp(v, min, max) {
if (v < min) return min;
if (v > max) return max;
return v;
}
var isBetween = (val, min, max) => min <= val && val <= max;
var lerp = (lo, hi, scale) => lo <= hi ? lo + (hi - lo) * scale : lo - (lo - hi) * scale;
function lerpScale(number, lo, hi) {
if (lo === hi) throw Error("lerpScale: lo === hi");
number = clamp(number, lo, hi);
return (number - lo) / (hi - lo);
}
var toDeg = 180 / Math.PI;
var toRad = Math.PI / 180;
function degToRad(degrees2) {
return mod2pi(degrees2 * toRad);
}
function radToDeg(radians2) {
return mod360(radians2 * toDeg);
}
var degToHeading = (degrees2) => mod360(90 - degrees2);
var headingToDeg = (heading) => mod360(90 - heading);
function mod360(degrees2) {
return mod(degrees2, 360);
}
function mod2pi(radians2) {
return mod(radians2, 2 * PI);
}
function mod180180(degrees2) {
let theta = mod360(degrees2);
if (theta > 180) theta -= 360;
return theta;
}
function radToHeading(radians2) {
const deg = radians2 * toDeg;
return mod360(90 - deg);
}
function headingToRad(heading) {
const deg = mod360(90 - heading);
return deg * toRad;
}
function radToHeadingAngle(radians2) {
return -radToDeg(radians2);
}
function headingAngleToRad(headingAngle) {
return -degToRad(headingAngle);
}
function degreesEqual(deg1, deg2) {
return mod360(deg1) === mod360(deg2);
}
function radsEqual(rads1, rads2) {
return mod2pi(rads1) === mod2pi(rads2);
}
var headingsEq = degreesEqual;
function subtractRadians(rad1, rad0) {
let dr = mod2pi(rad1 - rad0);
if (dr > PI) dr = dr - 2 * PI;
return dr;
}
function subtractDegrees(deg1, deg0) {
let dAngle = mod360(deg1 - deg0);
if (dAngle > 180) dAngle = dAngle - 360;
return dAngle;
}
function subtractHeadings(head1, head0) {
return -subtractDegrees(head1, head0);
}
function radiansTowardXY(x, y, x1, y1) {
return Math.atan2(y1 - y, x1 - x);
}
function headingTowardXY(x, y, x1, y1) {
return radToHeading(radiansTowardXY(x, y, x1, y1));
}
function degreesTowardXY(x, y, x1, y1) {
return radToDeg(radiansTowardXY(x, y, x1, y1));
}
function inCone(x, y, radius, coneAngle, direction, x0, y0) {
if (sqDistance(x0, y0, x, y) > radius * radius) return false;
const angle12 = radiansTowardXY(x0, y0, x, y);
return coneAngle / 2 >= Math.abs(subtractRadians(direction, angle12));
}
var sqDistance = (x, y, x1, y1) => (x - x1) ** 2 + (y - y1) ** 2;
var distance = (x, y, x1, y1) => Math.sqrt(sqDistance(x, y, x1, y1));
var sqDistance3 = (x, y, z, x1, y1, z1) => (x - x1) ** 2 + (y - y1) ** 2 + (z - z1) ** 2;
var distance3 = (x, y, z, x1, y1, z1) => Math.sqrt(sqDistance3(x, y, z, x1, y1, z1));
async function runModel(model, steps = 500, useSeed = true) {
console.log("runModel: model", model);
if (useSeed) randomSeed();
if (isString(model)) model = (await import(model)).default;
if (isFunction(model)) model = new model();
await model.startup();
model.setup();
if (inMain()) {
await timeoutLoop(() => {
model.step();
}, steps);
} else {
for (let i = 0; i < steps; i++) model.step();
}
return model;
}
function classHasStartup(Class) {
console.log("classHasStartup?", Class);
const str = Class.toString();
let lines = str.split("\n");
lines = lines.filter((line) => !/^ *\/\//.test(line));
lines = lines.filter((line) => /startup\(\)/.test(line));
return lines.length > 0;
}
function toJSON(obj, indent = 0, topLevelArrayOK = true) {
let firstCall = topLevelArrayOK;
const blackList = ["rectCache"];
const json = JSON.stringify(
obj,
(key, val) => {
if (blackList.includes(key)) {
return void 0;
}
const isAgentArray = Array.isArray(val) && val.length > 0 && Number.isInteger(val[0].id);
if (isAgentArray && !firstCall) {
return val.map((v) => v.id);
}
firstCall = false;
return val;
},
indent
);
return json;
}
function sampleModel(model) {
const obj = {
ticks: model.ticks,
model: Object.keys(model),
patches: model.patches.length,
patch: model.patches.oneOf(),
turtles: model.turtles.length,
turtle: model.turtles.oneOf(),
links: model.links.length,
link: model.links.oneOf()
};
const json = toJSON(obj);
return JSON.parse(json);
}
var identityFcn = (o) => o;
var noopFcn = () => {
};
var propFcn = (prop) => (o) => o[prop];
function arraysEqual(a1, a2) {
if (a1.length !== a2.length) return false;
for (let i = 0; i < a1.length; i++) {
if (a1[i] !== a2[i]) return false;
}
return true;
}
function removeArrayItem(array, item) {
const ix = array.indexOf(item);
if (ix !== -1) {
array.splice(ix, 1);
} else {
throw Error(`removeArrayItem: ${item} not in array`);
}
return array;
}
var arraysToString = (arrays) => arrays.map((a) => `${a}`).join(",");
function forLoop(arrayOrObj, fcn) {
if (arrayOrObj.slice) {
for (let i = 0, len = arrayOrObj.length; i < len; i++) {
fcn(arrayOrObj[i], i, arrayOrObj);
}
} else {
Object.keys(arrayOrObj).forEach((k) => fcn(arrayOrObj[k], k, arrayOrObj));
}
}
function repeat(n, f, a = []) {
for (let i = 0; i < n; i++) f(i, a);
return a;
}
function step(n, step2, f) {
for (let i = 0; i < n; i += step2) f(i);
}
function range(length) {
return repeat(length, (i, a) => {
a[i] = i;
});
}
function grep(array, regex) {
return array.reduce((acc, val) => {
if (regex.test(val)) acc.push(val);
return acc;
}, []);
}
function concatArrays(array1, array2) {
const Type = array1.constructor;
if (Type === Array) {
return array1.concat(convertArrayType(array2, Array));
}
const array = new Type(array1.length + array2.length);
array.set(array1);
array.set(array2, array1.length);
return array;
}
function objectToString(obj, indent = 2, jsKeys = true) {
let str = JSON.stringify(obj, null, indent);
if (jsKeys) str = str.replace(/"([^"]+)":/gm, "$1:");
return str;
}
function objectLength(obj) {
return Object.keys(obj).length;
}
var objectsEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
function oneOf(array) {
return array[randomInt(array.length)];
}
function otherOneOf(array, item) {
if (array.length < 2) throw Error("otherOneOf: array.length < 2");
let other;
do {
other = oneOf(array);
} while (item === other);
return other;
}
var oneKeyOf = (obj) => oneOf(Object.keys(obj));
var oneValOf = (obj) => obj[oneKeyOf(obj)];
function sortNums(array, ascending = true) {
return array.sort((a, b) => ascending ? a - b : b - a);
}
function sortObjs(array, fcn, ascending = true) {
if (typeof fcn === "string") fcn = propFcn(fcn);
const comp = (a, b) => fcn(a) - fcn(b);
return array.sort((a, b) => ascending ? comp(a, b) : -comp(a, b));
}
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = randomInt(i);
[array[j], array[i]] = [array[i], array[j]];
}
return array;
}
function union(a1, a2) {
return Array.from(new Set(a1.concat(a2)));
}
function intersection(a1, a2) {
const set2 = new Set(a2);
return a1.filter((x) => set2.has(x));
}
function difference(a1, a2) {
const set2 = new Set(a2);
return a1.filter((x) => !set2.has(x));
}
function floatRamp(start, stop, numItems) {
if (numItems <= 1) throw Error("floatRamp: numItems must be > 1");
const a = [];
for (let i = 0; i < numItems; i++) {
a.push(start + (stop - start) * (i / (numItems - 1)));
}
return a;
}
function integerRamp(start, stop, numItems = stop - start + 1) {
return floatRamp(start, stop, numItems).map((a) => Math.round(a));
}
function nestedProperty(obj, path) {
if (typeof path === "string") path = path.split(".");
switch (path.length) {
case 1:
return obj[path[0]];
case 2:
return obj[path[0]][path[1]];
case 3:
return obj[path[0]][path[1]][path[2]];
case 4:
return obj[path[0]][path[1]][path[2]][path[3]];
default:
return path.reduce((obj2, param) => obj2[param], obj);
}
}
var arrayLast = (array) => array[array.length - 1];
var arrayMax = (array) => array.reduce((a, b) => Math.max(a, b));
var arrayMin = (array) => array.reduce((a, b) => Math.min(a, b));
var arrayExtent = (array) => [arrayMin(array), arrayMax(array)];
var arraysDiff = (a1, a2, ifcn = (i) => i) => {
if (a1.length !== a2.length)
return console.log("lengths differ", a1.length, a2.length);
const diffs = [];
for (let i = 0; i < a1.length; i++) {
if (a1[i] !== a2[i]) diffs.push([ifcn(i), a1[i], a2[i]]);
}
return diffs;
};
function arrayToMatrix(array, width, height) {
if (array.length !== width * height)
throw Error("arrayToMatrix: length !== width * height");
const matrix = [];
for (let i = 0; i < height; i++) {
const row = array.slice(i * width, (i + 1) * width);
matrix.push(row);
}
return matrix;
}
var matrixToArray = (matrix) => matrix.flat();
function isOofA(data) {
if (!isObject(data)) return false;
return Object.values(data).every((v) => isTypedArray(v));
}
function toOofA(aofo, spec) {
const length = aofo.length;
const keys = Object.keys(spec);
const oofa = {};
keys.forEach((k) => {
oofa[k] = new spec[k](length);
});
forLoop(aofo, (o, i) => {
keys.forEach((key) => oofa[key][i] = o[key]);
});
return oofa;
}
function oofaObject(oofa, i, keys) {
const obj = {};
keys.forEach((key) => {
obj[key] = oofa[key][i];
});
return obj;
}
function toAofO(oofa, keys = Object.keys(oofa)) {
const length = oofa[keys[0]].length;
const aofo = new Array(length);
forLoop(aofo, (val, i) => {
aofo[i] = oofaObject(oofa, i, keys);
});
return aofo;
}
function oofaBuffers(postData) {
const buffers = [];
forLoop(postData, (obj) => forLoop(obj, (a) => buffers.push(a.buffer)));
return buffers;
}
var typeOf = (obj) => ({}).toString.call(obj).match(/\s(\w+)/)[1].toLowerCase();
var isType = (obj, string) => typeOf(obj) === string;
var isOneOfTypes = (obj, array) => array.includes(typeOf(obj));
var isString = (obj) => isType(obj, "string");
var isObject = (obj) => isType(obj, "object");
var isArray = (obj) => Array.isArray(obj);
var isNumber = (obj) => isType(obj, "number");
var isInteger = (n) => Number.isInteger(n);
var isFunction = (obj) => isType(obj, "function");
var isImage = (obj) => isType(obj, "image");
var isCanvas = (obj) => isOneOfTypes(obj, ["htmlcanvaselement", "offscreencanvas"]);
var isImageable = (obj) => isOneOfTypes(obj, [
"image",
"htmlimageelement",
"htmlcanvaselement",
"offscreencanvas",
"imagebitmap"
]);
var isTypedArray = (obj) => typeOf(obj.buffer) === "arraybuffer";
var isUintArray = (obj) => /^uint.*array$/.test(typeOf(obj));
var isIntArray = (obj) => /^int.*array$/.test(typeOf(obj));
var isFloatArray = (obj) => /^float.*array$/.test(typeOf(obj));
var isArrayLike = (obj) => isArray(obj) || isTypedArray(obj);
var isColorLikeArray = (obj) => isArrayLike(obj) && [3, 4].includes(obj.length) && obj.every(
(i) => isInteger(i) && isBetween(i, 0, 255) || isNumber(i) && isBetween(i, 0, 1)
);
function isLittleEndian() {
const d32 = new Uint32Array([16909060]);
return new Uint8ClampedArray(d32.buffer)[0] === 4;
}
function convertArrayType(array, Type) {
const Type0 = array.constructor;
if (Type0 === Type) return array;
return Type.from(array);
}
function isDataSet(obj) {
return typeOf(obj) === "object" && obj.width && obj.height && obj.data;
}
function downloadCanvas(can, name = "download.png", quality = null) {
if (!(name.endsWith(".png") || name.endsWith(".jpeg"))) name = name + ".png";
const type = name.endsWith(".png") ? "image/png" : "image/jpeg";
const url2 = typeOf(can) === "string" ? can : can.toDataURL(type, quality);
const link = document.createElement("a");
link.download = name;
link.href = url2;
link.click();
}
function downloadBlob(blobable, name = "download", format = true) {
if (isDataSet(blobable) && !Array.isArray(blobable.data))
blobable.data = Array.from(blobable.data);
if (isTypedArray(blobable)) blobable = Array.from(blobable);
if (isObject(blobable) || Array.isArray(blobable))
blobable = format ? JSON.stringify(blobable, null, 2) : JSON.stringify(blobable);
const blob = typeOf(blobable) === "blob" ? blobable : new Blob([blobable]);
const url2 = URL.createObjectURL(blob);
const link = document.createElement("a");
link.download = name;
link.href = url2;
link.click();
URL.revokeObjectURL(url2);
}
function downloadJson(json, name = "download.json") {
downloadBlob(json, name);
}
function downloadJsonModule(json, name = "json.js") {
const string = JSON.stringify(json, null, 2);
const module = `const json = ${string}
export default json`;
downloadBlob(module, name);
}
async function imagePromise(url2, preferDOM = true) {
if (inMain() && preferDOM || inDeno()) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "Anonymous";
img.onload = () => resolve(img);
img.onerror = () => reject(`Could not load image ${url2}`);
img.src = url2;
});
} else if (inWorker() || !preferDOM) {
const blob = await fetch(url2).then((response) => response.blob());
return createImageBitmap(blob);
}
}
async function fetchImage(url2) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "Anonymous";
img.onload = () => resolve(img);
img.onerror = () => reject(`Could not load image ${url2}`);
img.src = url2;
});
}
async function fetchImageBitmap(url2) {
const blob = await fetchData(url2, "blob");
return createImageBitmap(blob);
}
function createCanvas(width, height, preferDOM = true) {
if (inMain() && preferDOM) {
const can = document.createElement("canvas");
can.width = width;
can.height = height;
return can;
} else if (inDeno()) {
return globalThis.createCanvas(width, height);
} else if (inWorker() || !preferDOM) {
return new OffscreenCanvas(width, height);
}
}
function createCtx(width, height, preferDOM = true, attrs = {}) {
const can = createCanvas(width, height, preferDOM);
const ctx = can.getContext("2d", attrs);
if (inDeno()) {
const ctxObj = {
canvas: can
};
Object.setPrototypeOf(ctxObj, ctx);
return ctxObj;
} else {
return ctx;
}
}
function cloneCanvas(can, preferDOM = true) {
const ctx = createCtx(can.width, can.height, preferDOM);
ctx.drawImage(can, 0, 0);
return ctx.canvas;
}
function resizeCtx(ctx, width, height) {
const copy = cloneCanvas(ctx.canvas);
ctx.canvas.width = width;
ctx.canvas.height = height;
ctx.drawImage(copy, 0, 0);
}
function setCanvasSize(can, width, height) {
if (can.width !== width || can.height != height) {
can.width = width;
can.height = height;
}
}
function setIdentity(ctx) {
ctx.save();
ctx.resetTransform();
}
function setTextProperties(ctx, font, textAlign = "center", textBaseline = "middle") {
Object.assign(ctx, { font, textAlign, textBaseline });
}
var bboxCtx;
function stringMetrics(string, font, textAlign = "center", textBaseline = "middle") {
if (!bboxCtx) bboxCtx = createCtx(0, 0);
setTextProperties(bboxCtx, font, textAlign, textBaseline);
const metrics = bboxCtx.measureText(string);
metrics.height = // not sure how safe this is but..
metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
return metrics;
}
function drawText(ctx, string, x, y, color, useIdentity = true) {
if (useIdentity) setIdentity(ctx);
ctx.fillStyle = color.css || color;
ctx.fillText(string, x, y);
if (useIdentity) ctx.restore();
}
function ctxImageData(ctx) {
return ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
}
function ctxImageColors(ctx) {
const typedArray = ctxImageData(ctx).data;
const colors = [];
step(typedArray.length, 4, (i) => colors.push(typedArray.subarray(i, i + 4)));
return colors;
}
function ctxImagePixels(ctx) {
const imageData = ctxImageData(ctx);
const pixels = new Uint32Array(imageData.data.buffer);
return pixels;
}
function clearCtx(ctx, cssColor3 = void 0) {
const { width, height } = ctx.canvas;
setIdentity(ctx);
if (!cssColor3 || cssColor3 === "transparent") {
ctx.clearRect(0, 0, width, height);
} else {
cssColor3 = cssColor3.css || cssColor3;
ctx.fillStyle = cssColor3;
ctx.fillRect(0, 0, width, height);
}
ctx.restore();
}
function imageToCtx(img) {
const { width, height } = img;
const ctx = createCtx(width, height);
fillCtxWithImage(ctx, img);
return ctx;
}
function imageToCanvas(img) {
return imageToCtx(img).canvas;
}
function fillCtxWithImage(ctx, img) {
setIdentity(ctx);
ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.restore();
}
function setCtxImage(ctx, img) {
setCanvasSize(ctx.canvas, img.width, img.height);
fillCtxWithImage(ctx, img);
}
function toWindow(obj) {
Object.assign(window, obj);
console.log("toWindow:", Object.keys(obj).join(", "));
}
function dump(model = window.model) {
const { patches: ps, turtles: ts, links: ls } = model;
Object.assign(window, { ps, ts, ls });
window.p = ps.length > 0 ? ps.oneOf() : {};
window.t = ts.length > 0 ? ts.oneOf() : {};
window.l = ls.length > 0 ? ls.oneOf() : {};
console.log("debug: ps, ts, ls, p, t, l dumped to window");
}
function addCssLink(url2) {
const link = document.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("href", url2);
document.head.appendChild(link);
}
async function fetchCssStyle(url2) {
if (url2.startsWith("/")) {
console.log("fetchCssStyle relative url", url2);
url2 = import.meta.resolve(url2);
console.log(" absolute url", url2);
}
const response = await fetch(url2);
if (!response.ok) throw Error(`fetchCssStyle: Not found: ${url2}`);
const css = await response.text();
addCssStyle(css);
return css;
}
function addCssStyle(css) {
const style = document.createElement("style");
style.innerHTML = css;
document.head.appendChild(style);
}
function getQueryString() {
return window.location.search.substr(1);
}
function parseQueryString(paramsString = getQueryString()) {
const results = {};
const searchParams = new URLSearchParams(paramsString);
for (const pair of searchParams.entries()) {
let [key, val] = pair;
if (val.match(/^[0-9.]+$/) || val.match(/^[0-9.]+e[0-9]+$/))
val = Number(val);
if (["true", "t", ""].includes(val)) val = true;
if (["false", "f"].includes(val)) val = false;
results[key] = val;
}
return results;
}
function RESTapi(parameters) {
return Object.assign(parameters, parseQueryString());
}
function printToPage(msg, element = document.body) {
if (typeof msg === "object") {
msg = JSON.stringify(msg, null, 2);
}
msg = "<pre>" + msg + "</pre>";
if (typeof element === "string") {
element = document.getElementById(element);
}
element.style.fontFamily = "monospace";
element.innerHTML += msg;
}
function getEventXY(element, evt) {
const rect = element.getBoundingClientRect();
return [evt.clientX - rect.left, evt.clientY - rect.top];
}
// src/steg.js
var steg_exports = {};
__export(steg_exports, {
decode: () => decode,
encode: () => encode,
stegMsgSize: () => stegMsgSize
});
async function toContext(img) {
const type = typeOf(img);
switch (type) {
// image url or html element
case "string":
img = await imagePromise(img);
case "htmlimageelement":
return imageToCtx(img);
// canvas
case "htmlcanvaselement":
case "offscreencanvas":
return img.getContext("2d");
// image 2D context
case "canvasrenderingcontext2d":
return img;
default:
throw Error("toContext: bad img type: " + type);
}
}
function toUint8Array(msg) {
const type = typeOf(msg);
switch (type) {
case "number":
msg = String.fromCharCode(msg);
// drop thru to 'string'
case "string":
return new TextEncoder().encode(msg);
case "uint8array":
case "uint8clampedarray":
return msg;
default:
throw Error("toUint8Array: bad msg type: " + type);
}
}
function charToBits(char) {
return [
char >> bits[0].shift,
char >> bits[1].shift & bits[1].msgMask,
char & bits[2].msgMask
];
}
var bits = [
{ shift: 5, msgMask: 7, dataMask: 248 },
// bits: 3
{ shift: 3, msgMask: 3, dataMask: 252 },
// bits: 2
{ shift: 0, msgMask: 7, dataMask: 248 }
// bits: 3
];
function checkSize(msg, width, height) {
const imgSize = width * height;
if (imgSize < msg.length)
throw Error(`encode: image size < msg.length: ${imgSize} ${msg.length}`);
}
function stegMsgSize(imgData) {
for (let i = 3; i < imgData.length; i = i + 4) {
if (imgData[i] === 254) return (i - 3) / 4;
}
throw Error(
`decode: no message terminator in image data, length = ${imgData.length}`
);
}
async function encode(img, msg) {
const ctx = await toContext(img);
const { width, height } = ctx.canvas;
checkSize(msg, width, height);
const msgArray = toUint8Array(msg);
console.log("msg buffer", msgArray);
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
console.log("imgageData.data", data);
let ix;
msgArray.forEach((char, i) => {
const [ch0, ch1, ch2] = charToBits(char);
ix = i * 4;
data[ix] = (data[ix++] & bits[0].dataMask) + ch0;
data[ix] = (data[ix++] & bits[1].dataMask) + ch1;
data[ix] = (data[ix++] & bits[2].dataMask) + ch2;
data[ix] = 255;
});
data[ix + 4] = 254;
console.log("encoded imgageData.data", data);
ctx.putImageData(imageData, 0, 0);
console.log("msg length", msg.length);
console.log("encode: embedded msg size", stegMsgSize(data));
return ctx;
}
async function decode(img, returnU8 = false) {
const ctx = await toContext(img);
const { width, height } = ctx.canvas;
const data = ctx.getImageData(0, 0, width, height).data;
const msgSize = stegMsgSize(data);
console.log("decode: embedded msg size", msgSize);
const msgArray = new Uint8Array(msgSize);
msgArray.forEach((char, i) => {
let ix = i * 4;
const ch0 = (bits[0].msgMask & data[ix++]) << bits[0].shift;
const ch1 = (bits[1].msgMask & data[ix++]) << bits[1].shift;
const ch2 = (bits[2].msgMask & data[ix++]) << bits[2].shift;
msgArray[i] = ch0 + ch1 + ch2;
});
console.log("decode msgArray", msgArray);
if (returnU8) return msgArray;
return new TextDecoder().decode(msgArray);
}
// vendor/turfImports.js
var turfImports_exports = {};
__export(turfImports_exports, {
bbox: () => bbox,
bboxPolygon: () => bboxPolygon,
bearingToAzimuth: () => bearingToAzimuth,
booleanPointInPolygon: () => booleanPointInPolygon,
collectionOf: () => collectionOf,
containsNumber: () => containsNumber,
convertArea: () => convertArea,
convertLength: () => convertLength,
coordAll: () => coordAll,
coordEach: () => coordEach,
coordReduce: () => coordReduce,
feature: () => feature,
featureCollection: () => featureCollection,
featureEach: () => featureEach,
featureOf: () => featureOf,
featureReduce: () => featureReduce,
findPoint: () => findPoint,
findSegment: () => findSegment,
flattenEach: () => flattenEach,
flattenReduce: () => flattenReduce,
geojsonType: () => geojsonType,
geomEach: () => geomEach,
geomReduce: () => geomReduce,
geometry: () => geometry,
geometryCollection: () => geometryCollection,
getCoord: () => getCoord,
getCoords: () => getCoords,
getGeom: () => getGeom,
getType: () => getType,
lengthToDegrees: () => lengthToDegrees,
lengthToRadians: () => lengthToRadians,
lineEach: () => lineEach,
lineReduce: () => lineReduce,
lineString: () => lineString,
lineStrings: () => lineStrings,
multiLineString: () => multiLineString,
multiPoint: () => multiPoint,
multiPolygon: () => multiPolygon,
point: () => point,
points: () => points,
polygon: () => polygon,
polygons: () => polygons,
propEach: () => propEach,
propReduce: () => propReduce,
radiansToLength: () => radiansToLength,
segmentEach: () => segmentEach,
segmentReduce: () => segmentReduce
});
var earthRadius = 63710088e-1;
var factors = {
centimeters: earthRadius * 100,
centimetres: earthRadius * 100,
degrees: earthRadius / 111325,
feet: earthRadius * 3.28084,
inches: earthRadius * 39.37,
kilometers: earthRadius / 1e3,
kilometres: earthRadius / 1e3,
meters: earthRadius,
metres: earthRadius,
miles: earthRadius / 1609.344,
millimeters: earthRadius * 1e3,
millimetres: earthRadius * 1e3,
nauticalmiles: earthRadius / 1852,
radians: 1,
yards: earthRadius * 1.0936
};
var areaFactors = {
acres: 247105e-9,
centimeters: 1e4,
centimetres: 1e4,
feet: 10.763910417,
hectares: 1e-4,
inches: 1550.003100006,
kilometers: 1e-6,
kilometres: 1e-6,
meters: 1,
metres: 1,
miles: 386e-9,
millimeters: 1e6,
millimetres: 1e6,
yards: 1.195990046
};
function feature(geom, properties, options) {
if (options === void 0) {
options = {};
}
var feat = { type: "Feature" };
if (options.id === 0 || options.id) {
feat.id = options.id;
}
if (options.bbox) {
feat.bbox = options.bbox;
}
feat.properties = properties || {};
feat.geometry = geom;
return feat;
}
function geometry(type, coordinates, _options) {
switch (type) {
case "Point":
return point(coordinates).geometry;
case "LineString":
return lineString(coordinates).geometry;
case "Polygon":
return polygon(coordinates).geometry;
case "MultiPoint":
return multiPoint(coordinates).geometry;
case "MultiLineString":
return multiLineString(coordinates).geometry;
case "MultiPolygon":
return multiPolygon(coordinates).geometry;
default:
throw new Error(type + " is invalid");
}
}
function point(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
if (!coordinates) {
throw new Error("coordinates is required");
}
if (!Array.isArray(coordinates)) {
throw new Error("coordinates must be an Array");
}
if (coordinates.length < 2) {
throw new Error("coordinates must be at least 2 numbers long");
}
if (!isNumber2(coordinates[0]) || !isNumber2(coordinates[1])) {
throw new Error("coordinates must contain numbers");
}
var geom = {
type: "Point",
coordinates
};
return feature(geom, properties, options);
}
function points(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
return featureCollection(coordinates.map(function(coords) {
return point(coords, properties);
}), options);
}
function polygon(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) {
var ring = coordinates_1[_i];
if (ring.length < 4) {
throw new Error("Each LinearRing of a Polygon must have 4 or more Positions.");
}
for (var j = 0; j < ring[ring.length - 1].length; j++) {
if (ring[ring.length - 1][j] !== ring[0][j]) {
throw new Error("First and last Position are not equivalent.");
}
}
}
var geom = {
type: "Polygon",
coordinates
};
return feature(geom, properties, options);
}
function polygons(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
return featureCollection(coordinates.map(function(coords) {
return polygon(coords, properties);
}), options);
}
function lineString(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
if (coordinates.length < 2) {
throw new Error("coordinates must be an array of two or more positions");
}
var geom = {
type: "LineString",
coordinates
};
return feature(geom, properties, options);
}
function lineStrings(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
return featureCollection(coordinates.map(function(coords) {
return lineString(coords, properties);
}), options);
}
function featureCollection(features, options) {
if (options === void 0) {
options = {};
}
var fc = { type: "FeatureCollection" };
if (options.id) {
fc.id = options.id;
}
if (options.bbox) {
fc.bbox = options.bbox;
}
fc.features = features;
return fc;
}
function multiLineString(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
var geom = {
type: "MultiLineString",
coordinates
};
return feature(geom, properties, options);
}
function multiPoint(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
var geom = {
type: "MultiPoint",
coordinates
};
return feature(geom, properties, options);
}
function multiPolygon(coordinates, properties, options) {
if (options === void 0) {
options = {};
}
var geom = {
type: "MultiPolygon",
coordinates
};
return feature(geom, properties, options);
}
function geometryCollection(geometries3, properties, options) {
if (options === void 0) {
options = {};
}
var geom = {
type: "GeometryCollection",
geometries: geometries3
};
return feature(geom, properties, options);
}
function radiansToLength(radians2, units) {
if (units === void 0) {
units = "kilometers";
}
var factor = factors[units];
if (!factor) {
throw new Error(units + " units is invalid");
}
return radians2 * factor;
}
function lengthToRadians(distance2, units) {
if (units === void 0) {
units = "kilometers";
}
var factor = factors[units];
if (!factor) {
throw new Error(units + " units is invalid");
}
return distance2 / factor;
}
function lengthToDegrees(distance2, units) {
return radiansToDegrees(lengthToRadians(distance2, units));
}
function bearingToAzimuth(bearing) {
var angle = bearing % 360;
if (angle < 0) {
angle += 360;
}
return angle;
}
function radiansToDegrees(radians2) {
var degrees2 = radians2 % (2 * Math.PI);
return degrees2 * 180 / Math.PI;
}
function convertLength(length, originalUnit, finalUnit) {
if (originalUnit === void 0) {
originalUnit = "kilometers";
}
if (finalUnit === void 0) {
finalUnit = "kilometers";
}
if (!(length >= 0)) {
throw new Error("length must be a positive number");
}
return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);
}
function convertArea(area2, originalUnit, finalUnit) {
if (originalUnit === void 0) {
originalUnit = "meters";
}
if (finalUnit === void 0) {
finalUnit = "kilometers";
}
if (!(area2 >= 0)) {
throw new Error("area must be a positive number");
}
var startFactor = areaFactors[originalUnit];
if (!startFactor) {
throw new Error("invalid original units");
}
var finalFactor = areaFactors[finalUnit];
if (!finalFactor) {
throw new Error("invalid final units");
}
return area2 / startFactor * finalFactor;
}
function isNumber2(num) {
return !isNaN(num) && num !== null && !Array.isArray(num);
}
function isObject2(input) {
return !!input && input.constructor === Object;
}
function coordEach(geojson, callback, excludeWrapCoord) {
if (geojson === null) return;
var j, k, l, geometry2, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === "FeatureCollection", isFeature = type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
geometryMaybeCollection = isFeatureCollection ? geojson.features[featureIndex].geometry : isFeature ? geojson.geometry : geojson;
isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false;
stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
var multiFeatureIndex = 0;
var geometryIndex = 0;
geometry2 = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;
if (geometry2 === null) continue;
coords = geometry2.coordinates;
var geomType = geometry2.type;
wrapShrink = excludeWrapCoord && (geomType === "Polygon" || geomType === "MultiPolygon") ? 1 : 0;
switch (geomType) {
case null:
break;
case "Point":
if (callback(
coords,
coordIndex,
featureIndex,
multiFeatureIndex,
geometryIndex
) === false)
return false;
coordIndex++;
multiFeatureIndex++;
break;
case "LineString":
case "MultiPoint":
for (j = 0; j < coords.length; j++) {
if (callback(
coords[j],
coordIndex,
featureIndex,
multiFeatureIndex,
geometryIndex
) === false)
return false;
coordIndex++;
if (geomType === "MultiPoint") multiFeatureIndex++;
}
if (geomType === "LineString") multiFeatureIndex++;
break;
case "Polygon":
case "MultiLineString":
for (j = 0; j < coords.length; j++) {
for (k = 0; k < coords[j].length - wrapShrink; k++) {
if (callback(
coords[j][k],
coordIndex,
featureIndex,
multiFeatureIndex,
geometryIndex
) === false)
return false;
coordIndex++;
}
if (geomType === "MultiLineString") multiFeatureIndex++;
if (geomType === "Polygon") geometryIndex++;
}
if (geomType === "Polygon") multiFeatureIndex++;
break;
case "MultiPolygon":
for (j = 0; j < coords.length; j++) {
geometryIndex = 0;
for (k = 0; k < coords[j].length; k++) {
for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
if (callback(
coords[j][k][l],
coordIndex,
featureIndex,
multiFeatureIndex,
geometryIndex
) === false)
return false;
coordIndex++;
}
geometryIndex++;
}
multiFeatureIndex++;
}
break;
case "GeometryCollection":
for (j = 0; j < geometry2.geometries.length; j++)
if (coordEach(geometry2.geometries[j], callback, excludeWrapCoord) === false)
return false;
break;
default:
throw new Error("Unknown Geometry Type");
}
}
}
}
function coordReduce(geojson, callback, initialValue, excludeWrapCoord) {
var previousValue = initialValue;
coordEach(
geojson,
function(currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {
if (coordIndex === 0 && initialValue === void 0)
previousValue = currentCoord;
else
previousValue = callback(
previousValue,
currentCoord,
coordIndex,
featureIndex,
multiFeatureIndex,
geometryIndex
);
},
excludeWrapCoord
);
return previousValue;
}
function propEach(geojson, callback) {
var i;
switch (geojson.type) {
case "FeatureCollection":
for (i = 0; i < geojson.features.length; i++) {
if (callback(geojson.features[i].properties, i) === false) break;
}
break;
case "Feature":
callback(geojson.properties, 0);
break;
}
}
function propReduce(geojson, callback, initialValue) {
var previousValue = initialValue;
propEach(geojson, function(currentProperties, featureIndex) {
if (featureIndex === 0 && initialValue === void 0)
previousValue = currentProperties;
else
previousValue = callback(previousValue, currentProperties, featureIndex);
});
return previousValue;
}
function featureEach(geojson, callback) {
if (geojson.type === "Feature") {
callback(geojson, 0);
} else if (geojson.type === "FeatureCollection") {
for (var i = 0; i < geojson.features.length; i++) {
if (callback(geojson.features[i], i) === false) break;
}
}
}
function featureReduce(geojson, callback, initialValue) {
var previousValue = initialValue;
featureEach(geojson, function(currentFeature, featureIndex) {
if (featureIndex === 0 && initialValue === void 0)
previousValue = currentFeature;
else previousValue = callback(previousValue, currentFeature, featureIndex);
});
return previousValue;
}
function coordAll(geojson) {
var coords = [];
coordEach(geojson, function(coord) {
coords.push(coord);
});
return coords;
}
function geomEach(geojson, callback) {
var i, j, g, geometry2, stopG, geometryMaybeCollection, isGeometryCollection, featureProperties, featureBBox, featureId, featureIndex = 0, isFeatureCollection = geojson.type === "FeatureCollection", isFeature = geojson.type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
for (i = 0; i < stop; i++) {
geometryMaybeCollection = isFeatureCollection ? geojson.features[i].geometry : isFeature ? geojson.geometry : geojson;
featureProperties = isFeatureCollection ? geojson.features[i].properties : isFeature ? geojson.properties : {};
featureBBox = isFeatureCollection ? geojson.features[i].bbox : isFeature ? geojson.bbox : void 0;
featureId = isFeatureCollection ? geojson.features[i].id : isFeature ? geojson.id : void 0;
isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false;
stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
for (g = 0; g < stopG; g++) {
geometry2 = isGeometryCollection ? geometryMaybeCollection.geometries[g] : geometryMaybeCollection;
if (geometry2 === null) {
if (callback(
null,
featureIndex,
featureProperties,
featureBBox,
featureId
) === false)
return false;
continue;
}
switch (geometry2.type) {
case "Point":
case "LineString":
case "MultiPoint":
case "Polygon":
case "MultiLineString":
case "MultiPolygon": {
if (callback(
geometry2,
featureIndex,
featureProperties,
featureBBox,
featureId
) === false)
return false;
break;
}
case "GeometryCollection": {
for (j = 0; j < geometry2.geometries.length; j++) {
if (callback(
geometry2.geometries[j],
featureIndex,
featureProperties,
featureBBox,
featureId
) === false)
return false;
}
break;
}
default:
throw new Error("Unknown Geometry Type");