feat(map): add fixed ENU and WGS84 sector grid
This commit is contained in:
+191
-21
@@ -520,21 +520,183 @@ const MAP_PAGE_SETTING_KEYS = new Set([
|
||||
"buildingsOpacity", "buildingsDetail", "imageryBrightness", "imageryContrast",
|
||||
"imagerySaturation", "gridVisible", "gridLodEnabled", "gridHeightMeters",
|
||||
"grid3dEnabled", "gridGraticuleEnabled", "gridCenterMode", "gridCenterLatitude",
|
||||
"gridCenterLongitude", "gridTileSizeKm", "gridAutoDisableHeightKm", "gridRebuildOnMoveEnd",
|
||||
"gridCenterLongitude", "gridTileSizeKm", "gridAutoDisableHeightKm", "gridRebuildOnMoveEnd", "gridLegacyMode",
|
||||
"gridMax3dViewAngleDegrees",
|
||||
"gridLod1MaxHeightKm", "gridLod1StepKm", "gridLod2MaxHeightKm", "gridLod2StepKm",
|
||||
"gridLod3MaxHeightKm", "gridLod3StepKm", "gridLod4MaxHeightKm", "gridLod4StepKm",
|
||||
"gridLod5StepKm", "gridLod1Mode", "gridLod2Mode", "gridLod3Mode", "gridLod4Mode",
|
||||
"gridLod5MaxHeightKm", "gridLod5StepKm", "gridLod1Mode", "gridLod2Mode", "gridLod3Mode", "gridLod4Mode",
|
||||
"gridLod5Mode", "gridRadiusKm", "gridLineWidth", "gridLineDiameterMeters", "gridColor", "gridOpacity",
|
||||
"gridDotsEnabled", "gridDotsSize", "gridDotsDiameterMeters", "gridDotsColor", "gridDotsOpacity",
|
||||
"gridCrossesEnabled", "gridCrossesLengthMeters", "gridCrossesWidthMeters",
|
||||
"gridCrossesColor", "gridCrossesOpacity",
|
||||
"gridCrossesColor", "gridCrossesOpacity", "gridLodProfiles",
|
||||
]);
|
||||
|
||||
const GRID_LOD_PROFILE_KEYS = new Set([
|
||||
"maxHeightKm", "stepKm", "mode", "heightMeters", "max3dViewAngleDegrees", "tileSizeKm", "radiusKm",
|
||||
"lineDiameterMeters", "lineColor", "lineOpacity", "dotsEnabled", "dotsDiameterMeters",
|
||||
"dotsColor", "dotsOpacity", "crossesEnabled", "crossesLengthMeters", "crossesWidthMeters",
|
||||
"crossesColor", "crossesOpacity", "graticuleStepDegrees", "graticuleLineWidthPx", "graticuleColor",
|
||||
"graticuleOpacity",
|
||||
]);
|
||||
|
||||
const GRID_LOD_PROFILE_INPUT_KEYS = new Set([...GRID_LOD_PROFILE_KEYS, "lineWidthPx"]);
|
||||
const MAX_LOCAL_GRID_INDEX = 512;
|
||||
const LEGACY_GRID_PROFILE_SETTING_KEYS = new Set([
|
||||
"gridHeightMeters", "gridTileSizeKm", "gridMax3dViewAngleDegrees", "gridRadiusKm",
|
||||
"gridLineWidth", "gridLineDiameterMeters", "gridColor", "gridOpacity",
|
||||
"gridDotsEnabled", "gridDotsSize", "gridDotsDiameterMeters", "gridDotsColor", "gridDotsOpacity",
|
||||
"gridCrossesEnabled", "gridCrossesLengthMeters", "gridCrossesWidthMeters", "gridCrossesColor", "gridCrossesOpacity",
|
||||
...Array.from({ length: 5 }, (_unused, index) => index + 1).flatMap((number) => [
|
||||
`gridLod${number}MaxHeightKm`, `gridLod${number}StepKm`, `gridLod${number}Mode`,
|
||||
]),
|
||||
]);
|
||||
|
||||
// Exact effective values of the tracked Engine MMAP/MOSCOWMAP Cesium grid.
|
||||
// These are persisted by Foundry as presentation policy; the renderer remains
|
||||
// a provider adapter and does not own or silently retune the sector definition.
|
||||
const DEFAULT_GRID_LOD_PROFILES = Object.freeze([
|
||||
Object.freeze({
|
||||
maxHeightKm: 10, stepKm: 1, mode: "3d", heightMeters: 300, max3dViewAngleDegrees: 30,
|
||||
tileSizeKm: 10, radiusKm: 50, lineDiameterMeters: 4, lineColor: "#f5f5f5", lineOpacity: 12,
|
||||
dotsEnabled: true, dotsDiameterMeters: 7, dotsColor: "#ffffff", dotsOpacity: 58,
|
||||
crossesEnabled: false, crossesLengthMeters: 60, crossesWidthMeters: 10, crossesColor: "#9c9c9c", crossesOpacity: 46,
|
||||
graticuleStepDegrees: 0.25, graticuleLineWidthPx: 1, graticuleColor: "#f5f5f5", graticuleOpacity: 12,
|
||||
}),
|
||||
Object.freeze({
|
||||
maxHeightKm: 50, stepKm: 5, mode: "3d", heightMeters: 500, max3dViewAngleDegrees: 30,
|
||||
tileSizeKm: 10, radiusKm: 1_000, lineDiameterMeters: 10, lineColor: "#f8fbfc", lineOpacity: 12,
|
||||
dotsEnabled: true, dotsDiameterMeters: 80, dotsColor: "#ffffff", dotsOpacity: 22,
|
||||
crossesEnabled: false, crossesLengthMeters: 60, crossesWidthMeters: 10, crossesColor: "#9c9c9c", crossesOpacity: 46,
|
||||
graticuleStepDegrees: 0.5, graticuleLineWidthPx: 1, graticuleColor: "#f8fbfc", graticuleOpacity: 12,
|
||||
}),
|
||||
Object.freeze({
|
||||
maxHeightKm: 200, stepKm: 25, mode: "3d", heightMeters: 500, max3dViewAngleDegrees: 30,
|
||||
tileSizeKm: 25, radiusKm: 1_000, lineDiameterMeters: 7, lineColor: "#fafafa", lineOpacity: 12,
|
||||
dotsEnabled: true, dotsDiameterMeters: 10, dotsColor: "#ffffff", dotsOpacity: 58,
|
||||
crossesEnabled: false, crossesLengthMeters: 60, crossesWidthMeters: 10, crossesColor: "#9c9c9c", crossesOpacity: 46,
|
||||
graticuleStepDegrees: 1, graticuleLineWidthPx: 1, graticuleColor: "#fafafa", graticuleOpacity: 12,
|
||||
}),
|
||||
Object.freeze({
|
||||
maxHeightKm: 800, stepKm: 50, mode: "graticule", heightMeters: 500, max3dViewAngleDegrees: 30,
|
||||
tileSizeKm: 10, radiusKm: 1_000, lineDiameterMeters: 10, lineColor: "#fcfdfd", lineOpacity: 12,
|
||||
dotsEnabled: true, dotsDiameterMeters: 10, dotsColor: "#fcfdfd", dotsOpacity: 58,
|
||||
crossesEnabled: false, crossesLengthMeters: 60, crossesWidthMeters: 10, crossesColor: "#9c9c9c", crossesOpacity: 46,
|
||||
graticuleStepDegrees: 2, graticuleLineWidthPx: 1, graticuleColor: "#fcfdfd", graticuleOpacity: 12,
|
||||
}),
|
||||
Object.freeze({
|
||||
maxHeightKm: 3_000, stepKm: 50, mode: "graticule", heightMeters: 500, max3dViewAngleDegrees: 30,
|
||||
tileSizeKm: 10, radiusKm: 100, lineDiameterMeters: 7, lineColor: "#9c9c9c", lineOpacity: 12,
|
||||
dotsEnabled: true, dotsDiameterMeters: 10, dotsColor: "#9c9c9c", dotsOpacity: 58,
|
||||
crossesEnabled: false, crossesLengthMeters: 60, crossesWidthMeters: 10, crossesColor: "#9c9c9c", crossesOpacity: 46,
|
||||
graticuleStepDegrees: 2, graticuleLineWidthPx: 1, graticuleColor: "#9c9c9c", graticuleOpacity: 8,
|
||||
}),
|
||||
]);
|
||||
|
||||
function promoteLegacyGridLodProfiles(settings) {
|
||||
return DEFAULT_GRID_LOD_PROFILES.map((fallback, index) => {
|
||||
const number = index + 1;
|
||||
return {
|
||||
...fallback,
|
||||
maxHeightKm: settings[`gridLod${number}MaxHeightKm`] ?? fallback.maxHeightKm,
|
||||
stepKm: settings[`gridLod${number}StepKm`] ?? fallback.stepKm,
|
||||
mode: settings[`gridLod${number}Mode`] ?? fallback.mode,
|
||||
heightMeters: settings.gridHeightMeters ?? fallback.heightMeters,
|
||||
max3dViewAngleDegrees: settings.gridMax3dViewAngleDegrees ?? fallback.max3dViewAngleDegrees,
|
||||
tileSizeKm: settings.gridTileSizeKm ?? fallback.tileSizeKm,
|
||||
radiusKm: settings.gridRadiusKm ?? fallback.radiusKm,
|
||||
lineDiameterMeters: settings.gridLineDiameterMeters ?? fallback.lineDiameterMeters,
|
||||
lineColor: settings.gridColor ?? fallback.lineColor,
|
||||
lineOpacity: settings.gridOpacity ?? fallback.lineOpacity,
|
||||
dotsEnabled: settings.gridDotsEnabled ?? fallback.dotsEnabled,
|
||||
dotsDiameterMeters: settings.gridDotsDiameterMeters ?? fallback.dotsDiameterMeters,
|
||||
dotsColor: settings.gridDotsColor ?? fallback.dotsColor,
|
||||
dotsOpacity: settings.gridDotsOpacity ?? fallback.dotsOpacity,
|
||||
crossesEnabled: settings.gridCrossesEnabled ?? fallback.crossesEnabled,
|
||||
crossesLengthMeters: settings.gridCrossesLengthMeters ?? fallback.crossesLengthMeters,
|
||||
crossesWidthMeters: settings.gridCrossesWidthMeters ?? fallback.crossesWidthMeters,
|
||||
crossesColor: settings.gridCrossesColor ?? fallback.crossesColor,
|
||||
crossesOpacity: settings.gridCrossesOpacity ?? fallback.crossesOpacity,
|
||||
graticuleLineWidthPx: settings.gridLineWidth ?? fallback.graticuleLineWidthPx,
|
||||
graticuleColor: settings.gridColor ?? fallback.graticuleColor,
|
||||
graticuleOpacity: settings.gridOpacity ?? fallback.graticuleOpacity,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function validateGridLodProfiles(value) {
|
||||
if (!Array.isArray(value) || value.length !== 5) throw applicationError("invalid_map_grid_lod_profiles");
|
||||
let previousMaxHeightKm = Number.NEGATIVE_INFINITY;
|
||||
return value.map((profile, index) => {
|
||||
if (!isObject(profile) || Object.keys(profile).some((key) => !GRID_LOD_PROFILE_INPUT_KEYS.has(key))) {
|
||||
throw applicationError(`invalid_map_grid_lod_profile_${index + 1}`);
|
||||
}
|
||||
const legacyProfile = Object.hasOwn(profile, "lineWidthPx");
|
||||
const normalized = legacyProfile ? {
|
||||
...profile,
|
||||
graticuleStepDegrees: profile.graticuleStepDegrees ?? DEFAULT_GRID_LOD_PROFILES[index].graticuleStepDegrees,
|
||||
graticuleLineWidthPx: profile.graticuleLineWidthPx ?? profile.lineWidthPx,
|
||||
graticuleColor: profile.graticuleColor ?? profile.lineColor,
|
||||
graticuleOpacity: profile.graticuleOpacity ?? profile.lineOpacity,
|
||||
} : { ...profile };
|
||||
delete normalized.lineWidthPx;
|
||||
if (GRID_LOD_PROFILE_KEYS.size !== Object.keys(normalized).length
|
||||
|| [...GRID_LOD_PROFILE_KEYS].some((key) => !Object.hasOwn(normalized, key))) {
|
||||
throw applicationError(`invalid_map_grid_lod_profile_${index + 1}`);
|
||||
}
|
||||
const code = (key) => `invalid_map_grid_lod_profile_${index + 1}_${key}`;
|
||||
const maxHeightKm = requireNumber(normalized.maxHeightKm, 0.1, 100_000, code("maxHeightKm"));
|
||||
if (maxHeightKm <= previousMaxHeightKm) {
|
||||
throw applicationError(`invalid_map_grid_lod_profile_${index + 1}_maxHeightKm_order`);
|
||||
}
|
||||
previousMaxHeightKm = maxHeightKm;
|
||||
if (!['3d', 'graticule'].includes(normalized.mode)) throw applicationError(code("mode"));
|
||||
const stepKm = requireNumber(normalized.stepKm, 0.1, 5_000, code("stepKm"));
|
||||
const radiusKm = requireNumber(normalized.radiusKm, 1, 100_000, code("radiusKm"));
|
||||
if (radiusKm / stepKm > MAX_LOCAL_GRID_INDEX) {
|
||||
throw applicationError(`invalid_map_grid_lod_profile_${index + 1}_workload`);
|
||||
}
|
||||
return {
|
||||
maxHeightKm,
|
||||
stepKm,
|
||||
mode: normalized.mode,
|
||||
heightMeters: requireNumber(normalized.heightMeters, 0, 5_000, code("heightMeters")),
|
||||
max3dViewAngleDegrees: requireNumber(normalized.max3dViewAngleDegrees, 30, 170, code("max3dViewAngleDegrees")),
|
||||
tileSizeKm: requireNumber(normalized.tileSizeKm, 1, 50, code("tileSizeKm")),
|
||||
radiusKm,
|
||||
lineDiameterMeters: requireNumber(normalized.lineDiameterMeters, 1, 100, code("lineDiameterMeters")),
|
||||
lineColor: requireHex(normalized.lineColor, code("lineColor")),
|
||||
lineOpacity: requireNumber(normalized.lineOpacity, 0, 100, code("lineOpacity")),
|
||||
dotsEnabled: requireBoolean(normalized.dotsEnabled, code("dotsEnabled")),
|
||||
dotsDiameterMeters: requireNumber(normalized.dotsDiameterMeters, 1, 1_000, code("dotsDiameterMeters")),
|
||||
dotsColor: requireHex(normalized.dotsColor, code("dotsColor")),
|
||||
dotsOpacity: requireNumber(normalized.dotsOpacity, 0, 100, code("dotsOpacity")),
|
||||
crossesEnabled: requireBoolean(normalized.crossesEnabled, code("crossesEnabled")),
|
||||
crossesLengthMeters: requireNumber(normalized.crossesLengthMeters, 1, 5_000, code("crossesLengthMeters")),
|
||||
crossesWidthMeters: requireNumber(normalized.crossesWidthMeters, 1, 500, code("crossesWidthMeters")),
|
||||
crossesColor: requireHex(normalized.crossesColor, code("crossesColor")),
|
||||
crossesOpacity: requireNumber(normalized.crossesOpacity, 0, 100, code("crossesOpacity")),
|
||||
graticuleStepDegrees: requireNumber(normalized.graticuleStepDegrees, 0.1, 180, code("graticuleStepDegrees")),
|
||||
graticuleLineWidthPx: requireNumber(normalized.graticuleLineWidthPx, 1, 3, code("graticuleLineWidthPx")),
|
||||
graticuleColor: requireHex(normalized.graticuleColor, code("graticuleColor")),
|
||||
graticuleOpacity: requireNumber(normalized.graticuleOpacity, 0, 100, code("graticuleOpacity")),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function validateMapPageSettingsPatch(value) {
|
||||
if (!isObject(value) || Object.keys(value).length === 0) throw applicationError("invalid_map_page_settings_patch");
|
||||
if (Object.keys(value).some((key) => !MAP_PAGE_SETTING_KEYS.has(key))) throw applicationError("invalid_map_page_settings_patch_field");
|
||||
return value;
|
||||
if (value.gridCenterMode !== undefined && !["camera", "fixed"].includes(value.gridCenterMode)) {
|
||||
throw applicationError("invalid_map_page_setting_gridCenterMode");
|
||||
}
|
||||
if (value.gridLodProfiles === undefined && Object.keys(value).some((key) => LEGACY_GRID_PROFILE_SETTING_KEYS.has(key))) {
|
||||
throw applicationError("map_grid_lod_profiles_required");
|
||||
}
|
||||
return {
|
||||
...value,
|
||||
...(value.gridCenterMode !== undefined ? { gridCenterMode: "fixed" } : {}),
|
||||
...(value.gridLodProfiles !== undefined ? { gridLodProfiles: validateGridLodProfiles(value.gridLodProfiles) } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
function validateMapInspectorOpenSections(value) {
|
||||
@@ -565,7 +727,7 @@ function validateMapPageLayout(value) {
|
||||
// Layouts written before this field existed are safely upgraded to the
|
||||
// no-overwrite default during read/save; they are not rejected as damaged.
|
||||
if (settings.cacheNoOverwrite !== undefined) requireBoolean(settings.cacheNoOverwrite, "invalid_map_page_setting_cacheNoOverwrite");
|
||||
for (const key of ["grid3dEnabled", "gridGraticuleEnabled", "gridRebuildOnMoveEnd", "gridCrossesEnabled"]) {
|
||||
for (const key of ["grid3dEnabled", "gridGraticuleEnabled", "gridRebuildOnMoveEnd", "gridLegacyMode", "gridCrossesEnabled"]) {
|
||||
if (settings[key] !== undefined) requireBoolean(settings[key], `invalid_map_page_setting_${key}`);
|
||||
}
|
||||
requireString(settings.imagerySource, "invalid_map_page_imagery_source", 64);
|
||||
@@ -575,9 +737,11 @@ function validateMapPageLayout(value) {
|
||||
for (const key of ["monochromeColor", "globeColor", "backgroundColor", "buildingsColor", "gridColor", "gridDotsColor"]) {
|
||||
requireHex(settings[key], `invalid_map_page_setting_${key}`);
|
||||
}
|
||||
for (const key of ["gridCenterLatitude", "gridCenterLongitude", "gridTileSizeKm", "gridAutoDisableHeightKm", "gridMax3dViewAngleDegrees", "gridLod3MaxHeightKm", "gridLod4MaxHeightKm", "gridLod4StepKm", "gridLod5StepKm", "gridLineDiameterMeters", "gridDotsDiameterMeters", "gridCrossesLengthMeters", "gridCrossesWidthMeters", "gridCrossesOpacity"]) {
|
||||
for (const key of ["gridTileSizeKm", "gridAutoDisableHeightKm", "gridMax3dViewAngleDegrees", "gridLod3MaxHeightKm", "gridLod4MaxHeightKm", "gridLod4StepKm", "gridLod5MaxHeightKm", "gridLod5StepKm", "gridLineDiameterMeters", "gridDotsDiameterMeters", "gridCrossesLengthMeters", "gridCrossesWidthMeters", "gridCrossesOpacity"]) {
|
||||
if (settings[key] !== undefined) requireNumber(settings[key], -100000, 100000, `invalid_map_page_setting_${key}`);
|
||||
}
|
||||
if (settings.gridCenterLatitude !== undefined) requireNumber(settings.gridCenterLatitude, -90, 90, "invalid_map_page_setting_gridCenterLatitude");
|
||||
if (settings.gridCenterLongitude !== undefined) requireNumber(settings.gridCenterLongitude, -180, 180, "invalid_map_page_setting_gridCenterLongitude");
|
||||
if (settings.gridCrossesColor !== undefined) requireHex(settings.gridCrossesColor, "invalid_map_page_setting_gridCrossesColor");
|
||||
if (settings.gridCenterMode !== undefined && !["camera", "fixed"].includes(settings.gridCenterMode)) {
|
||||
throw applicationError("invalid_map_page_setting_gridCenterMode");
|
||||
@@ -587,6 +751,9 @@ function validateMapPageLayout(value) {
|
||||
throw applicationError(`invalid_map_page_setting_${key}`);
|
||||
}
|
||||
}
|
||||
const gridLodProfiles = validateGridLodProfiles(
|
||||
settings.gridLodProfiles ?? promoteLegacyGridLodProfiles(settings),
|
||||
);
|
||||
const camera = value.camera;
|
||||
for (const key of ["longitude", "latitude", "height", "heading", "pitch", "roll"]) {
|
||||
requireNumber(camera[key], -1_000_000_000, 1_000_000_000, `invalid_map_page_camera_${key}`);
|
||||
@@ -652,7 +819,7 @@ function validateMapPageLayout(value) {
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
pageId: "map",
|
||||
settings: { ...settings, cacheNoOverwrite: settings.cacheNoOverwrite ?? true },
|
||||
settings: { ...settings, cacheNoOverwrite: settings.cacheNoOverwrite ?? true, gridCenterMode: "fixed", gridLodProfiles },
|
||||
mapHeight: requireInteger(value.mapHeight, 360, 5000, "invalid_map_page_height"),
|
||||
camera: {
|
||||
longitude: camera.longitude,
|
||||
@@ -736,12 +903,13 @@ function defaultMapPageLayout() {
|
||||
gridLodEnabled: true,
|
||||
grid3dEnabled: true,
|
||||
gridGraticuleEnabled: true,
|
||||
gridCenterMode: "camera",
|
||||
gridCenterMode: "fixed",
|
||||
gridCenterLatitude: 55.7558,
|
||||
gridCenterLongitude: 37.6173,
|
||||
gridTileSizeKm: 10,
|
||||
gridAutoDisableHeightKm: 10000,
|
||||
gridRebuildOnMoveEnd: true,
|
||||
gridLegacyMode: false,
|
||||
gridMax3dViewAngleDegrees: 30,
|
||||
gridHeightMeters: 500,
|
||||
gridLod1MaxHeightKm: 10,
|
||||
@@ -750,29 +918,31 @@ function defaultMapPageLayout() {
|
||||
gridLod2MaxHeightKm: 50,
|
||||
gridLod2StepKm: 5,
|
||||
gridLod2Mode: "3d",
|
||||
gridLod3MaxHeightKm: 180,
|
||||
gridLod3MaxHeightKm: 200,
|
||||
gridLod3StepKm: 25,
|
||||
gridLod3Mode: "3d",
|
||||
gridLod4MaxHeightKm: 700,
|
||||
gridLod4StepKm: 100,
|
||||
gridLod4MaxHeightKm: 800,
|
||||
gridLod4StepKm: 50,
|
||||
gridLod4Mode: "graticule",
|
||||
gridLod5StepKm: 500,
|
||||
gridLod5MaxHeightKm: 3000,
|
||||
gridLod5StepKm: 50,
|
||||
gridLod5Mode: "graticule",
|
||||
gridRadiusKm: 1000,
|
||||
gridLineWidth: 4,
|
||||
gridLineDiameterMeters: 10,
|
||||
gridColor: "#f5f5f5",
|
||||
gridRadiusKm: 40,
|
||||
gridLineWidth: 1,
|
||||
gridLineDiameterMeters: 7,
|
||||
gridColor: "#9c9c9c",
|
||||
gridOpacity: 12,
|
||||
gridDotsEnabled: true,
|
||||
gridDotsSize: 7,
|
||||
gridDotsDiameterMeters: 80,
|
||||
gridDotsColor: "#ffffff",
|
||||
gridDotsDiameterMeters: 10,
|
||||
gridDotsColor: "#9c9c9c",
|
||||
gridDotsOpacity: 58,
|
||||
gridCrossesEnabled: false,
|
||||
gridCrossesLengthMeters: 200,
|
||||
gridCrossesLengthMeters: 60,
|
||||
gridCrossesWidthMeters: 10,
|
||||
gridCrossesColor: "#35cfff",
|
||||
gridCrossesOpacity: 50,
|
||||
gridCrossesColor: "#9c9c9c",
|
||||
gridCrossesOpacity: 46,
|
||||
gridLodProfiles: structuredClone(DEFAULT_GRID_LOD_PROFILES),
|
||||
},
|
||||
mapHeight: 470,
|
||||
camera: {
|
||||
|
||||
+40
-3
@@ -414,12 +414,13 @@ const mapPageSettingsPatchInputSchema = {
|
||||
gridLodEnabled: { type: "boolean" },
|
||||
grid3dEnabled: { type: "boolean" },
|
||||
gridGraticuleEnabled: { type: "boolean" },
|
||||
gridCenterMode: { type: "string", enum: ["camera", "fixed"] },
|
||||
gridCenterLatitude: { type: "number" },
|
||||
gridCenterLongitude: { type: "number" },
|
||||
gridCenterMode: { type: "string", enum: ["fixed"] },
|
||||
gridCenterLatitude: { type: "number", minimum: -90, maximum: 90 },
|
||||
gridCenterLongitude: { type: "number", minimum: -180, maximum: 180 },
|
||||
gridTileSizeKm: { type: "number" },
|
||||
gridAutoDisableHeightKm: { type: "number" },
|
||||
gridRebuildOnMoveEnd: { type: "boolean" },
|
||||
gridLegacyMode: { type: "boolean" },
|
||||
gridMax3dViewAngleDegrees: { type: "number" },
|
||||
gridHeightMeters: { type: "number" },
|
||||
gridLod1MaxHeightKm: { type: "number" },
|
||||
@@ -434,6 +435,7 @@ const mapPageSettingsPatchInputSchema = {
|
||||
gridLod4MaxHeightKm: { type: "number" },
|
||||
gridLod4StepKm: { type: "number" },
|
||||
gridLod4Mode: { type: "string", enum: ["3d", "graticule"] },
|
||||
gridLod5MaxHeightKm: { type: "number" },
|
||||
gridLod5StepKm: { type: "number" },
|
||||
gridLod5Mode: { type: "string", enum: ["3d", "graticule"] },
|
||||
gridRadiusKm: { type: "number" },
|
||||
@@ -451,6 +453,41 @@ const mapPageSettingsPatchInputSchema = {
|
||||
gridCrossesWidthMeters: { type: "number" },
|
||||
gridCrossesColor: { type: "string", pattern: "^#[0-9A-Fa-f]{6}$" },
|
||||
gridCrossesOpacity: { type: "number" },
|
||||
gridLodProfiles: {
|
||||
type: "array",
|
||||
minItems: 5,
|
||||
maxItems: 5,
|
||||
items: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
required: ["maxHeightKm", "stepKm", "mode", "heightMeters", "max3dViewAngleDegrees", "tileSizeKm", "radiusKm", "lineDiameterMeters", "lineColor", "lineOpacity", "dotsEnabled", "dotsDiameterMeters", "dotsColor", "dotsOpacity", "crossesEnabled", "crossesLengthMeters", "crossesWidthMeters", "crossesColor", "crossesOpacity", "graticuleStepDegrees", "graticuleLineWidthPx", "graticuleColor", "graticuleOpacity"],
|
||||
properties: {
|
||||
maxHeightKm: { type: "number", minimum: 0.1, maximum: 100000, description: "Strictly greater than the previous LOD maxHeightKm; enforced by Foundry." },
|
||||
stepKm: { type: "number", minimum: 0.1, maximum: 5000 },
|
||||
mode: { type: "string", enum: ["3d", "graticule"] },
|
||||
heightMeters: { type: "number", minimum: 0, maximum: 5000 },
|
||||
max3dViewAngleDegrees: { type: "number", minimum: 30, maximum: 170 },
|
||||
tileSizeKm: { type: "number", minimum: 1, maximum: 50 },
|
||||
radiusKm: { type: "number", minimum: 1, maximum: 100000 },
|
||||
lineDiameterMeters: { type: "number", minimum: 1, maximum: 100 },
|
||||
lineColor: { type: "string", pattern: "^#[0-9A-Fa-f]{6}$" },
|
||||
lineOpacity: { type: "number", minimum: 0, maximum: 100 },
|
||||
dotsEnabled: { type: "boolean" },
|
||||
dotsDiameterMeters: { type: "number", minimum: 1, maximum: 1000 },
|
||||
dotsColor: { type: "string", pattern: "^#[0-9A-Fa-f]{6}$" },
|
||||
dotsOpacity: { type: "number", minimum: 0, maximum: 100 },
|
||||
crossesEnabled: { type: "boolean" },
|
||||
crossesLengthMeters: { type: "number", minimum: 1, maximum: 5000 },
|
||||
crossesWidthMeters: { type: "number", minimum: 1, maximum: 500 },
|
||||
crossesColor: { type: "string", pattern: "^#[0-9A-Fa-f]{6}$" },
|
||||
crossesOpacity: { type: "number", minimum: 0, maximum: 100 },
|
||||
graticuleStepDegrees: { type: "number", minimum: 0.1, maximum: 180 },
|
||||
graticuleLineWidthPx: { type: "number", minimum: 1, maximum: 3 },
|
||||
graticuleColor: { type: "string", pattern: "^#[0-9A-Fa-f]{6}$" },
|
||||
graticuleOpacity: { type: "number", minimum: 0, maximum: 100 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user