cesium-heatbox 0.1.9-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +398 -0
- package/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/cesium-heatbox.umd.min.js +2 -0
- package/dist/cesium-heatbox.umd.min.js.map +1 -0
- package/package.json +102 -0
- package/types/index.d.ts +81 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cesium-heatbox.umd.min.js","mappings":"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","sources":["webpack://CesiumHeatbox/webpack/universalModuleDefinition","webpack://CesiumHeatbox/external umd {\"commonjs\":\"cesium\",\"commonjs2\":\"cesium\",\"amd\":\"cesium\",\"root\":\"Cesium\"}","webpack://CesiumHeatbox/webpack/bootstrap","webpack://CesiumHeatbox/webpack/runtime/define property getters","webpack://CesiumHeatbox/webpack/runtime/hasOwnProperty shorthand","webpack://CesiumHeatbox/./src/utils/constants.js","webpack://CesiumHeatbox/./src/utils/logger.js","webpack://CesiumHeatbox/./src/utils/validation.js","webpack://CesiumHeatbox/./src/utils/deviceTierDetector.js","webpack://CesiumHeatbox/./src/core/CoordinateTransformer.js","webpack://CesiumHeatbox/./src/core/VoxelGrid.js","webpack://CesiumHeatbox/./src/core/DataProcessor.js","webpack://CesiumHeatbox/./src/core/VoxelRenderer.js","webpack://CesiumHeatbox/./src/index.js","webpack://CesiumHeatbox/./src/Heatbox.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"cesium\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"cesium\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"CesiumHeatbox\"] = factory(require(\"cesium\"));\n\telse\n\t\troot[\"CesiumHeatbox\"] = factory(root[\"Cesium\"]);\n})(this, (__WEBPACK_EXTERNAL_MODULE__50__) => {\nreturn ","module.exports = __WEBPACK_EXTERNAL_MODULE__50__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","/**\n * Constant definitions for CesiumJS Heatbox library.\n * CesiumJS Heatbox ライブラリの定数定義。\n */\n\n/**\n * Default option values.\n * デフォルト設定値。\n */\nexport const DEFAULT_OPTIONS = {\n voxelSize: 20,\n opacity: 0.8,\n emptyOpacity: 0.03,\n showOutline: true,\n showEmptyVoxels: false,\n minColor: [0, 32, 255],\n maxColor: [255, 64, 0],\n maxRenderVoxels: 50000,\n batchMode: 'auto',\n debug: false, // ログ制御(false で本番モード、true で開発モード、またはオブジェクト)\n autoVoxelSize: false, // v0.1.4: 自動ボクセルサイズ決定(既存互換性のためfalse)\n // v0.1.5: 新機能\n colorMap: 'custom', // 'custom', 'viridis', 'inferno'\n diverging: false, // 二極性データ対応\n divergingPivot: 0, // 二極性配色のピボット値\n highlightTopN: null, // トップN強調表示(null: 無効)\n highlightStyle: {\n outlineWidth: 4,\n boostOpacity: 0.2\n },\n // v0.1.6: 枠線重なり対策・柔軟化\n voxelGap: 0, // ボクセル間ギャップ(メートル)\n outlineOpacity: 1.0, // 枠線透明度(0-1)\n outlineWidthResolver: null, // 関数: (params) => number で動的太さ制御\n // 実質的な太さ表現のための代替描画(WebGLの線幅制限回避用)\n outlineEmulation: 'off', // 'off' | 'topn' | 'non-topn' | 'all'(ポリラインで太線エミュレーション:TopNのみ | TopN以外のみ | すべて)\n // v0.1.6.1: インセット枠線(ADR-0004)\n outlineInset: 0, // インセット枠線のオフセット距離(メートル、0で無効)\n outlineInsetMode: 'all', // インセット枠線の適用範囲:'all'(全体) | 'topn'(TopNのみ)\n enableThickFrames: false, // 厚い枠線表示(インセット枠線とメイン枠線の間をフレームで埋める)\n \n // v0.1.7: 適応的枠線制御とエミュレーション専用表示モード(ADR-0005)\n outlineRenderMode: 'standard', // 'standard' | 'inset' | 'emulation-only' 表示モード\n adaptiveOutlines: false, // 適応的枠線制御を有効化(オプトイン)\n outlineWidthPreset: 'uniform', // 'adaptive-density' | 'topn-focus' | 'uniform' プリセット\n \n // v0.1.7: 透明度resolver\n boxOpacityResolver: null, // 関数: (ctx) => number(0-1) でボックス透明度制御\n outlineOpacityResolver: null, // 関数: (ctx) => number(0-1) で枠線透明度制御\n \n // v0.1.7: 適応的制御パラメータ\n adaptiveParams: {\n neighborhoodRadius: 50, // 近傍密度計算の半径(メートル)\n densityThreshold: 5, // 密度しきい値(エンティティ数/ボクセル)\n cameraDistanceFactor: 1.0, // カメラ距離補正係数\n overlapRiskFactor: 0.3 // 重なりリスク補正係数\n },\n \n // v0.1.9: 適応的レンダリング制限とスマート視覚化支援(ADR-0006 Phase 1)\n renderLimitStrategy: 'density', // 'density' | 'coverage' | 'hybrid' 選択戦略\n minCoverageRatio: 0.2, // hybrid戦略での層化抽出最小比率(0-1)\n coverageBinsXY: 'auto', // 層化抽出用格子分割数('auto' | number)\n \n // 自動ボクセルサイズ決定の強化\n autoVoxelSizeMode: 'basic', // 'basic' | 'occupancy' 自動サイズ計算方式\n autoVoxelTargetFill: 0.6, // 目標占有率(0-1, occupancyモード用)\n \n // Auto Render Budget\n renderBudgetMode: 'manual', // 'manual' | 'auto' 描画上限制御\n \n // 自動視点調整\n autoView: false, // 自動視点調整有効化\n fitViewOptions: {\n paddingPercent: 0.1, // データ範囲の10%パディング\n pitch: -30, // ピッチ角度(度)\n heading: 0, // ヘディング角度(度)\n altitudeStrategy: 'auto' // 'auto' | 'manual' 高度計算戦略\n }\n};\n\n/**\n * Performance limits.\n * パフォーマンス制限値。\n */\nexport const PERFORMANCE_LIMITS = {\n maxEntities: 5000,\n maxVoxels: 50000,\n maxEmptyVoxelsRendered: 10000,\n minVoxelSize: 5,\n maxVoxelSize: 1000,\n warningThreshold: 30000\n};\n\n/**\n * Coordinate-related constants.\n * 座標変換定数。\n */\nexport const COORDINATE_CONSTANTS = {\n EARTH_RADIUS: 6378137,\n DEGREES_TO_METERS_LAT: 111000,\n DEGREES_TO_RADIANS: Math.PI / 180\n};\n\n/**\n * Error message strings.\n * エラーメッセージ。\n */\nexport const ERROR_MESSAGES = {\n NO_ENTITIES: '対象エンティティがありません',\n NO_VIEWER: 'CesiumJS Viewerが初期化されていません',\n INVALID_VIEWER: 'CesiumJS Viewerが無効です',\n VOXEL_LIMIT_EXCEEDED: 'ボクセル数が上限を超えています',\n MEMORY_WARNING: '推定メモリ使用量が警告値を超えています',\n WEBGL_NOT_SUPPORTED: 'WebGLがサポートされていません',\n INVALID_VOXEL_SIZE: 'ボクセルサイズが無効です'\n};\n\n/**\n * Default statistics values.\n * 統計情報のデフォルト値。\n */\nexport const DEFAULT_STATISTICS = {\n totalVoxels: 0,\n renderedVoxels: 0,\n nonEmptyVoxels: 0,\n emptyVoxels: 0,\n totalEntities: 0,\n minCount: 0,\n maxCount: 0,\n averageCount: 0\n};\n\n/**\n * Color-related constants.\n * 色分け関連定数。\n */\nexport const COLOR_CONSTANTS = {\n MIN_HUE: 240, // 青\n MAX_HUE: 0, // 赤\n SATURATION: 0.8,\n BRIGHTNESS: 0.7,\n SATURATION_RANGE: 0.2,\n BRIGHTNESS_RANGE: 0.3\n};\n","/**\n * Logging utility.\n * NODE_ENV and debug flags control the log level.\n * ログ出力制御ユーティリティ。NODE_ENV や debug フラグによってログレベルを制御します。\n */\n\n/**\n * Log level constants.\n * ログレベル定数。\n */\nconst LOG_LEVELS = {\n ERROR: 0,\n WARN: 1,\n INFO: 2,\n DEBUG: 3\n};\n\n/**\n * Determine current log level.\n * 現在のログレベルを決定します。\n * NODE_ENV=production では ERROR と WARN のみ、DEBUG=true または NODE_ENV=development では全レベル出力。\n */\nfunction getLogLevel() {\n // 明示的にDEBUG=trueが設定されている場合\n if (typeof process !== 'undefined' && process.env && process.env.DEBUG === 'true') {\n return LOG_LEVELS.DEBUG;\n }\n \n // NODE_ENVをチェック\n if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'production') {\n return LOG_LEVELS.WARN;\n }\n \n // デフォルトは開発モード(全ログ出力)\n return LOG_LEVELS.DEBUG;\n}\n\nlet currentLogLevel = getLogLevel();\n\n/**\n * Common logging utility.\n * ログ出力の共通ユーティリティ。\n */\nexport const Logger = {\n /**\n * Error log (always output).\n * エラーログ(常に出力)。\n * @param {...any} args - Log arguments / ログ引数\n */\n error(...args) {\n if (currentLogLevel >= LOG_LEVELS.ERROR) {\n console.error('[Heatbox ERROR]', ...args); // eslint-disable-line no-console\n }\n },\n\n /**\n * Warning log.\n * 警告ログ。\n * @param {...any} args - Log arguments / ログ引数\n */\n warn(...args) {\n if (currentLogLevel >= LOG_LEVELS.WARN) {\n console.warn('[Heatbox WARN]', ...args); // eslint-disable-line no-console\n }\n },\n\n /**\n * Info log.\n * 情報ログ。\n * @param {...any} args - Log arguments / ログ引数\n */\n info(...args) {\n if (currentLogLevel >= LOG_LEVELS.INFO) {\n console.log('[Heatbox INFO]', ...args); // eslint-disable-line no-console\n }\n },\n\n /**\n * Debug log.\n * デバッグログ。\n * @param {...any} args - Log arguments / ログ引数\n */\n debug(...args) {\n if (currentLogLevel >= LOG_LEVELS.DEBUG) {\n console.log('[Heatbox DEBUG]', ...args); // eslint-disable-line no-console\n }\n },\n\n /**\n * Control log level by options.\n * オプション設定によるログレベル制御。\n * v0.1.5: debug オプションがオブジェクトの場合に対応。\n * @param {Object} options - Options / オプション\n */\n setLogLevel(options) {\n if (options && options.debug !== undefined) {\n if (typeof options.debug === 'boolean') {\n // debug: true → 詳細ログ、debug: false → 重要ログのみ\n currentLogLevel = options.debug ? LOG_LEVELS.DEBUG : LOG_LEVELS.WARN;\n } else if (typeof options.debug === 'object' && options.debug !== null) {\n // オブジェクトの場合はログレベルをDEBUGに設定(境界表示制御は別途処理)\n currentLogLevel = LOG_LEVELS.DEBUG;\n }\n }\n return currentLogLevel;\n }\n};\n\n/**\n * Wrapper functions for backward compatibility.\n * 既存の console.log 置き換え用のラッパー関数群。\n */\nexport const log = Logger.debug;\nexport const warn = Logger.warn;\nexport const error = Logger.error;\nexport const info = Logger.info;\n","/**\n * Validation utility functions.\n * バリデーション関連のユーティリティ関数。\n */\n\nimport * as Cesium from 'cesium';\nimport { PERFORMANCE_LIMITS, ERROR_MESSAGES } from './constants.js';\nimport { Logger } from './logger.js';\n\n/**\n * Check whether a CesiumJS Viewer is valid.\n * CesiumJS Viewerが有効かチェックします。\n * @param {Object} viewer - CesiumJS Viewer\n * @returns {boolean} true if valid / 有効な場合は true\n */\nexport function isValidViewer(viewer) {\n if (!viewer) {\n return false;\n }\n \n // 必要なプロパティが存在するかチェック\n if (!viewer.scene || !viewer.entities || !viewer.scene.canvas) {\n return false;\n }\n \n // WebGL対応チェック(WebGL2 も許容)\n const canvas = viewer.scene.canvas;\n const gl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n if (!gl) {\n return false;\n }\n \n return true;\n}\n\n/**\n * Check whether the entity array is valid.\n * エンティティ配列が有効かチェックします。\n * @param {Array} entities - Entity array / エンティティ配列\n * @returns {boolean} true if valid / 有効な場合は true\n */\nexport function isValidEntities(entities) {\n if (!Array.isArray(entities)) {\n return false;\n }\n \n if (entities.length === 0) {\n return false;\n }\n \n if (entities.length > PERFORMANCE_LIMITS.maxEntities) {\n Logger.warn(`エンティティ数が推奨値(${PERFORMANCE_LIMITS.maxEntities})を超えています: ${entities.length}`);\n }\n \n return true;\n}\n\n/**\n * Check whether the voxel size is valid.\n * ボクセルサイズが有効かチェックします。\n * @param {number} voxelSize - Voxel size / ボクセルサイズ\n * @returns {boolean} true if valid / 有効な場合は true\n */\nexport function isValidVoxelSize(voxelSize) {\n if (typeof voxelSize !== 'number' || isNaN(voxelSize)) {\n return false;\n }\n \n if (voxelSize < PERFORMANCE_LIMITS.minVoxelSize || voxelSize > PERFORMANCE_LIMITS.maxVoxelSize) {\n return false;\n }\n \n return true;\n}\n\n/**\n * Check whether an entity has a valid position.\n * エンティティが有効な位置情報を持つかチェックします。\n * @param {Object} entity - Cesium Entity\n * @returns {boolean} true if valid / 有効な場合は true\n */\nexport function hasValidPosition(entity) {\n if (!entity || !entity.position) {\n return false;\n }\n \n // Propertyベースの位置情報の場合\n if (typeof entity.position.getValue === 'function') {\n const position = entity.position.getValue(Cesium.JulianDate.now());\n return position && !isNaN(position.x) && !isNaN(position.y) && !isNaN(position.z);\n }\n \n // 直接Cartesian3の場合\n if (entity.position.x !== undefined) {\n return !isNaN(entity.position.x) && !isNaN(entity.position.y) && !isNaN(entity.position.z);\n }\n \n return false;\n}\n\n/**\n * Validate that total voxel count is within limits.\n * 処理するボクセル数が制限内かチェックします。\n * @param {number} totalVoxels - Total voxels / 総ボクセル数\n * @param {number} voxelSize - Voxel size / ボクセルサイズ\n * @returns {Object} Validation result / チェック結果\n */\nexport function validateVoxelCount(totalVoxels, voxelSize) {\n const result = {\n valid: true,\n warning: false,\n error: null,\n recommendedSize: null\n };\n \n if (totalVoxels > PERFORMANCE_LIMITS.maxVoxels) {\n result.valid = false;\n result.error = ERROR_MESSAGES.VOXEL_LIMIT_EXCEEDED;\n result.recommendedSize = Math.ceil(voxelSize * Math.pow(totalVoxels / PERFORMANCE_LIMITS.maxVoxels, 1/3));\n } else if (totalVoxels > PERFORMANCE_LIMITS.warningThreshold) {\n result.warning = true;\n result.error = ERROR_MESSAGES.MEMORY_WARNING;\n }\n \n return result;\n}\n\n/**\n * Validate and normalize options.\n * オプションを検証して正規化します。\n * v0.1.5: batchMode 非推奨化と新機能バリデーションを追加。\n * @param {Object} options - User-specified options / ユーザー指定のオプション\n * @returns {Object} Normalized options / 正規化されたオプション\n */\nexport function validateAndNormalizeOptions(options = {}) {\n const normalized = { ...options };\n \n // v0.1.5: batchMode非推奨化警告(debug時のみ)\n if (normalized.batchMode && normalized.debug) {\n Logger.warn('batchMode option is deprecated and will be removed in v1.0.0. It is currently ignored.');\n }\n \n // ボクセルサイズのバリデーション\n if (normalized.voxelSize !== undefined && !isValidVoxelSize(normalized.voxelSize)) {\n throw new Error(`${ERROR_MESSAGES.INVALID_VOXEL_SIZE}: ${normalized.voxelSize}`);\n }\n \n // 透明度のバリデーション\n if (normalized.opacity !== undefined) {\n normalized.opacity = Math.max(0, Math.min(1, normalized.opacity));\n }\n \n if (normalized.emptyOpacity !== undefined) {\n normalized.emptyOpacity = Math.max(0, Math.min(1, normalized.emptyOpacity));\n }\n \n // 色のバリデーション\n if (normalized.minColor && Array.isArray(normalized.minColor) && normalized.minColor.length === 3) {\n normalized.minColor = normalized.minColor.map(c => Math.max(0, Math.min(255, Math.floor(c))));\n }\n \n if (normalized.maxColor && Array.isArray(normalized.maxColor) && normalized.maxColor.length === 3) {\n normalized.maxColor = normalized.maxColor.map(c => Math.max(0, Math.min(255, Math.floor(c))));\n }\n \n // v0.1.5: 新機能のバリデーション\n if (normalized.colorMap !== undefined) {\n const validColorMaps = ['custom', 'viridis', 'inferno'];\n if (!validColorMaps.includes(normalized.colorMap)) {\n Logger.warn(`Invalid colorMap: ${normalized.colorMap}. Using 'custom'.`);\n normalized.colorMap = 'custom';\n }\n }\n \n if (normalized.highlightTopN !== undefined && normalized.highlightTopN !== null) {\n if (typeof normalized.highlightTopN !== 'number' || normalized.highlightTopN <= 0) {\n Logger.warn(`Invalid highlightTopN: ${normalized.highlightTopN}. Must be a positive number.`);\n normalized.highlightTopN = null;\n }\n }\n \n // v0.1.6: 枠線重なり対策のバリデーション\n if (normalized.voxelGap !== undefined) {\n normalized.voxelGap = Math.max(0, Math.min(100, parseFloat(normalized.voxelGap) || 0));\n }\n \n if (normalized.outlineOpacity !== undefined) {\n normalized.outlineOpacity = Math.max(0, Math.min(1, parseFloat(normalized.outlineOpacity) || 1));\n }\n \n if (normalized.outlineWidthResolver !== undefined && normalized.outlineWidthResolver !== null) {\n if (typeof normalized.outlineWidthResolver !== 'function') {\n Logger.warn('outlineWidthResolver must be a function. Ignoring.');\n normalized.outlineWidthResolver = null;\n }\n }\n\n // v0.1.6+: 太線エミュレーションモード\n if (normalized.outlineEmulation !== undefined) {\n const validModes = ['off', 'topn', 'non-topn', 'all'];\n if (!validModes.includes(normalized.outlineEmulation)) {\n Logger.warn(`Invalid outlineEmulation: ${normalized.outlineEmulation}. Using 'off'.`);\n normalized.outlineEmulation = 'off';\n }\n }\n\n // v0.1.6.1 (ADR-0004): インセット枠線\n if (normalized.outlineInset !== undefined) {\n const v = parseFloat(normalized.outlineInset);\n normalized.outlineInset = isNaN(v) || v < 0 ? 0 : v;\n }\n if (normalized.outlineInsetMode !== undefined) {\n const validModes = ['all', 'topn'];\n if (!validModes.includes(normalized.outlineInsetMode)) {\n Logger.warn(`Invalid outlineInsetMode: ${normalized.outlineInsetMode}. Using 'all'.`);\n normalized.outlineInsetMode = 'all';\n }\n }\n\n // v0.1.6.1: インセット枠線(ADR-0004)\n if (normalized.outlineInset !== undefined) {\n // 0〜100mの範囲にクランプ(安全上限)\n const inset = parseFloat(normalized.outlineInset);\n normalized.outlineInset = Math.max(0, Math.min(100, isNaN(inset) ? 0 : inset));\n }\n \n if (normalized.outlineInsetMode !== undefined) {\n const validInsetModes = ['all', 'topn'];\n if (!validInsetModes.includes(normalized.outlineInsetMode)) {\n Logger.warn(`Invalid outlineInsetMode: ${normalized.outlineInsetMode}. Using 'all'.`);\n normalized.outlineInsetMode = 'all';\n }\n }\n \n // 厚い枠線表示\n if (normalized.enableThickFrames !== undefined) {\n normalized.enableThickFrames = Boolean(normalized.enableThickFrames);\n }\n \n // v0.1.9: 適応的レンダリング制限のバリデーション\n if (normalized.renderLimitStrategy !== undefined) {\n const validStrategies = ['density', 'coverage', 'hybrid'];\n if (!validStrategies.includes(normalized.renderLimitStrategy)) {\n Logger.warn(`Invalid renderLimitStrategy: ${normalized.renderLimitStrategy}. Using 'density'.`);\n normalized.renderLimitStrategy = 'density';\n }\n }\n if (normalized.minCoverageRatio !== undefined) {\n const v = parseFloat(normalized.minCoverageRatio);\n normalized.minCoverageRatio = isNaN(v) ? 0.2 : Math.max(0, Math.min(1, v));\n }\n if (normalized.coverageBinsXY !== undefined) {\n const v = normalized.coverageBinsXY;\n if (v !== 'auto') {\n const n = parseInt(v, 10);\n if (!Number.isFinite(n) || n <= 0) {\n Logger.warn(`Invalid coverageBinsXY: ${v}. Using 'auto'.`);\n normalized.coverageBinsXY = 'auto';\n } else {\n normalized.coverageBinsXY = n;\n }\n }\n }\n \n // v0.1.9: 自動ボクセルサイズ決定の強化\n if (normalized.autoVoxelSizeMode !== undefined) {\n const validModes = ['basic', 'occupancy'];\n if (!validModes.includes(normalized.autoVoxelSizeMode)) {\n Logger.warn(`Invalid autoVoxelSizeMode: ${normalized.autoVoxelSizeMode}. Using 'basic'.`);\n normalized.autoVoxelSizeMode = 'basic';\n }\n }\n if (normalized.autoVoxelTargetFill !== undefined) {\n const v = parseFloat(normalized.autoVoxelTargetFill);\n normalized.autoVoxelTargetFill = isNaN(v) ? 0.6 : Math.max(0, Math.min(1, v));\n }\n \n // v0.1.9: Auto Render Budget\n if (normalized.renderBudgetMode !== undefined) {\n const validModes = ['manual', 'auto'];\n if (!validModes.includes(normalized.renderBudgetMode)) {\n Logger.warn(`Invalid renderBudgetMode: ${normalized.renderBudgetMode}. Using 'manual'.`);\n normalized.renderBudgetMode = 'manual';\n }\n }\n \n // v0.1.9: 自動視点調整 fitView オプション\n if (normalized.fitViewOptions !== undefined) {\n const f = normalized.fitViewOptions || {};\n const padding = parseFloat(f.paddingPercent);\n const pitch = parseFloat(f.pitch);\n const heading = parseFloat(f.heading);\n const altitudeStrategy = f.altitudeStrategy;\n normalized.fitViewOptions = {\n paddingPercent: Number.isFinite(padding) ? Math.max(0, Math.min(1, padding)) : 0.1,\n pitch: Number.isFinite(pitch) ? Math.max(-90, Math.min(0, pitch)) : -30,\n heading: Number.isFinite(heading) ? heading : 0,\n altitudeStrategy: altitudeStrategy === 'manual' ? 'manual' : 'auto'\n };\n }\n \n return normalized;\n}\n\n/**\n * Estimate initial voxel size based on data range.\n * データ範囲に基づいて初期ボクセルサイズを推定します。\n * @param {Object} bounds - Bounds info / 境界情報\n * @param {number} entityCount - Number of entities / エンティティ数\n * @param {Object} options - Calculation options / 計算オプション\n * @returns {number} Estimated voxel size in meters / 推定ボクセルサイズ(メートル)\n */\nexport function estimateInitialVoxelSize(bounds, entityCount, options = {}) {\n try {\n const mode = options.autoVoxelSizeMode || 'basic';\n \n if (mode === 'occupancy') {\n return estimateVoxelSizeByOccupancy(bounds, entityCount, options);\n } else {\n return estimateVoxelSizeBasic(bounds, entityCount);\n }\n } catch (error) {\n Logger.warn('Initial voxel size estimation failed:', error);\n return 20; // デフォルトサイズ\n }\n}\n\n/**\n * Basic voxel size estimation (existing algorithm).\n * 基本的なボクセルサイズ推定(既存アルゴリズム)\n * @param {Object} bounds - Bounds info / 境界情報\n * @param {number} entityCount - Number of entities / エンティティ数\n * @returns {number} Estimated voxel size in meters / 推定ボクセルサイズ(メートル)\n */\nfunction estimateVoxelSizeBasic(bounds, entityCount) {\n // 1. データ範囲(X/Y/Z軸の物理的範囲)を計算\n const dataRange = calculateDataRange(bounds);\n \n // 2. エンティティ密度を推定\n const volume = dataRange.x * dataRange.y * Math.max(dataRange.z, 10); // 最小高度差10m\n const density = entityCount / volume; // エンティティ/立方メートル\n \n // 3. 密度に応じて適切なボクセルサイズを推定\n // - 高密度: 細かいサイズ(10-20m)\n // - 中密度: 標準サイズ(20-50m)\n // - 低密度: 粗いサイズ(50-100m)\n let estimatedSize;\n \n if (density > 0.001) {\n // 高密度:細かいサイズ\n estimatedSize = Math.max(10, Math.min(20, 20 / Math.sqrt(density * 1000)));\n } else if (density > 0.0001) {\n // 中密度:標準サイズ\n estimatedSize = Math.max(20, Math.min(50, 50 / Math.sqrt(density * 10000)));\n } else {\n // 低密度:粗いサイズ\n estimatedSize = Math.max(50, Math.min(100, 100 / Math.sqrt(density * 100000)));\n }\n \n // 制限値内に収める\n estimatedSize = Math.max(PERFORMANCE_LIMITS.minVoxelSize, \n Math.min(PERFORMANCE_LIMITS.maxVoxelSize, estimatedSize));\n \n Logger.debug(`Basic voxel size estimated: ${estimatedSize}m (density: ${density}, volume: ${volume})`);\n return Math.round(estimatedSize);\n}\n\n/**\n * Occupancy-based voxel size estimation with iterative approximation.\n * 占有率ベースのボクセルサイズ推定(反復近似)\n * @param {Object} bounds - Bounds info / 境界情報\n * @param {number} entityCount - Number of entities / エンティティ数\n * @param {Object} options - Calculation options / 計算オプション\n * @returns {number} Estimated voxel size in meters / 推定ボクセルサイズ(メートル)\n */\nfunction estimateVoxelSizeByOccupancy(bounds, entityCount, options) {\n const dataRange = calculateDataRange(bounds);\n const maxRenderVoxels = options.maxRenderVoxels || 50000;\n const targetFill = options.autoVoxelTargetFill || 0.6;\n const maxIterations = 10;\n const tolerance = 0.05; // 5%の許容誤差\n \n // 初期推定値(基本アルゴリズムから)\n let currentSize = estimateVoxelSizeBasic(bounds, entityCount);\n \n Logger.debug(`Starting occupancy-based estimation: N=${entityCount}, target=${targetFill}, maxVoxels=${maxRenderVoxels}`);\n \n for (let iteration = 0; iteration < maxIterations; iteration++) {\n // 現在のサイズでの総ボクセル数を計算\n const numVoxelsX = Math.ceil(dataRange.x / currentSize);\n const numVoxelsY = Math.ceil(dataRange.y / currentSize);\n const numVoxelsZ = Math.ceil(dataRange.z / currentSize);\n const totalVoxels = numVoxelsX * numVoxelsY * numVoxelsZ;\n \n // 期待占有セル数の計算: E[occupied] ≈ M × (1 - exp(-N/M))\n const expectedOccupied = totalVoxels * (1 - Math.exp(-entityCount / totalVoxels));\n \n // 現在の占有率\n const currentFill = Math.min(expectedOccupied / maxRenderVoxels, 1.0);\n \n Logger.debug(`Iteration ${iteration}: size=${currentSize.toFixed(1)}m, totalVoxels=${totalVoxels}, expectedOccupied=${expectedOccupied.toFixed(0)}, fill=${currentFill.toFixed(3)}`);\n \n // 収束判定\n const fillError = Math.abs(currentFill - targetFill);\n if (fillError < tolerance) {\n Logger.debug(`Converged at iteration ${iteration}: size=${currentSize.toFixed(1)}m, fill=${currentFill.toFixed(3)}`);\n break;\n }\n \n // サイズ調整(Newton法的なアプローチ)\n if (currentFill > targetFill) {\n // 占有率が高すぎる → サイズを大きくしてボクセル数を減らす\n currentSize *= Math.pow(currentFill / targetFill, 0.3);\n } else {\n // 占有率が低すぎる → サイズを小さくしてボクセル数を増やす\n currentSize *= Math.pow(currentFill / targetFill, 0.3);\n }\n \n // 制限値内に収める\n currentSize = Math.max(PERFORMANCE_LIMITS.minVoxelSize, \n Math.min(PERFORMANCE_LIMITS.maxVoxelSize, currentSize));\n }\n \n const finalSize = Math.round(currentSize);\n Logger.info(`Occupancy-based voxel size: ${finalSize}m (target fill: ${targetFill})`);\n \n return finalSize;\n}\n\n/**\n * 境界からデータ範囲を計算\n * @param {Object} bounds - 境界情報\n * @returns {Object} データ範囲 {x, y, z}(メートル)\n */\nexport function calculateDataRange(bounds) {\n try {\n // 緯度経度をメートルに変換(簡易変換)\n const centerLat = (bounds.minLat + bounds.maxLat) / 2;\n const cosLat = Math.cos(centerLat * Math.PI / 180);\n \n const lonRangeMeters = (bounds.maxLon - bounds.minLon) * 111000 * cosLat;\n const latRangeMeters = (bounds.maxLat - bounds.minLat) * 111000;\n const altRangeMeters = Math.max(bounds.maxAlt - bounds.minAlt, 1); // 最小1m\n \n return {\n x: Math.max(lonRangeMeters, 1),\n y: Math.max(latRangeMeters, 1),\n z: altRangeMeters\n };\n \n } catch (error) {\n Logger.warn('Data range calculation failed:', error);\n // フォールバック値\n return { x: 1000, y: 1000, z: 100 };\n }\n}\n","/**\n * Device tier detection for Auto Render Budget.\n * 端末ティア検出(Auto Render Budget用)\n */\n\nimport { Logger } from './logger.js';\nimport { PERFORMANCE_LIMITS } from './constants.js';\n\n/**\n * Device tier constants\n * 端末ティア定数\n */\nconst DEVICE_TIER_RANGES = {\n low: { min: 8000, max: 12000 },\n mid: { min: 20000, max: 35000 },\n high: { min: 40000, max: 50000 }\n};\n\n/**\n * Detect device tier and return appropriate maxRenderVoxels\n * 端末ティアを検出し、適切なmaxRenderVoxelsを返す\n * @returns {Object} { tier: string, maxRenderVoxels: number, detectionMethod: string }\n */\nexport function detectDeviceTier() {\n try {\n const webglInfo = getWebGLInfo();\n const deviceInfo = getDeviceInfo();\n \n // ティア判定ロジック\n let tier = 'mid'; // デフォルトは中ティア\n let detectionMethod = 'fallback';\n \n // Primary: deviceMemory利用可能時(Chrome系のみ)\n if (deviceInfo.deviceMemory !== null) {\n if (deviceInfo.deviceMemory <= 4) {\n tier = 'low';\n } else if (deviceInfo.deviceMemory <= 8) {\n tier = 'mid';\n } else {\n tier = 'high';\n }\n detectionMethod = 'deviceMemory';\n } \n // Fallback: hardwareConcurrency + 画面解像度\n else if (deviceInfo.hardwareConcurrency !== null) {\n const baseScore = deviceInfo.hardwareConcurrency;\n const resolutionFactor = Math.min(deviceInfo.screenPixels / 2073600, 2.0); // 1920x1080 = 2073600を基準\n const adjustedScore = baseScore * resolutionFactor;\n \n if (adjustedScore <= 4) {\n tier = 'low';\n } else if (adjustedScore <= 8) {\n tier = 'mid';\n } else {\n tier = 'high';\n }\n detectionMethod = 'hardwareConcurrency+resolution';\n }\n \n // WebGL制限による追加調整\n if (webglInfo.maxTextureSize < 4096 || !webglInfo.webgl2) {\n tier = tier === 'high' ? 'mid' : 'low';\n detectionMethod += '+webglLimits';\n }\n \n // ティアに応じた上限値を計算\n const range = DEVICE_TIER_RANGES[tier];\n const maxRenderVoxels = Math.min(\n Math.floor((range.min + range.max) / 2),\n PERFORMANCE_LIMITS.maxVoxels\n );\n \n Logger.debug(`Device tier detected: ${tier} (${detectionMethod}), maxRenderVoxels: ${maxRenderVoxels}`);\n \n return {\n tier,\n maxRenderVoxels,\n detectionMethod,\n deviceInfo,\n webglInfo\n };\n \n } catch (error) {\n Logger.warn('Device tier detection failed, using default mid tier:', error);\n return {\n tier: 'mid',\n maxRenderVoxels: Math.min(25000, PERFORMANCE_LIMITS.maxVoxels),\n detectionMethod: 'error-fallback',\n deviceInfo: null,\n webglInfo: null\n };\n }\n}\n\n/**\n * Get WebGL capability information\n * WebGL能力情報を取得\n * @returns {Object} WebGL情報オブジェクト\n */\nfunction getWebGLInfo() {\n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');\n \n if (!gl) {\n return {\n webgl2: false,\n maxTextureSize: 0,\n maxRenderbufferSize: 0\n };\n }\n \n const info = {\n webgl2: !!canvas.getContext('webgl2'),\n maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),\n maxRenderbufferSize: gl.getParameter(gl.MAX_RENDERBUFFER_SIZE)\n };\n \n // クリーンアップ\n canvas.remove();\n \n return info;\n } catch (error) {\n Logger.warn('WebGL info detection failed:', error);\n return {\n webgl2: false,\n maxTextureSize: 0,\n maxRenderbufferSize: 0\n };\n }\n}\n\n/**\n * Get device information\n * 端末情報を取得\n * @returns {Object} 端末情報オブジェクト\n */\nfunction getDeviceInfo() {\n try {\n const info = {\n deviceMemory: navigator.deviceMemory || null, // Chrome系のみ\n hardwareConcurrency: navigator.hardwareConcurrency || null,\n devicePixelRatio: window.devicePixelRatio || 1,\n screenPixels: screen.width * screen.height * Math.pow(window.devicePixelRatio || 1, 2),\n userAgent: navigator.userAgent\n };\n \n return info;\n } catch (error) {\n Logger.warn('Device info detection failed:', error);\n return {\n deviceMemory: null,\n hardwareConcurrency: null,\n devicePixelRatio: 1,\n screenPixels: 2073600, // 1920x1080 fallback\n userAgent: ''\n };\n }\n}\n\n/**\n * Apply auto render budget to options\n * Auto Render Budgetをオプションに適用\n * @param {Object} options - 設定オプション\n * @returns {Object} 更新された設定オプション\n */\nexport function applyAutoRenderBudget(options) {\n if (options.renderBudgetMode !== 'auto' && options.maxRenderVoxels !== 'auto') {\n return options; // 手動モードの場合は変更なし\n }\n \n const detection = detectDeviceTier();\n \n const updatedOptions = {\n ...options,\n maxRenderVoxels: detection.maxRenderVoxels,\n // 統計情報用\n _autoRenderBudget: {\n tier: detection.tier,\n detectionMethod: detection.detectionMethod,\n autoMaxRenderVoxels: detection.maxRenderVoxels\n }\n };\n \n Logger.info(`Auto Render Budget applied: ${detection.tier} tier, maxRenderVoxels: ${detection.maxRenderVoxels}`);\n \n return updatedOptions;\n}\n","/**\n * Coordinate transformation utilities (simple implementation).\n * 座標変換を担当するクラス(シンプル実装)。\n */\nimport * as Cesium from 'cesium';\nimport { Logger } from '../utils/logger.js';\n\n/**\n * Class providing coordinate transformation utilities.\n * 座標変換機能を提供するクラス。\n */\nexport class CoordinateTransformer {\n /**\n * Calculate 3D bounds from an entity array.\n * エンティティ配列から 3D 境界を計算します。\n * @param {Array} entities - Entity array / エンティティ配列\n * @returns {Object} Bounds info / 境界情報\n */\n static calculateBounds(entities) {\n if (!Array.isArray(entities) || entities.length === 0) {\n throw new Error('エンティティが提供されていません');\n }\n \n let minLon = Infinity;\n let maxLon = -Infinity;\n let minLat = Infinity;\n let maxLat = -Infinity;\n let minAlt = Infinity;\n let maxAlt = -Infinity;\n \n let validCount = 0;\n const currentTime = Cesium.JulianDate.now();\n \n entities.forEach((entity, index) => {\n try {\n // エンティティの位置を取得\n let position;\n if (entity.position) {\n if (typeof entity.position.getValue === 'function') {\n position = entity.position.getValue(currentTime);\n } else {\n position = entity.position;\n }\n }\n \n if (!position) {\n return; // 位置情報がない場合はスキップ\n }\n \n // Cartesian3からCartographic(経度、緯度、高度)に変換\n const cartographic = Cesium.Cartographic.fromCartesian(position);\n if (!cartographic) return;\n \n const lon = Cesium.Math.toDegrees(cartographic.longitude);\n const lat = Cesium.Math.toDegrees(cartographic.latitude);\n const alt = cartographic.height;\n \n minLon = Math.min(minLon, lon);\n maxLon = Math.max(maxLon, lon);\n minLat = Math.min(minLat, lat);\n maxLat = Math.max(maxLat, lat);\n minAlt = Math.min(minAlt, alt);\n maxAlt = Math.max(maxAlt, alt);\n \n validCount++;\n } catch (error) {\n Logger.warn(`エンティティ ${index} の処理に失敗:`, error);\n }\n });\n \n if (validCount === 0) {\n throw new Error('有効な位置情報を持つエンティティが見つかりません');\n }\n \n // デバッグ出力\n Logger.debug('座標範囲計算完了:', {\n validCount,\n bounds: {\n minLon, maxLon, \n minLat, maxLat, \n minAlt, maxAlt\n }\n });\n \n return {\n minLon,\n maxLon,\n minLat,\n maxLat,\n minAlt,\n maxAlt,\n centerLon: (minLon + maxLon) / 2,\n centerLat: (minLat + maxLat) / 2,\n centerAlt: (minAlt + maxAlt) / 2\n };\n }\n \n /**\n * Convert voxel indices to geographic coordinates (cell center).\n * ボクセルインデックスを地理座標(中心位置)に変換します。\n * @param {number} x - X-axis voxel index / X軸ボクセルインデックス\n * @param {number} y - Y-axis voxel index / Y軸ボクセルインデックス\n * @param {number} z - Z-axis voxel index / Z軸ボクセルインデックス\n * @param {Object} bounds - Bounds info / 境界情報\n * @param {Object} grid - Grid info / グリッド情報\n * @returns {Object} Geographic coordinate {lon, lat, alt} / 地理座標 {lon, lat, alt}\n */\n static voxelIndexToCoordinate(x, y, z, bounds, grid) {\n const { minLon, maxLon, minLat, maxLat, minAlt, maxAlt } = bounds;\n const { numVoxelsX, numVoxelsY, numVoxelsZ } = grid;\n \n // ボクセルの中心位置を計算(シンプルな線形補間)\n const normalizedLon = (x + 0.5) / numVoxelsX;\n const normalizedLat = (y + 0.5) / numVoxelsY;\n const normalizedAlt = (z + 0.5) / numVoxelsZ;\n \n return {\n lon: minLon + normalizedLon * (maxLon - minLon),\n lat: minLat + normalizedLat * (maxLat - minLat),\n alt: minAlt + normalizedAlt * (maxAlt - minAlt)\n };\n }\n \n /**\n * Convert geographic coordinates to Cesium Cartesian3.\n * 地理座標を Cesium Cartesian3 に変換します。\n * @param {number} lon - Longitude / 経度\n * @param {number} lat - Latitude / 緯度\n * @param {number} alt - Altitude / 高度\n * @returns {Cesium.Cartesian3} Cesium Cartesian3\n */\n static coordinateToCartesian3(lon, lat, alt) {\n return Cesium.Cartesian3.fromDegrees(lon, lat, alt);\n }\n}\n","/**\n * ボクセルグリッドを管理するクラス(シンプル実装)\n */\nimport { Logger } from '../utils/logger.js';\n\n/**\n * Class for managing 3D voxel grids.\n * 3Dボクセルグリッドを管理するクラス。\n */\nexport class VoxelGrid {\n /**\n * Create a grid from bounds and voxel size (simple version).\n * 境界情報とボクセルサイズからグリッドを作成(シンプル版)。\n * @param {Object} bounds - Bounds info / 境界情報\n * @param {number} voxelSizeMeters - Target voxel size in meters (actual cell size is range/divisions per axis) / 目標ボクセルサイズ(メートル)。実セルサイズは各軸で範囲/分割数。\n * @returns {Object} Grid info { numVoxelsX, numVoxelsY, numVoxelsZ, totalVoxels, voxelSizeMeters, cellSizeX, cellSizeY, cellSizeZ, lonRangeMeters, latRangeMeters, altRangeMeters }\n */\n static createGrid(bounds, voxelSizeMeters) {\n // 緯度・経度をメートルに概算変換(シンプルな公式)\n const centerLat = (bounds.minLat + bounds.maxLat) / 2;\n const lonRangeMeters = (bounds.maxLon - bounds.minLon) * 111000 * Math.cos(centerLat * Math.PI / 180);\n const latRangeMeters = (bounds.maxLat - bounds.minLat) * 111000;\n const altRangeMeters = bounds.maxAlt - bounds.minAlt;\n \n // 各軸のボクセル数を計算\n const numVoxelsX = Math.max(1, Math.ceil(lonRangeMeters / voxelSizeMeters));\n const numVoxelsY = Math.max(1, Math.ceil(latRangeMeters / voxelSizeMeters));\n const numVoxelsZ = Math.max(1, Math.ceil(altRangeMeters / voxelSizeMeters));\n\n // 実際の各軸セルサイズ(メートル)\n // ceil により分割数が増える場合があるため、実セルサイズは指定サイズ以下になる。\n const cellSizeX = numVoxelsX > 0 ? (lonRangeMeters / numVoxelsX) : voxelSizeMeters;\n const cellSizeY = numVoxelsY > 0 ? (latRangeMeters / numVoxelsY) : voxelSizeMeters;\n // 高度差が極小の場合に0にならないよう最低1mを確保\n const cellSizeZ = numVoxelsZ > 0 ? Math.max(altRangeMeters / numVoxelsZ, 1) : Math.max(voxelSizeMeters, 1);\n \n const totalVoxels = numVoxelsX * numVoxelsY * numVoxelsZ;\n \n Logger.debug('VoxelGrid created:', {\n numVoxelsX,\n numVoxelsY,\n numVoxelsZ,\n totalVoxels,\n voxelSizeMeters,\n cellSizeX,\n cellSizeY,\n cellSizeZ,\n lonRangeMeters,\n latRangeMeters,\n altRangeMeters\n });\n \n return {\n numVoxelsX,\n numVoxelsY,\n numVoxelsZ,\n totalVoxels,\n voxelSizeMeters,\n cellSizeX,\n cellSizeY,\n cellSizeZ,\n lonRangeMeters,\n latRangeMeters,\n altRangeMeters\n };\n }\n \n /**\n * Generate a key from voxel indices.\n * ボクセルインデックスからキーを生成します。\n * @param {number} x - X index / X軸インデックス\n * @param {number} y - Y index / Y軸インデックス\n * @param {number} z - Z index / Z軸インデックス\n * @returns {string} Voxel key / ボクセルキー\n */\n static getVoxelKey(x, y, z) {\n return `${x},${y},${z}`;\n }\n \n /**\n * Parse voxel key into indices.\n * ボクセルキーからインデックスを解析します。\n * @param {string} key - Voxel key / ボクセルキー\n * @returns {Object} Indices {x, y, z} / インデックス {x, y, z}\n */\n static parseVoxelKey(key) {\n const [x, y, z] = key.split(',').map(Number);\n return { x, y, z };\n }\n \n /**\n * Iterate all voxels and invoke callback per cell.\n * グリッド内の全ボクセルを反復処理します。\n * @param {Object} grid - Grid info / グリッド情報\n * @param {Function} callback - Callback per voxel / 各ボクセルに対するコールバック関数\n */\n static iterateAllVoxels(grid, callback) {\n const { numVoxelsX, numVoxelsY, numVoxelsZ } = grid;\n \n for (let x = 0; x < numVoxelsX; x++) {\n for (let y = 0; y < numVoxelsY; y++) {\n for (let z = 0; z < numVoxelsZ; z++) {\n const key = this.getVoxelKey(x, y, z);\n callback(x, y, z, key);\n }\n }\n }\n }\n}\n","/**\n * データ処理を担当するクラス(シンプル実装)\n */\nimport * as Cesium from 'cesium';\nimport { VoxelGrid } from './VoxelGrid.js';\nimport { Logger } from '../utils/logger.js';\n\n/**\n * Class responsible for processing entity data.\n * エンティティデータの処理を担当するクラス。\n */\nexport class DataProcessor {\n /**\n * Classify entities into voxels (simple implementation).\n * エンティティをボクセルに分類(シンプル実装)。\n * @param {Array} entities - Entity array / エンティティ配列\n * @param {Object} bounds - Bounds info / 境界情報\n * @param {Object} grid - Grid info / グリッド情報\n * @returns {Map} Voxel data Map (key: voxel key, value: info) / ボクセルデータ(キー: ボクセルキー, 値: ボクセル情報)\n */\n static classifyEntitiesIntoVoxels(entities, bounds, grid) {\n const voxelData = new Map();\n let processedCount = 0;\n let skippedCount = 0;\n \n Logger.debug(`Processing ${entities.length} entities for classification`);\n \n const currentTime = Cesium.JulianDate.now();\n \n entities.forEach((entity, index) => {\n try {\n // エンティティの位置を取得(シンプルなアプローチ)\n let position;\n if (entity.position) {\n if (typeof entity.position.getValue === 'function') {\n position = entity.position.getValue(currentTime);\n } else {\n position = entity.position;\n }\n }\n \n if (!position) {\n skippedCount++;\n return; // 位置がない場合はスキップ\n }\n \n // Cartesian3からCartographicに変換\n const cartographic = Cesium.Cartographic.fromCartesian(position);\n if (!cartographic) {\n skippedCount++;\n return;\n }\n \n // 地理座標に変換\n const lon = Cesium.Math.toDegrees(cartographic.longitude);\n const lat = Cesium.Math.toDegrees(cartographic.latitude);\n const alt = cartographic.height;\n \n // 範囲外チェック(少しマージンを持たせる)\n if (lon < bounds.minLon - 0.001 || lon > bounds.maxLon + 0.001 ||\n lat < bounds.minLat - 0.001 || lat > bounds.maxLat + 0.001 ||\n alt < bounds.minAlt - 1 || alt > bounds.maxAlt + 1) {\n skippedCount++;\n return;\n }\n \n // ボクセルインデックスを計算(範囲0の安全対策)\n const lonDen = (bounds.maxLon - bounds.minLon);\n const latDen = (bounds.maxLat - bounds.minLat);\n const altDen = (bounds.maxAlt - bounds.minAlt);\n\n const voxelX = lonDen === 0 ? 0 : Math.floor(\n (lon - bounds.minLon) / lonDen * grid.numVoxelsX\n );\n const voxelY = latDen === 0 ? 0 : Math.floor(\n (lat - bounds.minLat) / latDen * grid.numVoxelsY\n );\n const voxelZ = altDen === 0 ? 0 : Math.floor(\n (alt - bounds.minAlt) / altDen * grid.numVoxelsZ\n );\n \n // インデックスが有効範囲内かチェック\n if (voxelX >= 0 && voxelX < grid.numVoxelsX &&\n voxelY >= 0 && voxelY < grid.numVoxelsY &&\n voxelZ >= 0 && voxelZ < grid.numVoxelsZ) {\n \n const voxelKey = VoxelGrid.getVoxelKey(voxelX, voxelY, voxelZ);\n \n if (!voxelData.has(voxelKey)) {\n voxelData.set(voxelKey, {\n x: voxelX,\n y: voxelY,\n z: voxelZ,\n entities: [],\n count: 0\n });\n }\n \n const voxelInfo = voxelData.get(voxelKey);\n voxelInfo.entities.push(entity);\n voxelInfo.count++;\n \n processedCount++;\n } else {\n skippedCount++;\n }\n } catch (error) {\n Logger.warn(`エンティティ ${index} の処理に失敗:`, error);\n skippedCount++;\n }\n });\n \n Logger.info(`${processedCount}個のエンティティを${voxelData.size}個のボクセルに分類(${skippedCount}個はスキップ)`);\n return voxelData;\n }\n \n /**\n * Calculate statistics from voxel data.\n * ボクセルデータから統計情報を計算します。\n * @param {Map} voxelData - Voxel data / ボクセルデータ\n * @param {Object} grid - Grid info / グリッド情報\n * @returns {Object} Statistics / 統計情報\n */\n static calculateStatistics(voxelData, grid) {\n if (voxelData.size === 0) {\n return {\n totalVoxels: grid.totalVoxels,\n renderedVoxels: 0,\n nonEmptyVoxels: 0,\n emptyVoxels: grid.totalVoxels,\n totalEntities: 0,\n minCount: 0,\n maxCount: 0,\n averageCount: 0,\n // v0.1.4: 自動調整情報の初期化\n autoAdjusted: false,\n originalVoxelSize: null,\n finalVoxelSize: null,\n adjustmentReason: null\n };\n }\n \n const counts = Array.from(voxelData.values()).map(voxel => voxel.count);\n const totalEntities = counts.reduce((sum, count) => sum + count, 0);\n \n const stats = {\n totalVoxels: grid.totalVoxels,\n renderedVoxels: 0, // 実際の描画後にVoxelRendererから設定される\n nonEmptyVoxels: voxelData.size,\n emptyVoxels: grid.totalVoxels - voxelData.size,\n totalEntities: totalEntities,\n minCount: Math.min(...counts),\n maxCount: Math.max(...counts),\n averageCount: totalEntities / voxelData.size,\n // v0.1.4: 自動調整情報の初期化\n autoAdjusted: false,\n originalVoxelSize: null,\n finalVoxelSize: null,\n adjustmentReason: null\n };\n \n Logger.debug('統計情報計算完了:', stats);\n return stats;\n }\n \n /**\n * Get top-N densest voxels.\n * 上位 N 個のボクセルを取得します。\n * @param {Map} voxelData - Voxel data / ボクセルデータ\n * @param {number} topN - Number to get / 取得する上位の数\n * @returns {Array} Top-N voxel info / 上位N個のボクセル情報\n */\n static getTopNVoxels(voxelData, topN) {\n if (voxelData.size === 0 || topN <= 0) {\n return [];\n }\n \n // ボクセルを密度でソート\n const sortedVoxels = Array.from(voxelData.values())\n .sort((a, b) => b.count - a.count);\n \n // 上位N個を返す\n return sortedVoxels.slice(0, Math.min(topN, sortedVoxels.length));\n }\n}\n","/**\n * Class responsible for rendering 3D voxels.\n * 3Dボクセルの描画を担当するクラス。\n * プロトタイプ実装ベース(シンプル・確実動作重視)\n */\nimport * as Cesium from 'cesium';\nimport { Logger } from '../utils/logger.js';\n\n// v0.1.5: カラーマップ定義(256段階のLUTテーブル)\nconst COLOR_MAPS = {\n // Viridisカラーマップ(簡略化した16段階)\n viridis: [\n [68, 1, 84], [71, 44, 122], [59, 81, 139], [44, 113, 142],\n [33, 144, 141], [39, 173, 129], [92, 200, 99], [170, 220, 50],\n [253, 231, 37], [255, 255, 255], [255, 255, 255], [255, 255, 255],\n [255, 255, 255], [255, 255, 255], [255, 255, 255], [255, 255, 255]\n ],\n // Infernoカラーマップ(簡略化した16段階)\n inferno: [\n [0, 0, 4], [31, 12, 72], [85, 15, 109], [136, 34, 106],\n [186, 54, 85], [227, 89, 51], [249, 142, 8], [252, 187, 17],\n [245, 219, 76], [252, 255, 164], [255, 255, 255], [255, 255, 255],\n [255, 255, 255], [255, 255, 255], [255, 255, 255], [255, 255, 255]\n ],\n // 二極性配色(blue-white-red)\n diverging: [\n [0, 0, 255], [32, 64, 255], [64, 128, 255], [96, 160, 255],\n [128, 192, 255], [160, 224, 255], [192, 240, 255], [224, 248, 255],\n [255, 255, 255], [255, 248, 224], [255, 240, 192], [255, 224, 160],\n [255, 192, 128], [255, 160, 96], [255, 128, 64], [255, 64, 32], [255, 0, 0]\n ]\n};\n\n/**\n * Class responsible for 3D voxel rendering.\n * 3Dボクセルの描画を担当するクラス。\n */\nexport class VoxelRenderer {\n /**\n * Constructor\n * @param {Cesium.Viewer} viewer - CesiumJS Viewer / CesiumJS Viewer\n * @param {Object} options - Rendering options / 描画オプション\n */\n constructor(viewer, options = {}) {\n this.viewer = viewer;\n this.options = {\n minColor: [0, 0, 255],\n maxColor: [255, 0, 0],\n opacity: 0.8,\n emptyOpacity: 0.03,\n showOutline: true,\n showEmptyVoxels: false,\n wireframeOnly: false, // 枠線のみ表示\n heightBased: false, // 高さベース表現\n outlineWidth: 2, // 枠線の太さ\n // v0.1.6.1: インセット枠線のデフォルト値\n outlineInset: 0, // インセット枠線オフセット(メートル)\n outlineInsetMode: 'all', // インセット枠線適用範囲\n // v0.1.7: 新オプション\n outlineRenderMode: 'standard',\n adaptiveOutlines: false,\n outlineWidthPreset: 'uniform',\n boxOpacityResolver: null,\n outlineOpacityResolver: null,\n adaptiveParams: {\n neighborhoodRadius: 50,\n densityThreshold: 5,\n cameraDistanceFactor: 1.0,\n overlapRiskFactor: 0.3\n },\n ...options\n };\n this.voxelEntities = [];\n \n Logger.debug('VoxelRenderer initialized with options:', this.options);\n }\n\n /**\n * Compute adaptive outline parameters (v0.1.7).\n * 適応的枠線パラメータを計算 (v0.1.7)。\n * @param {Object} voxelInfo - Voxel info / ボクセル情報\n * @param {boolean} isTopN - Whether it is TopN / TopNボクセルかどうか\n * @param {Map} voxelData - All voxel data / 全ボクセルデータ\n * @param {Object} statistics - Statistics / 統計情報\n * @returns {Object} Adaptive params / 適応的パラメータ\n * @private\n */\n _calculateAdaptiveParams(voxelInfo, isTopN, voxelData, statistics) {\n if (!this.options.adaptiveOutlines) {\n return {\n outlineWidth: null,\n boxOpacity: null,\n outlineOpacity: null,\n shouldUseEmulation: false\n };\n }\n\n const { x, y, z, count } = voxelInfo;\n const normalizedDensity = statistics.maxCount > statistics.minCount ? \n (count - statistics.minCount) / (statistics.maxCount - statistics.minCount) : 0;\n \n // 近働密度を計算\n let neighborhoodDensity = 0;\n let neighborCount = 0;\n const radius = Math.max(1, Math.floor(this.options.adaptiveParams.neighborhoodRadius / 20)); // 簡略化\n \n for (let dx = -radius; dx <= radius; dx++) {\n for (let dy = -radius; dy <= radius; dy++) {\n for (let dz = -radius; dz <= radius; dz++) {\n if (dx === 0 && dy === 0 && dz === 0) continue;\n const neighborKey = `${x + dx},${y + dy},${z + dz}`;\n const neighbor = voxelData.get(neighborKey);\n if (neighbor) {\n neighborhoodDensity += neighbor.count;\n neighborCount++;\n }\n }\n }\n }\n \n const avgNeighborhoodDensity = neighborCount > 0 ? neighborhoodDensity / neighborCount : 0;\n const isDenseArea = avgNeighborhoodDensity > this.options.adaptiveParams.densityThreshold;\n \n // カメラ距離は簡略化(実装では固定値を使用)\n const cameraDistance = 1000; // 固定値、実際の実装ではカメラからの距離を取得\n const cameraFactor = Math.min(1.0, 1000 / cameraDistance) * this.options.adaptiveParams.cameraDistanceFactor;\n \n // 重なりリスクの算出\n const overlapRisk = isDenseArea ? this.options.adaptiveParams.overlapRiskFactor : 0;\n \n // プリセットによる調整\n let adaptiveWidth, adaptiveBoxOpacity, adaptiveOutlineOpacity;\n \n switch (this.options.outlineWidthPreset) {\n case 'adaptive-density':\n adaptiveWidth = isDenseArea ? \n Math.max(0.5, this.options.outlineWidth * (0.5 + normalizedDensity * 0.5)) :\n this.options.outlineWidth;\n adaptiveBoxOpacity = isDenseArea ? this.options.opacity * 0.8 : this.options.opacity;\n adaptiveOutlineOpacity = isDenseArea ? 0.6 : 1.0;\n break;\n \n case 'topn-focus':\n adaptiveWidth = isTopN ? \n this.options.outlineWidth * (1.5 + normalizedDensity * 0.5) :\n Math.max(0.5, this.options.outlineWidth * 0.7);\n adaptiveBoxOpacity = isTopN ? this.options.opacity : this.options.opacity * 0.6;\n adaptiveOutlineOpacity = isTopN ? 1.0 : 0.4;\n break;\n \n case 'uniform':\n default:\n adaptiveWidth = this.options.outlineWidth;\n adaptiveBoxOpacity = this.options.opacity;\n adaptiveOutlineOpacity = this.options.outlineOpacity || 1.0;\n break;\n }\n \n // カメラ距離と重なりリスクで調整\n adaptiveWidth *= cameraFactor;\n adaptiveOutlineOpacity = Math.max(0.2, adaptiveOutlineOpacity * (1 - overlapRisk));\n \n return {\n outlineWidth: Math.max(0.5, adaptiveWidth),\n boxOpacity: Math.max(0.1, Math.min(1.0, adaptiveBoxOpacity)),\n outlineOpacity: Math.max(0.2, Math.min(1.0, adaptiveOutlineOpacity)),\n shouldUseEmulation: isDenseArea || (adaptiveWidth > 2 && this.options.outlineRenderMode !== 'standard')\n };\n }\n\n /**\n * Render voxel data (simple implementation).\n * ボクセルデータを描画(シンプル実装)。\n * @param {Map} voxelData - Voxel data / ボクセルデータ\n * @param {Object} bounds - Bounds info / 境界情報\n * @param {Object} grid - Grid info / グリッド情報\n * @param {Object} statistics - Statistics / 統計情報\n * @returns {number} Number of rendered voxels / 実際に描画されたボクセル数\n */\n render(voxelData, bounds, grid, statistics) {\n this.clear();\n Logger.debug('VoxelRenderer.render - Starting render with simplified approach', {\n voxelDataSize: voxelData.size,\n bounds,\n grid,\n statistics\n });\n\n // バウンディングボックスのデバッグ表示制御(v0.1.5: debug.showBounds対応)\n const shouldShowBounds = this._shouldShowBounds();\n if (shouldShowBounds) {\n this._renderBoundingBox(bounds);\n }\n\n // 表示するボクセルのリスト\n let displayVoxels = [];\n const topNVoxels = new Set(); // v0.1.5: TopN強調表示用\n\n // 空ボクセルのフィルタリング\n if (this.options.showEmptyVoxels) {\n // 全ボクセルを生成(これは上限値が大きいとメモリ消費とパフォーマンスに影響する)\n const maxVoxels = Math.min(grid.totalVoxels, this.options.maxRenderVoxels || 10000);\n Logger.debug(`Generating grid for up to ${maxVoxels} voxels`);\n \n // 空のボクセルも含めて全ボクセルを追加\n for (let x = 0; x < grid.numVoxelsX; x++) {\n for (let y = 0; y < grid.numVoxelsY; y++) {\n for (let z = 0; z < grid.numVoxelsZ; z++) {\n const voxelKey = `${x},${y},${z}`;\n const voxelInfo = voxelData.get(voxelKey) || { x, y, z, count: 0 };\n \n displayVoxels.push({\n key: voxelKey,\n info: voxelInfo\n });\n \n if (displayVoxels.length >= maxVoxels) {\n Logger.debug(`Reached maximum voxel limit of ${maxVoxels}`);\n break;\n }\n }\n if (displayVoxels.length >= maxVoxels) break;\n }\n if (displayVoxels.length >= maxVoxels) break;\n }\n } else {\n // データがあるボクセルのみ表示\n displayVoxels = Array.from(voxelData.entries()).map(([key, info]) => {\n return { key, info };\n });\n \n // v0.1.9: 適応的レンダリング制限の適用\n if (this.options.maxRenderVoxels && displayVoxels.length > this.options.maxRenderVoxels) {\n const selectionResult = this._selectVoxelsForRendering(displayVoxels, this.options.maxRenderVoxels, bounds, grid);\n displayVoxels = selectionResult.selectedVoxels;\n \n // 統計情報の更新\n this._selectionStats = {\n strategy: selectionResult.strategy,\n clippedNonEmpty: selectionResult.clippedNonEmpty,\n coverageRatio: selectionResult.coverageRatio || 0\n };\n \n Logger.debug(`Applied ${selectionResult.strategy} strategy: ${displayVoxels.length} voxels selected, ${selectionResult.clippedNonEmpty} clipped`);\n }\n }\n\n // v0.1.5: TopN強調表示の前処理\n if (this.options.highlightTopN && this.options.highlightTopN > 0) {\n const sortedForTopN = [...displayVoxels].sort((a, b) => b.info.count - a.info.count);\n const topN = sortedForTopN.slice(0, this.options.highlightTopN);\n topN.forEach(voxel => topNVoxels.add(voxel.key));\n Logger.debug(`TopN highlight enabled: ${topNVoxels.size} voxels will be highlighted`);\n }\n \n Logger.debug(`Rendering ${displayVoxels.length} voxels`);\n \n // レンダリングカウント\n let renderedCount = 0;\n\n // 実際にボクセルを描画\n displayVoxels.forEach(({ key, info }) => {\n try {\n const { x, y, z } = info;\n \n // ボクセル中心座標を計算(シンプルな方法)\n const centerLon = bounds.minLon + (x + 0.5) * (bounds.maxLon - bounds.minLon) / grid.numVoxelsX;\n const centerLat = bounds.minLat + (y + 0.5) * (bounds.maxLat - bounds.minLat) / grid.numVoxelsY;\n const centerAlt = bounds.minAlt + (z + 0.5) * (bounds.maxAlt - bounds.minAlt) / grid.numVoxelsZ;\n \n const isTopN = topNVoxels.has(key); // v0.1.5: TopNハイライト判定\n \n // v0.1.7: 適応的パラメータの計算\n const adaptiveParams = this._calculateAdaptiveParams(info, isTopN, voxelData, statistics);\n \n // 密度に応じた色を計算\n let color, opacity;\n \n if (info.count === 0) {\n // 空ボクセルの場合\n color = Cesium.Color.LIGHTGRAY;\n opacity = this.options.emptyOpacity;\n } else {\n // データありボクセルの場合\n const normalizedDensity = statistics.maxCount > statistics.minCount ? \n (info.count - statistics.minCount) / (statistics.maxCount - statistics.minCount) : 0;\n \n color = this.interpolateColor(normalizedDensity, info.count);\n \n // v0.1.7: 透明度resolverの適用(優先順位:resolver > 適応的 > 固定値)\n if (this.options.boxOpacityResolver && typeof this.options.boxOpacityResolver === 'function') {\n const resolverCtx = {\n voxel: { x, y, z, count: info.count },\n isTopN,\n normalizedDensity,\n statistics,\n adaptiveParams\n };\n try {\n const resolverOpacity = this.options.boxOpacityResolver(resolverCtx);\n opacity = isNaN(resolverOpacity) ? this.options.opacity : Math.max(0, Math.min(1, resolverOpacity));\n } catch (e) {\n Logger.warn('boxOpacityResolver error, using fallback:', e);\n opacity = adaptiveParams.boxOpacity || this.options.opacity;\n }\n } else {\n opacity = adaptiveParams.boxOpacity || this.options.opacity;\n }\n \n // v0.1.5: TopN強調表示で非TopNボクセルを淡色化(resolver適用後)\n if (this.options.highlightTopN && !isTopN && !this.options.boxOpacityResolver) {\n opacity *= (1 - (this.options.highlightStyle?.boostOpacity || 0.2));\n }\n }\n \n // v0.1.6: ボクセル寸法計算(voxelGap対応)\n // 各軸のセルサイズ(グリッドが持つ実セルサイズを優先、なければvoxelSizeMetersにフォールバック)\n let cellSizeX = grid.cellSizeX || (grid.lonRangeMeters ? (grid.lonRangeMeters / grid.numVoxelsX) : grid.voxelSizeMeters);\n let cellSizeY = grid.cellSizeY || (grid.latRangeMeters ? (grid.latRangeMeters / grid.numVoxelsY) : grid.voxelSizeMeters);\n let baseCellSizeZ = grid.cellSizeZ || (grid.altRangeMeters ? Math.max(grid.altRangeMeters / Math.max(grid.numVoxelsZ, 1), 1) : Math.max(grid.voxelSizeMeters, 1));\n\n // v0.1.6: voxelGap による寸法縮小(枠線重なり対策)\n if (this.options.voxelGap > 0) {\n cellSizeX = Math.max(cellSizeX - this.options.voxelGap, cellSizeX * 0.1);\n cellSizeY = Math.max(cellSizeY - this.options.voxelGap, cellSizeY * 0.1);\n baseCellSizeZ = Math.max(baseCellSizeZ - this.options.voxelGap, baseCellSizeZ * 0.1);\n }\n\n let boxHeight = baseCellSizeZ;\n if (this.options.heightBased && info.count > 0) {\n const normalizedDensity = statistics.maxCount > statistics.minCount ? \n (info.count - statistics.minCount) / (statistics.maxCount - statistics.minCount) : 0;\n boxHeight = baseCellSizeZ * (0.1 + normalizedDensity * 0.9); // 10%から100%の高さ\n }\n \n // v0.1.7: 動的枠線太さ制御(優先順位:resolver > 適応的 > 固定値)\n let finalOutlineWidth;\n if (this.options.outlineWidthResolver && typeof this.options.outlineWidthResolver === 'function') {\n // outlineWidthResolver による動的制御\n const normalizedDensity = statistics.maxCount > statistics.minCount ? \n (info.count - statistics.minCount) / (statistics.maxCount - statistics.minCount) : 0;\n const resolverParams = {\n voxel: { x, y, z, count: info.count },\n isTopN,\n normalizedDensity,\n statistics,\n adaptiveParams\n };\n try {\n finalOutlineWidth = this.options.outlineWidthResolver(resolverParams);\n if (isNaN(finalOutlineWidth)) {\n finalOutlineWidth = adaptiveParams.outlineWidth || this.options.outlineWidth;\n }\n } catch (e) {\n Logger.warn('outlineWidthResolver error, using fallback:', e);\n finalOutlineWidth = adaptiveParams.outlineWidth || this.options.outlineWidth;\n }\n } else {\n // v0.1.7: 適応的パラメータを優先、なければ従来の静的制御\n if (this.options.adaptiveOutlines && adaptiveParams.outlineWidth !== null) {\n finalOutlineWidth = adaptiveParams.outlineWidth;\n } else {\n finalOutlineWidth = isTopN && this.options.highlightTopN ? \n (this.options.highlightStyle?.outlineWidth || this.options.outlineWidth) : \n this.options.outlineWidth;\n }\n }\n\n // v0.1.7: 枠線透明度制御(resolver > 適応的 > 固定値)\n let finalOutlineOpacity;\n if (this.options.outlineOpacityResolver && typeof this.options.outlineOpacityResolver === 'function') {\n const normalizedDensity = statistics.maxCount > statistics.minCount ? \n (info.count - statistics.minCount) / (statistics.maxCount - statistics.minCount) : 0;\n const resolverCtx = {\n voxel: { x, y, z, count: info.count },\n isTopN,\n normalizedDensity,\n statistics,\n adaptiveParams\n };\n try {\n const resolverOpacity = this.options.outlineOpacityResolver(resolverCtx);\n finalOutlineOpacity = isNaN(resolverOpacity) ? (this.options.outlineOpacity ?? 1.0) : Math.max(0, Math.min(1, resolverOpacity));\n } catch (e) {\n Logger.warn('outlineOpacityResolver error, using fallback:', e);\n finalOutlineOpacity = adaptiveParams.outlineOpacity || (this.options.outlineOpacity ?? 1.0);\n }\n } else {\n finalOutlineOpacity = adaptiveParams.outlineOpacity || (this.options.outlineOpacity ?? 1.0);\n }\n \n const outlineColorWithOpacity = color.withAlpha(finalOutlineOpacity);\n\n // v0.1.7: outlineRenderModeによる表示モード制御\n let shouldShowStandardOutline = true;\n let shouldShowInsetOutline = false;\n let shouldUseEmulationOnly = false;\n \n switch (this.options.outlineRenderMode) {\n case 'standard':\n shouldShowStandardOutline = this.options.showOutline;\n shouldShowInsetOutline = this.options.outlineInset > 0;\n break;\n case 'inset':\n shouldShowStandardOutline = false; // インセットモードでは標準枠線を無効化\n shouldShowInsetOutline = true;\n break;\n case 'emulation-only':\n shouldShowStandardOutline = false;\n shouldShowInsetOutline = false;\n shouldUseEmulationOnly = true;\n break;\n }\n \n // v0.1.7: 適応的エミュレーション判定を組み込み\n let emulateThickForThis = shouldUseEmulationOnly;\n if (!shouldUseEmulationOnly) {\n // 従来のoutlineEmulationオプションを尊重\n if (this.options.outlineEmulation === 'topn') {\n emulateThickForThis = isTopN && (finalOutlineWidth || 1) > 1;\n } else if (this.options.outlineEmulation === 'non-topn') {\n emulateThickForThis = !isTopN && (finalOutlineWidth || 1) > 1;\n } else if (this.options.outlineEmulation === 'all') {\n emulateThickForThis = (finalOutlineWidth || 1) > 1;\n } else if (this.options.adaptiveOutlines && adaptiveParams.shouldUseEmulation) {\n emulateThickForThis = true;\n }\n }\n \n // エンティティの設定\n const entityConfig = {\n position: Cesium.Cartesian3.fromDegrees(centerLon, centerLat, centerAlt),\n box: {\n dimensions: new Cesium.Cartesian3(\n cellSizeX,\n cellSizeY,\n boxHeight\n ),\n outline: shouldShowStandardOutline && !emulateThickForThis,\n outlineColor: outlineColorWithOpacity,\n outlineWidth: Math.max(finalOutlineWidth || 1, 0) // 負値防止\n },\n properties: {\n type: 'voxel',\n key: key,\n count: info.count,\n x: x,\n y: y,\n z: z\n },\n description: this.createVoxelDescription(info, key)\n };\n\n // wireframeOnlyモードの場合は透明、そうでなければ通常の材質\n if (this.options.wireframeOnly) {\n entityConfig.box.material = Cesium.Color.TRANSPARENT;\n entityConfig.box.fill = false;\n } else {\n entityConfig.box.material = color.withAlpha(opacity);\n entityConfig.box.fill = true;\n }\n \n // エンティティを作成\n const entity = this.viewer.entities.add(entityConfig);\n \n this.voxelEntities.push(entity);\n\n // v0.1.7: インセット枠線の実装(outlineRenderModeに応じて制御)\n if (shouldShowInsetOutline && this._shouldApplyInsetOutline(isTopN)) {\n try {\n const insetAmount = this.options.outlineInset > 0 ? this.options.outlineInset : 1; // emulation-onlyでは最低1m\n this._createInsetOutline(\n centerLon, centerLat, centerAlt,\n cellSizeX, cellSizeY, boxHeight,\n outlineColorWithOpacity, Math.max(finalOutlineWidth || 1, 1),\n key, insetAmount\n );\n } catch (e) {\n Logger.warn('Failed to create inset outline:', e);\n }\n }\n \n // 太線エミュレーション(条件に応じてポリラインでエッジを追加)\n // 隣接枠線の被りを避けるため、外縁ではなく“インセット後”の寸法でエッジを描く\n if (emulateThickForThis) {\n try {\n const centerCart = entity.position.getValue(Cesium.JulianDate.now());\n\n const maxInsetX = cellSizeX * 0.2;\n const maxInsetY = cellSizeY * 0.2;\n const maxInsetZ = boxHeight * 0.2;\n const baseInset = (this.options.outlineInset && this.options.outlineInset > 0) ? this.options.outlineInset : 0;\n const autoInsetX = cellSizeX * 0.05;\n const autoInsetY = cellSizeY * 0.05;\n const autoInsetZ = boxHeight * 0.05;\n const effInsetX = Math.min(baseInset > 0 ? baseInset : autoInsetX, maxInsetX);\n const effInsetY = Math.min(baseInset > 0 ? baseInset : autoInsetY, maxInsetY);\n const effInsetZ = Math.min(baseInset > 0 ? baseInset : autoInsetZ, maxInsetZ);\n\n // 外縁とインセットの“中間”に相当する寸法(片側ぶんだけ縮める)\n const midSizeX = Math.max(cellSizeX - effInsetX, cellSizeX * 0.1);\n const midSizeY = Math.max(cellSizeY - effInsetY, cellSizeY * 0.1);\n const midSizeZ = Math.max(boxHeight - effInsetZ, boxHeight * 0.1);\n\n this._addEdgePolylines(\n centerCart,\n midSizeX,\n midSizeY,\n midSizeZ,\n outlineColorWithOpacity,\n Math.max(finalOutlineWidth, 1)\n );\n } catch (e) {\n Logger.warn('Failed to add emulated thick outline polylines:', e);\n }\n }\n renderedCount++;\n } catch (error) {\n Logger.warn('Error rendering voxel:', error);\n }\n });\n\n Logger.info(`Successfully rendered ${renderedCount} voxels`);\n \n // 実際に描画されたボクセル数を返す\n return renderedCount;\n }\n\n /**\n * バウンディングボックスを描画(デバッグ用)\n * @param {Object} bounds - 境界情報\n * @private\n */\n _renderBoundingBox(bounds) {\n if (!bounds) return;\n\n try {\n // 中心点\n const centerLon = (bounds.minLon + bounds.maxLon) / 2;\n const centerLat = (bounds.minLat + bounds.maxLat) / 2;\n const centerAlt = (bounds.minAlt + bounds.maxAlt) / 2;\n \n // サイズ計算(概算)\n const widthMeters = (bounds.maxLon - bounds.minLon) * 111000 * Math.cos(centerLat * Math.PI / 180);\n const depthMeters = (bounds.maxLat - bounds.minLat) * 111000;\n const heightMeters = bounds.maxAlt - bounds.minAlt;\n \n // 境界ボックスの作成\n const boundingBox = this.viewer.entities.add({\n position: Cesium.Cartesian3.fromDegrees(centerLon, centerLat, centerAlt),\n box: {\n dimensions: new Cesium.Cartesian3(widthMeters, depthMeters, heightMeters),\n material: Cesium.Color.YELLOW.withAlpha(0.1),\n outline: true,\n outlineColor: Cesium.Color.YELLOW.withAlpha(0.3),\n outlineWidth: 2\n },\n description: `バウンディングボックス<br>サイズ: ${widthMeters.toFixed(1)} x ${depthMeters.toFixed(1)} x ${heightMeters.toFixed(1)} m`\n });\n \n this.voxelEntities.push(boundingBox);\n \n Logger.debug('Debug bounding box added:', {\n center: { lon: centerLon, lat: centerLat, alt: centerAlt },\n size: { width: widthMeters, depth: depthMeters, height: heightMeters }\n });\n \n } catch (error) {\n Logger.warn('Failed to render bounding box:', error);\n }\n }\n\n /**\n * ボックスのエッジをポリラインで描画(太線エミュレーション)\n * @param {Cesium.Cartesian3} centerCart - ボックス中心\n * @param {number} sx - X寸法(m)\n * @param {number} sy - Y寸法(m)\n * @param {number} sz - Z寸法(m)\n * @param {Cesium.Color} color - 線色\n * @param {number} width - 線幅(px)\n * @private\n */\n _addEdgePolylines(centerCart, sx, sy, sz, color, width) {\n try {\n const halfX = sx / 2, halfY = sy / 2, halfZ = sz / 2;\n const enu = Cesium.Transforms.eastNorthUpToFixedFrame(centerCart);\n const toWorld = (dx, dy, dz) => {\n const local = new Cesium.Cartesian3(dx, dy, dz);\n return Cesium.Matrix4.multiplyByPoint(enu, local, new Cesium.Cartesian3());\n };\n const C = [\n toWorld(-halfX, -halfY, -halfZ),\n toWorld( halfX, -halfY, -halfZ),\n toWorld( halfX, halfY, -halfZ),\n toWorld(-halfX, halfY, -halfZ),\n toWorld(-halfX, -halfY, halfZ),\n toWorld( halfX, -halfY, halfZ),\n toWorld( halfX, halfY, halfZ),\n toWorld(-halfX, halfY, halfZ)\n ];\n const edges = [[0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7]];\n edges.forEach(([i, j]) => {\n const poly = this.viewer.entities.add({\n polyline: {\n positions: [C[i], C[j]],\n width: width,\n material: color,\n arcType: Cesium.ArcType.NONE\n }\n });\n this.voxelEntities.push(poly);\n });\n } catch (error) {\n Logger.warn('Edge polyline creation failed:', error);\n }\n }\n\n /**\n * Interpolate color based on density (v0.1.5: color maps supported).\n * 密度に基づいて色を補間(v0.1.5: カラーマップ対応)。\n * @param {number} normalizedDensity - Normalized density (0-1) / 正規化された密度 (0-1)\n * @param {number} [rawValue] - Raw value for diverging scheme / 生値(二極性配色用)\n * @returns {Cesium.Color} Calculated color / 計算された色\n */\n interpolateColor(normalizedDensity, rawValue = null) {\n // v0.1.5: 二極性配色対応(pivot<=0 の場合は安全にフォールバック)\n if (this.options.diverging && rawValue !== null) {\n const pivot = typeof this.options.divergingPivot === 'number' ? this.options.divergingPivot : 0;\n if (pivot > 0) {\n return this._interpolateDivergingColor(rawValue);\n }\n // pivot が 0 以下の場合は従来の補間にフォールバック\n }\n \n // v0.1.5: カラーマップ対応\n if (this.options.colorMap && this.options.colorMap !== 'custom') {\n return this._interpolateFromColorMap(normalizedDensity, this.options.colorMap);\n }\n \n // 従来のmin/max色補間(後方互換)\n const [minR, minG, minB] = this.options.minColor;\n const [maxR, maxG, maxB] = this.options.maxColor;\n \n const r = Math.round(minR + (maxR - minR) * normalizedDensity);\n const g = Math.round(minG + (maxG - minG) * normalizedDensity);\n const b = Math.round(minB + (maxB - minB) * normalizedDensity);\n \n return Cesium.Color.fromBytes(r, g, b);\n }\n \n /**\n * Interpolate color from a color map.\n * カラーマップから色を補間します。\n * @param {number} normalizedValue - Normalized value (0-1) / 正規化された値 (0-1)\n * @param {string} colorMapName - Color map name / カラーマップ名\n * @returns {Cesium.Color} Calculated color / 計算された色\n * @private\n */\n _interpolateFromColorMap(normalizedValue, colorMapName) {\n const colorMap = COLOR_MAPS[colorMapName];\n if (!colorMap) {\n Logger.warn(`Unknown color map: ${colorMapName}. Falling back to custom.`);\n return this.interpolateColor(normalizedValue);\n }\n \n // マップインデックスを計算\n const scaledValue = normalizedValue * (colorMap.length - 1);\n const lowerIndex = Math.floor(scaledValue);\n const upperIndex = Math.min(lowerIndex + 1, colorMap.length - 1);\n const fraction = scaledValue - lowerIndex;\n \n // 線形補間\n const [r1, g1, b1] = colorMap[lowerIndex];\n const [r2, g2, b2] = colorMap[upperIndex];\n \n const r = Math.round(r1 + (r2 - r1) * fraction);\n const g = Math.round(g1 + (g2 - g1) * fraction);\n const b = Math.round(b1 + (b2 - b1) * fraction);\n \n return Cesium.Color.fromBytes(r, g, b);\n }\n \n /**\n * Interpolate diverging (blue-white-red) color.\n * 二極性配色(blue-white-red)で色を補間します。\n * @param {number} rawValue - Raw value / 生値\n * @returns {Cesium.Color} Calculated color / 計算された色\n * @private\n */\n _interpolateDivergingColor(rawValue) {\n const pivot = this.options.divergingPivot || 0;\n \n // ピボットからの偏差を正規化\n let normalizedValue;\n if (rawValue <= pivot) {\n // 青い側 (0 to 0.5)\n normalizedValue = 0.5 * (rawValue / pivot);\n normalizedValue = Math.max(0, Math.min(0.5, normalizedValue));\n } else {\n // 赤い側 (0.5 to 1)\n normalizedValue = 0.5 + 0.5 * ((rawValue - pivot) / pivot);\n normalizedValue = Math.max(0.5, Math.min(1, normalizedValue));\n }\n \n return this._interpolateFromColorMap(normalizedValue, 'diverging');\n }\n\n /**\n * Create description HTML for a voxel.\n * ボクセルの説明文を生成します。\n * @param {Object} voxelInfo - Voxel info / ボクセル情報\n * @param {string} voxelKey - Voxel key / ボクセルキー\n * @returns {string} HTML description / HTML形式の説明文\n */\n createVoxelDescription(voxelInfo, voxelKey) {\n return `\n <div style=\"padding: 10px; font-family: Arial, sans-serif;\">\n <h3 style=\"margin-top: 0;\">ボクセル [${voxelInfo.x}, ${voxelInfo.y}, ${voxelInfo.z}]</h3>\n <table style=\"width: 100%;\">\n <tr><td><b>エンティティ数:</b></td><td>${voxelInfo.count}</td></tr>\n <tr><td><b>ID:</b></td><td>${voxelKey}</td></tr>\n </table>\n </div>\n `;\n }\n\n /**\n * 描画されたエンティティを全てクリア\n */\n clear() {\n Logger.debug('VoxelRenderer.clear - Removing', this.voxelEntities.length, 'entities');\n \n this.voxelEntities.forEach(entity => {\n try {\n // isDestroyedのチェックを安全に行う\n const isDestroyed = typeof entity.isDestroyed === 'function' ? entity.isDestroyed() : false;\n \n if (entity && !isDestroyed) {\n this.viewer.entities.remove(entity);\n }\n } catch (error) {\n Logger.warn('Entity removal error:', error);\n }\n });\n \n this.voxelEntities = [];\n }\n\n /**\n * デバッグ境界ボックス表示の判定(v0.1.5: debug.showBounds対応)\n * @returns {boolean} 境界ボックスを表示する場合はtrue\n * @private\n */\n _shouldShowBounds() {\n if (!this.options.debug) {\n return false;\n }\n \n if (typeof this.options.debug === 'boolean') {\n // 従来の動作:debugがtrueの場合はバウンディングボックス表示\n return this.options.debug;\n }\n \n if (typeof this.options.debug === 'object' && this.options.debug !== null) {\n // 新しい動作:debug.showBoundsで明示的に制御\n return this.options.debug.showBounds === true;\n }\n \n return false;\n }\n\n /**\n * インセット枠線を適用すべきかどうかを判定(ADR-0004)\n * @param {boolean} isTopN - TopNボクセルかどうか\n * @returns {boolean} インセット枠線を適用する場合はtrue\n * @private\n */\n _shouldApplyInsetOutline(isTopN) {\n const mode = this.options.outlineInsetMode || 'all';\n switch (mode) {\n case 'topn':\n return isTopN;\n case 'all':\n default:\n return true;\n }\n }\n\n /**\n * インセット枠線用のセカンダリBoxエンティティを作成(ADR-0004)\n * @param {number} centerLon - 中心経度\n * @param {number} centerLat - 中心緯度 \n * @param {number} centerAlt - 中心高度\n * @param {number} baseSizeX - 基本サイズX\n * @param {number} baseSizeY - 基本サイズY\n * @param {number} baseSizeZ - 基本サイズZ\n * @param {Cesium.Color} outlineColor - 枠線色\n * @param {number} outlineWidth - 枠線太さ\n * @param {string} voxelKey - ボクセルキー\n * @param {number} [insetAmount] - v0.1.7: インセット量のオーバーライド\n * @private\n */\n _createInsetOutline(centerLon, centerLat, centerAlt, baseSizeX, baseSizeY, baseSizeZ, outlineColor, outlineWidth, voxelKey, insetAmount = null) {\n // インセット距離の適用(ADR-0004の境界条件:両側合計で各軸寸法の最大40%まで=片側20%)\n // 片側20%までに制限することで、最終寸法は元の60%以上を保証する\n const maxInsetX = baseSizeX * 0.2;\n const maxInsetY = baseSizeY * 0.2;\n const maxInsetZ = baseSizeZ * 0.2;\n \n const baseInset = insetAmount !== null ? insetAmount : this.options.outlineInset;\n const effectiveInsetX = Math.min(baseInset, maxInsetX);\n const effectiveInsetY = Math.min(baseInset, maxInsetY); \n const effectiveInsetZ = Math.min(baseInset, maxInsetZ);\n \n // インセット後の寸法計算(各軸から2倍のインセットを引く)\n const insetSizeX = Math.max(baseSizeX - (effectiveInsetX * 2), baseSizeX * 0.1);\n const insetSizeY = Math.max(baseSizeY - (effectiveInsetY * 2), baseSizeY * 0.1);\n const insetSizeZ = Math.max(baseSizeZ - (effectiveInsetZ * 2), baseSizeZ * 0.1);\n \n // セカンダリBoxエンティティの設定(枠線のみ、塗りなし)\n const insetEntity = this.viewer.entities.add({\n position: Cesium.Cartesian3.fromDegrees(centerLon, centerLat, centerAlt),\n box: {\n dimensions: new Cesium.Cartesian3(insetSizeX, insetSizeY, insetSizeZ),\n fill: false,\n outline: true,\n outlineColor: outlineColor,\n outlineWidth: Math.max(outlineWidth || 1, 0)\n },\n properties: {\n type: 'voxel-inset-outline',\n parentKey: voxelKey,\n insetSize: { x: insetSizeX, y: insetSizeY, z: insetSizeZ }\n }\n });\n \n this.voxelEntities.push(insetEntity);\n \n // 枠線の厚み部分を視覚化(WebGL 1px制限の回避)\n if (this.options.enableThickFrames && (effectiveInsetX > 0.1 || effectiveInsetY > 0.1 || effectiveInsetZ > 0.1)) {\n this._createThickOutlineFrames(\n centerLon, centerLat, centerAlt,\n baseSizeX, baseSizeY, baseSizeZ,\n insetSizeX, insetSizeY, insetSizeZ,\n outlineColor, voxelKey\n );\n }\n \n Logger.debug(`Inset outline created for voxel ${voxelKey}:`, {\n originalSize: { x: baseSizeX, y: baseSizeY, z: baseSizeZ },\n insetSize: { x: insetSizeX, y: insetSizeY, z: insetSizeZ },\n effectiveInset: { x: effectiveInsetX, y: effectiveInsetY, z: effectiveInsetZ }\n });\n }\n\n /**\n * 枠線の厚み部分を視覚化するフレーム構造を作成\n * メインボックスとインセットボックスの間を12個のボックスで埋める\n * @param {number} centerLon - 中心経度\n * @param {number} centerLat - 中心緯度\n * @param {number} centerAlt - 中心高度\n * @param {number} outerX - 外側サイズX\n * @param {number} outerY - 外側サイズY\n * @param {number} outerZ - 外側サイズZ\n * @param {number} innerX - 内側サイズX\n * @param {number} innerY - 内側サイズY\n * @param {number} innerZ - 内側サイズZ\n * @param {Cesium.Color} frameColor - フレーム色\n * @param {string} voxelKey - ボクセルキー\n * @private\n */\n _createThickOutlineFrames(centerLon, centerLat, centerAlt, outerX, outerY, outerZ, innerX, innerY, innerZ, frameColor, voxelKey) {\n // フレーム厚み計算(外側と内側の差を2で割ったもの)\n const frameThickX = (outerX - innerX) / 2;\n const frameThickY = (outerY - innerY) / 2;\n const frameThickZ = (outerZ - innerZ) / 2;\n \n // 境界計算:各軸での内側・外側の境界\n const outerBoundX = outerX / 2; // 外側境界(中心からの距離)\n const outerBoundY = outerY / 2;\n const outerBoundZ = outerZ / 2;\n const innerBoundX = innerX / 2; // 内側境界(中心からの距離)\n const innerBoundY = innerY / 2;\n const innerBoundZ = innerZ / 2;\n \n Logger.debug(`Frame bounds for ${voxelKey}:`, {\n frameThick: { x: frameThickX, y: frameThickY, z: frameThickZ },\n outerBound: { x: outerBoundX, y: outerBoundY, z: outerBoundZ },\n innerBound: { x: innerBoundX, y: innerBoundY, z: innerBoundZ }\n });\n \n // 12個のフレームボックスを配置(外側と内側の境界間に正確にフィット)\n const frames = [\n // 上面の枠線(4つ)- Z軸上側\n { \n pos: [0, (outerBoundY + innerBoundY) / 2, outerBoundZ - frameThickZ / 2], \n size: [innerX, frameThickY, frameThickZ], \n name: 'top-back' \n },\n { \n pos: [0, -(outerBoundY + innerBoundY) / 2, outerBoundZ - frameThickZ / 2], \n size: [innerX, frameThickY, frameThickZ], \n name: 'top-front' \n },\n { \n pos: [(outerBoundX + innerBoundX) / 2, 0, outerBoundZ - frameThickZ / 2], \n size: [frameThickX, outerY, frameThickZ], \n name: 'top-right' \n },\n { \n pos: [-(outerBoundX + innerBoundX) / 2, 0, outerBoundZ - frameThickZ / 2], \n size: [frameThickX, outerY, frameThickZ], \n name: 'top-left' \n },\n \n // 下面の枠線(4つ)- Z軸下側\n { \n pos: [0, (outerBoundY + innerBoundY) / 2, -outerBoundZ + frameThickZ / 2], \n size: [innerX, frameThickY, frameThickZ], \n name: 'bottom-back' \n },\n { \n pos: [0, -(outerBoundY + innerBoundY) / 2, -outerBoundZ + frameThickZ / 2], \n size: [innerX, frameThickY, frameThickZ], \n name: 'bottom-front' \n },\n { \n pos: [(outerBoundX + innerBoundX) / 2, 0, -outerBoundZ + frameThickZ / 2], \n size: [frameThickX, outerY, frameThickZ], \n name: 'bottom-right' \n },\n { \n pos: [-(outerBoundX + innerBoundX) / 2, 0, -outerBoundZ + frameThickZ / 2], \n size: [frameThickX, outerY, frameThickZ], \n name: 'bottom-left' \n },\n \n // 縦の枠線(4つ)- 角の柱\n { \n pos: [(outerBoundX + innerBoundX) / 2, (outerBoundY + innerBoundY) / 2, 0], \n size: [frameThickX, frameThickY, innerZ], \n name: 'vertical-back-right' \n },\n { \n pos: [(outerBoundX + innerBoundX) / 2, -(outerBoundY + innerBoundY) / 2, 0], \n size: [frameThickX, frameThickY, innerZ], \n name: 'vertical-front-right' \n },\n { \n pos: [-(outerBoundX + innerBoundX) / 2, (outerBoundY + innerBoundY) / 2, 0], \n size: [frameThickX, frameThickY, innerZ], \n name: 'vertical-back-left' \n },\n { \n pos: [-(outerBoundX + innerBoundX) / 2, -(outerBoundY + innerBoundY) / 2, 0], \n size: [frameThickX, frameThickY, innerZ], \n name: 'vertical-front-left' \n }\n ];\n \n // 各フレームボックスを作成\n frames.forEach(frame => {\n if (frame.size[0] > 0.1 && frame.size[1] > 0.1 && frame.size[2] > 0.1) {\n try {\n // より正確な座標計算:経度・緯度・高度で直接オフセット\n const DEG_PER_METER_LON = 1 / (111000 * Math.cos(centerLat * Math.PI / 180));\n const DEG_PER_METER_LAT = 1 / 111000;\n \n const frameLon = centerLon + frame.pos[0] * DEG_PER_METER_LON;\n const frameLat = centerLat + frame.pos[1] * DEG_PER_METER_LAT;\n const frameAlt = centerAlt + frame.pos[2];\n \n const frameEntity = this.viewer.entities.add({\n position: Cesium.Cartesian3.fromDegrees(frameLon, frameLat, frameAlt),\n box: {\n dimensions: new Cesium.Cartesian3(frame.size[0], frame.size[1], frame.size[2]),\n material: frameColor.withAlpha(0.8), // 少し透明度を下げて重なりを考慮\n outline: false, // 内部フレームには枠線なし\n fill: true\n },\n properties: {\n type: 'voxel-outline-frame',\n parentKey: voxelKey,\n frameName: frame.name\n }\n });\n \n this.voxelEntities.push(frameEntity);\n } catch (e) {\n Logger.warn(`Failed to create outline frame ${frame.name}:`, e);\n }\n }\n });\n \n Logger.debug(`Thick outline frames created for voxel ${voxelKey}: ${frames.length} frames`);\n }\n\n /**\n * Toggle visibility.\n * 表示/非表示を切り替えます。\n * @param {boolean} show - true to show / 表示する場合は true\n */\n setVisible(show) {\n Logger.debug('VoxelRenderer.setVisible:', show);\n \n this.voxelEntities.forEach(entity => {\n try {\n // isDestroyedのチェックを安全に行う\n const isDestroyed = typeof entity.isDestroyed === 'function' ? entity.isDestroyed() : false;\n \n if (entity && !isDestroyed) {\n entity.show = show;\n }\n } catch (error) {\n Logger.warn('Entity visibility error:', error);\n }\n });\n }\n\n /**\n * Select voxels for rendering based on the specified strategy.\n * 指定された戦略に基づいてレンダリング用ボクセルを選択します。\n * @param {Array} allVoxels - All available voxels / 利用可能な全ボクセル\n * @param {number} maxCount - Maximum number of voxels to select / 選択する最大ボクセル数\n * @param {Object} bounds - Data bounds / データ境界\n * @returns {Object} Selection result / 選択結果\n * @private\n */\n _selectVoxelsForRendering(allVoxels, maxCount, bounds, grid) {\n const strategy = this.options.renderLimitStrategy || 'density';\n \n // TopN強調ボクセルは必ず選択対象に含む\n const topNVoxels = new Set();\n if (this.options.highlightTopN && this.options.highlightTopN > 0) {\n const sortedForTopN = [...allVoxels].sort((a, b) => b.info.count - a.info.count);\n const topN = sortedForTopN.slice(0, this.options.highlightTopN);\n topN.forEach(voxel => topNVoxels.add(voxel.key));\n }\n \n let selectedVoxels;\n let clippedCount;\n let coverageRatio = null;\n \n switch (strategy) {\n case 'coverage': {\n const coverageResult = this._selectByCoverage(allVoxels, maxCount, grid, topNVoxels);\n selectedVoxels = coverageResult.selected;\n clippedCount = allVoxels.length - selectedVoxels.length;\n break;\n }\n \n case 'hybrid': {\n const hybridResult = this._selectByHybrid(allVoxels, maxCount, grid, topNVoxels);\n selectedVoxels = hybridResult.selected;\n clippedCount = allVoxels.length - selectedVoxels.length;\n coverageRatio = hybridResult.coverageRatio;\n break;\n }\n \n case 'density':\n default: {\n const densityResult = this._selectByDensity(allVoxels, maxCount, topNVoxels);\n selectedVoxels = densityResult.selected;\n clippedCount = allVoxels.length - selectedVoxels.length;\n break;\n }\n }\n \n return {\n selectedVoxels,\n strategy,\n clippedNonEmpty: clippedCount,\n coverageRatio\n };\n }\n\n /**\n * Select voxels by density (existing algorithm).\n * 密度による選択(既存アルゴリズム)\n * @param {Array} allVoxels - All voxels / 全ボクセル\n * @param {number} maxCount - Maximum count / 最大数\n * @param {Set} forceInclude - Voxels to force include / 強制包含ボクセル\n * @returns {Object} Selection result / 選択結果\n * @private\n */\n _selectByDensity(allVoxels, maxCount, forceInclude = new Set()) {\n // 密度でソートして上位を選択\n const sorted = [...allVoxels].sort((a, b) => b.info.count - a.info.count);\n \n // 強制包含ボクセルを最初に追加\n const selected = [];\n const included = new Set();\n \n // TopNなど強制包含ボクセルを先に追加\n sorted.forEach(voxel => {\n if (forceInclude.has(voxel.key) && selected.length < maxCount) {\n selected.push(voxel);\n included.add(voxel.key);\n }\n });\n \n // 残りを密度順で追加\n sorted.forEach(voxel => {\n if (!included.has(voxel.key) && selected.length < maxCount) {\n selected.push(voxel);\n included.add(voxel.key);\n }\n });\n \n return { selected };\n }\n\n /**\n * Select voxels by coverage (stratified sampling).\n * カバレッジによる選択(層化抽出)\n * @param {Array} allVoxels - All voxels / 全ボクセル\n * @param {number} maxCount - Maximum count / 最大数\n * @param {Object} bounds - Data bounds / データ境界\n * @param {Set} forceInclude - Voxels to force include / 強制包含ボクセル\n * @returns {Object} Selection result / 選択結果\n * @private\n */\n _selectByCoverage(allVoxels, maxCount, grid, forceInclude = new Set()) {\n const selected = [];\n const included = new Set();\n \n // 強制包含ボクセルを先に追加\n allVoxels.forEach(voxel => {\n if (forceInclude.has(voxel.key) && selected.length < maxCount) {\n selected.push(voxel);\n included.add(voxel.key);\n }\n });\n \n // 格子分割数の決定\n const binsXY = this.options.coverageBinsXY === 'auto' \n ? Math.ceil(Math.sqrt(maxCount / 4)) // 自動計算: 平均4ボクセル/ビン\n : this.options.coverageBinsXY;\n \n // 空間をグリッド分割\n const bins = new Map();\n const remainingVoxels = allVoxels.filter(voxel => !included.has(voxel.key));\n \n remainingVoxels.forEach(voxel => {\n const binX = Math.max(0, Math.min(binsXY - 1, Math.floor((voxel.info.x / Math.max(1, grid.numVoxelsX)) * binsXY)));\n const binY = Math.max(0, Math.min(binsXY - 1, Math.floor((voxel.info.y / Math.max(1, grid.numVoxelsY)) * binsXY)));\n const binKey = `${binX},${binY}`;\n \n if (!bins.has(binKey)) {\n bins.set(binKey, []);\n }\n bins.get(binKey).push(voxel);\n });\n \n // 各ビンから代表ボクセルを選択\n const binKeys = Array.from(bins.keys());\n let binIndex = 0;\n \n while (selected.length < maxCount && binIndex < binKeys.length * 10) { // 最大10周\n const binKey = binKeys[binIndex % binKeys.length];\n const binVoxels = bins.get(binKey);\n \n if (binVoxels && binVoxels.length > 0) {\n // ビン内で最高密度のボクセルを選択\n binVoxels.sort((a, b) => b.info.count - a.info.count);\n const voxel = binVoxels.shift();\n \n if (!included.has(voxel.key)) {\n selected.push(voxel);\n included.add(voxel.key);\n }\n \n // 空になったビンを削除\n if (binVoxels.length === 0) {\n bins.delete(binKey);\n binKeys.splice(binKeys.indexOf(binKey), 1);\n }\n }\n \n binIndex++;\n }\n \n return { selected };\n }\n\n /**\n * Select voxels by hybrid strategy (density + coverage).\n * ハイブリッド戦略による選択(密度 + カバレッジ)\n * @param {Array} allVoxels - All voxels / 全ボクセル\n * @param {number} maxCount - Maximum count / 最大数\n * @param {Object} bounds - Data bounds / データ境界\n * @param {Set} forceInclude - Voxels to force include / 強制包含ボクセル\n * @returns {Object} Selection result / 選択結果\n * @private\n */\n _selectByHybrid(allVoxels, maxCount, grid, forceInclude = new Set()) {\n const minCoverageRatio = this.options.minCoverageRatio || 0.2;\n \n const selected = [];\n const included = new Set();\n \n // 強制包含ボクセルを先に追加\n allVoxels.forEach(voxel => {\n if (forceInclude.has(voxel.key) && selected.length < maxCount) {\n selected.push(voxel);\n included.add(voxel.key);\n }\n });\n \n const remainingCount = maxCount - selected.length;\n const adjustedCoverageCount = Math.floor(remainingCount * minCoverageRatio);\n const adjustedDensityCount = remainingCount - adjustedCoverageCount;\n \n // カバレッジ選択(層化抽出)\n if (adjustedCoverageCount > 0) {\n const coverageResult = this._selectByCoverage(\n allVoxels.filter(voxel => !included.has(voxel.key)), \n adjustedCoverageCount, \n grid, \n new Set()\n );\n \n coverageResult.selected.forEach(voxel => {\n if (selected.length < maxCount && !included.has(voxel.key)) {\n selected.push(voxel);\n included.add(voxel.key);\n }\n });\n }\n \n // 密度選択(残り)\n if (adjustedDensityCount > 0) {\n const densityResult = this._selectByDensity(\n allVoxels.filter(voxel => !included.has(voxel.key)), \n adjustedDensityCount, \n new Set()\n );\n \n densityResult.selected.forEach(voxel => {\n if (selected.length < maxCount && !included.has(voxel.key)) {\n selected.push(voxel);\n included.add(voxel.key);\n }\n });\n }\n \n // 実際のカバレッジ比率を計算\n const actualCoverageRatio = adjustedCoverageCount > 0 ? \n (selected.length - forceInclude.size - adjustedDensityCount) / (selected.length - forceInclude.size) : 0;\n \n return { \n selected, \n coverageRatio: actualCoverageRatio \n };\n }\n\n /**\n * Get selection statistics.\n * 選択統計を取得します。\n * @returns {Object|null} Selection statistics / 選択統計\n */\n getSelectionStats() {\n return this._selectionStats || null;\n }\n}\n","/**\n * CesiumJS Heatbox - Entry point.\n * CesiumJS Heatbox - エントリーポイント。\n */\n\nimport { Heatbox } from './Heatbox.js';\nimport { Logger } from './utils/logger.js';\nimport { getAllEntities, generateTestEntities } from './utils/sampleData.js';\n\n// デフォルトエクスポート\nexport default Heatbox;\n\n// 名前付きエクスポート\nexport { Heatbox };\nexport { getAllEntities, generateTestEntities };\n\n// 互換性のための追加エクスポート\nexport { Heatbox as CesiumHeatbox };\n\n/**\n * Library metadata.\n * ライブラリのメタ情報。\n */\nexport const VERSION = '0.1.9';\nexport const AUTHOR = 'hiro-nyon';\nexport const REPOSITORY = 'https://github.com/hiro-nyon/cesium-heatbox';\n\n/**\n * Quick start helper function.\n * クイックスタート用のヘルパー関数。\n * @param {Object} viewer - CesiumJS Viewer / CesiumJS Viewer\n * @param {Object} options - Configuration options / 設定オプション\n * @returns {Heatbox} New Heatbox instance / 生成された Heatbox インスタンス\n */\nexport function createHeatbox(viewer, options) {\n return new Heatbox(viewer, options);\n}\n\n/**\n * Get environment information.\n * 環境情報を取得します。\n * @returns {Object} Environment info / 環境情報\n */\nexport function getEnvironmentInfo() {\n // WebGL サポートの確認\n let webglSupport = false;\n try {\n if (typeof WebGLRenderingContext !== 'undefined') {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n webglSupport = !!gl;\n }\n } catch (_e) {\n webglSupport = false;\n }\n \n return {\n version: VERSION,\n cesiumVersion: typeof Cesium !== 'undefined' ? Cesium.VERSION : 'N/A',\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'N/A',\n webglSupport: webglSupport,\n timestamp: new Date().toISOString()\n };\n}\n\n// ライブラリの初期化ログ\nLogger.info(`CesiumJS Heatbox v${VERSION} loaded`);\n","/**\n * CesiumJS Heatbox - メインクラス\n */\nimport * as Cesium from 'cesium';\nimport { DEFAULT_OPTIONS, ERROR_MESSAGES, PERFORMANCE_LIMITS } from './utils/constants.js';\nimport { \n isValidViewer,\n isValidEntities,\n validateAndNormalizeOptions,\n validateVoxelCount,\n estimateInitialVoxelSize,\n calculateDataRange\n} from './utils/validation.js';\nimport { applyAutoRenderBudget } from './utils/deviceTierDetector.js';\nimport { Logger } from './utils/logger.js';\nimport { CoordinateTransformer } from './core/CoordinateTransformer.js';\nimport { VoxelGrid } from './core/VoxelGrid.js';\nimport { DataProcessor } from './core/DataProcessor.js';\nimport { VoxelRenderer } from './core/VoxelRenderer.js';\n\n/**\n * Main class of CesiumJS Heatbox.\n * Provides 3D voxel-based heatmap visualization in CesiumJS environments.\n *\n * CesiumJS Heatbox メインクラス。\n * CesiumJS 環境で 3D ボクセルベースのヒートマップ可視化を提供します。\n */\nexport class Heatbox {\n /**\n * Constructor\n * @param {Cesium.Viewer} viewer - CesiumJS Viewer instance / CesiumJS Viewer インスタンス\n * @param {Object} options - Configuration options / 設定オプション\n */\n constructor(viewer, options = {}) {\n if (!isValidViewer(viewer)) {\n throw new Error(ERROR_MESSAGES.INVALID_VIEWER);\n }\n \n this.viewer = viewer;\n \n // v0.1.9: Auto Render Budgetの適用\n const mergedOptions = { ...DEFAULT_OPTIONS, ...options };\n this.options = validateAndNormalizeOptions(applyAutoRenderBudget(mergedOptions));\n \n // ログレベルをオプションに基づいて設定\n Logger.setLogLevel(this.options);\n this.renderer = new VoxelRenderer(this.viewer, this.options);\n \n this._bounds = null;\n this._grid = null;\n this._voxelData = null;\n this._statistics = null;\n this._eventHandler = null;\n\n this._initializeEventListeners();\n }\n\n /**\n * Set heatmap data and render.\n * ヒートマップデータを設定し、描画を実行します。\n * @param {Cesium.Entity[]} entities - Target entities array / 対象エンティティ配列\n */\n async setData(entities) {\n if (!isValidEntities(entities)) {\n this.clear();\n return;\n }\n \n try {\n Logger.debug('Heatbox.setData - 処理開始:', entities.length, '個のエンティティ');\n \n // 1. 境界計算\n Logger.debug('Step 1: 境界計算');\n this._bounds = CoordinateTransformer.calculateBounds(entities);\n if (!this._bounds) {\n Logger.error('境界計算に失敗');\n this.clear();\n return;\n }\n Logger.debug('境界計算完了:', this._bounds);\n\n // v0.1.4+v0.1.9: 自動ボクセルサイズ調整(占有率ベース対応)\n let finalVoxelSize = this.options.voxelSize || DEFAULT_OPTIONS.voxelSize;\n let autoAdjustmentInfo = null;\n \n if (this.options.autoVoxelSize && !this.options.voxelSize) {\n try {\n Logger.debug('自動ボクセルサイズ調整開始');\n \n // v0.1.9: 占有率ベースの計算オプション\n const sizeOptions = {\n autoVoxelSizeMode: this.options.autoVoxelSizeMode,\n autoVoxelTargetFill: this.options.autoVoxelTargetFill,\n maxRenderVoxels: this.options.maxRenderVoxels\n };\n \n const estimatedSize = estimateInitialVoxelSize(this._bounds, entities.length, sizeOptions);\n const tempGrid = VoxelGrid.createGrid(this._bounds, estimatedSize);\n const validation = validateVoxelCount(tempGrid.totalVoxels, estimatedSize);\n \n if (!validation.valid && validation.recommendedSize) {\n finalVoxelSize = validation.recommendedSize;\n autoAdjustmentInfo = {\n enabled: true,\n mode: this.options.autoVoxelSizeMode,\n originalSize: estimatedSize,\n finalSize: finalVoxelSize,\n adjusted: true,\n reason: `Performance limit exceeded: ${tempGrid.totalVoxels} > ${PERFORMANCE_LIMITS.maxVoxels}`\n };\n Logger.info(`Auto-adjusted voxelSize: ${estimatedSize}m → ${finalVoxelSize}m (${tempGrid.totalVoxels} voxels)`);\n } else {\n finalVoxelSize = estimatedSize;\n autoAdjustmentInfo = {\n enabled: true,\n mode: this.options.autoVoxelSizeMode,\n originalSize: estimatedSize,\n finalSize: finalVoxelSize,\n adjusted: false,\n reason: null\n };\n Logger.info(`Auto-determined voxelSize: ${finalVoxelSize}m`);\n }\n } catch (error) {\n Logger.warn('Auto voxel size adjustment failed, using default:', error);\n finalVoxelSize = DEFAULT_OPTIONS.voxelSize;\n autoAdjustmentInfo = {\n enabled: true,\n adjusted: false,\n reason: 'Estimation failed, using default size',\n originalSize: null,\n finalSize: finalVoxelSize\n };\n }\n }\n\n // 2. グリッド生成(最終的なボクセルサイズを使用)\n Logger.debug('Step 2: グリッド生成 (サイズ:', finalVoxelSize, 'm)');\n this._grid = VoxelGrid.createGrid(this._bounds, finalVoxelSize);\n Logger.debug('グリッド生成完了:', this._grid);\n \n // 3. エンティティ分類\n Logger.debug('Step 3: エンティティ分類');\n this._voxelData = DataProcessor.classifyEntitiesIntoVoxels(entities, this._bounds, this._grid);\n Logger.debug('エンティティ分類完了:', this._voxelData.size, '個のボクセル');\n \n // 4. 統計計算\n Logger.debug('Step 4: 統計計算');\n this._statistics = DataProcessor.calculateStatistics(this._voxelData, this._grid);\n Logger.debug('統計情報:', this._statistics);\n \n // 統計情報に自動調整情報を追加\n if (autoAdjustmentInfo) {\n this._statistics.autoAdjusted = autoAdjustmentInfo.adjusted;\n this._statistics.originalVoxelSize = autoAdjustmentInfo.originalSize;\n this._statistics.finalVoxelSize = autoAdjustmentInfo.finalSize;\n this._statistics.adjustmentReason = autoAdjustmentInfo.reason;\n }\n \n // 5. 描画\n Logger.debug('Step 5: 描画');\n const renderedVoxelCount = this.renderer.render(this._voxelData, this._bounds, this._grid, this._statistics);\n \n // 統計情報に実際の描画数を反映\n this._statistics.renderedVoxels = renderedVoxelCount;\n Logger.info('描画完了 - 実際の描画数:', renderedVoxelCount);\n \n // v0.1.9: 自動視点調整\n if (this.options.autoView) {\n try {\n Logger.debug('Auto view adjustment triggered');\n await this.fitView();\n Logger.debug('Auto view adjustment completed');\n } catch (error) {\n Logger.warn('Auto view adjustment failed:', error);\n // 自動視点調整の失敗は致命的エラーとしない\n }\n }\n \n Logger.debug('Heatbox.setData - 処理完了');\n \n } catch (error) {\n Logger.error('ヒートマップ作成エラー:', error);\n this.clear();\n throw error;\n }\n }\n\n /**\n * Create heatmap from entities (async).\n * エンティティからヒートマップを作成(非同期 API)。\n * @param {Cesium.Entity[]} entities - Target entities array / 対象エンティティ配列\n * @returns {Promise<Object>} Statistics info / 統計情報\n */\n async createFromEntities(entities) {\n if (!isValidEntities(entities)) {\n throw new Error(ERROR_MESSAGES.NO_ENTITIES);\n }\n await this.setData(entities);\n return this.getStatistics();\n }\n\n /**\n * Toggle visibility.\n * 表示/非表示を切り替えます。\n * @param {boolean} show - true to show / 表示する場合は true\n */\n setVisible(show) {\n this.renderer.setVisible(show);\n }\n\n /**\n * Clear the heatmap and internal state.\n * ヒートマップと内部状態をクリアします。\n */\n clear() {\n this.renderer.clear();\n this._bounds = null;\n this._grid = null;\n this._voxelData = null;\n this._statistics = null;\n }\n\n /**\n * Destroy the instance and release event listeners.\n * インスタンスを破棄し、イベントリスナーを解放します。\n */\n destroy() {\n this.clear();\n if (this._eventHandler && !this._eventHandler.isDestroyed()) {\n this._eventHandler.destroy();\n }\n this._eventHandler = null;\n }\n\n /**\n * Alias for destroy() to match examples and tests.\n * 互換性のための別名。destroy() を呼び出します。\n */\n dispose() {\n this.destroy();\n }\n\n /**\n * Get current options.\n * 現在のオプションを取得します。\n * @returns {Object} Options / オプション\n */\n getOptions() {\n return { ...this.options };\n }\n\n /**\n * Update options and re-render if applicable.\n * オプションを更新し、必要に応じて再描画します。\n * @param {Object} newOptions - New options / 新しいオプション\n */\n updateOptions(newOptions) {\n this.options = validateAndNormalizeOptions({ ...this.options, ...newOptions });\n this.renderer.options = this.options;\n \n // 既存のヒートマップがある場合は再描画\n if (this._voxelData) {\n const renderedVoxelCount = this.renderer.render(this._voxelData, this._bounds, this._grid, this._statistics);\n // 統計情報を更新\n this._statistics.renderedVoxels = renderedVoxelCount;\n }\n }\n\n /**\n * Initialize internal event listeners.\n * 内部のイベントリスナーを初期化します。\n * @private\n */\n _initializeEventListeners() {\n this._eventHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);\n\n // クリックイベントでInfoBoxを更新\n this._eventHandler.setInputAction(movement => {\n const pickedObject = this.viewer.scene.pick(movement.position);\n if (Cesium.defined(pickedObject) && pickedObject.id && \n pickedObject.id.properties && \n pickedObject.id.properties.type === 'voxel') {\n // プロパティからキー値を取得\n const voxelKey = pickedObject.id.properties.key;\n const voxelInfo = {\n x: pickedObject.id.properties.x,\n y: pickedObject.id.properties.y,\n z: pickedObject.id.properties.z,\n count: pickedObject.id.properties.count\n };\n \n // InfoBoxに表示するためのダミーエンティティを作成\n const dummyEntity = new Cesium.Entity({\n id: `voxel-${voxelKey}`,\n description: this.renderer.createVoxelDescription(voxelInfo, voxelKey)\n });\n this.viewer.selectedEntity = dummyEntity;\n }\n }, Cesium.ScreenSpaceEventType.LEFT_CLICK);\n }\n\n /**\n * Get statistics information.\n * 統計情報を取得します(未作成の場合は null)。\n * @returns {Object|null} Statistics or null / 統計情報 または null\n */\n getStatistics() {\n if (!this._statistics) {\n return null;\n }\n\n // 基本統計情報\n const stats = { ...this._statistics };\n\n // v0.1.9: 選択戦略統計を追加\n const selectionStats = this.renderer.getSelectionStats();\n if (selectionStats) {\n stats.selectionStrategy = selectionStats.strategy;\n stats.clippedNonEmpty = selectionStats.clippedNonEmpty;\n stats.coverageRatio = selectionStats.coverageRatio ?? 0;\n }\n\n // v0.1.9: Auto Render Budget統計を追加\n if (this.options._autoRenderBudget) {\n stats.renderBudgetTier = this.options._autoRenderBudget.tier;\n stats.autoMaxRenderVoxels = this.options._autoRenderBudget.autoMaxRenderVoxels;\n }\n\n // v0.1.9: occupancy ratio (rendered / budget) for diagnostics\n if (typeof this.options.maxRenderVoxels === 'number' && this.options.maxRenderVoxels > 0) {\n stats.occupancyRatio = Math.min(1, Math.max(0, (stats.renderedVoxels || 0) / this.options.maxRenderVoxels));\n } else {\n stats.occupancyRatio = null;\n }\n\n return stats;\n }\n\n /**\n * Get bounds info if available.\n * 境界情報を取得します(未作成の場合は null)。\n * @returns {Object|null} Bounds or null / 境界情報 または null\n */\n getBounds() {\n return this._bounds;\n }\n\n /**\n * Get debug information.\n * デバッグ情報を取得します。\n * @returns {Object} Debug info / デバッグ情報\n */\n getDebugInfo() {\n const baseInfo = {\n options: { ...this.options },\n bounds: this._bounds,\n grid: this._grid,\n statistics: this._statistics\n };\n \n // v0.1.4: 自動調整情報を追加\n if (this.options.autoVoxelSize) {\n baseInfo.autoVoxelSizeInfo = {\n enabled: this.options.autoVoxelSize,\n originalSize: this._statistics?.originalVoxelSize,\n finalSize: this._statistics?.finalVoxelSize,\n adjusted: this._statistics?.autoAdjusted || false,\n reason: this._statistics?.adjustmentReason,\n dataRange: this._bounds ? calculateDataRange(this._bounds) : null,\n estimatedDensity: this._bounds && this._statistics ? \n this._statistics.totalEntities / (calculateDataRange(this._bounds).x * calculateDataRange(this._bounds).y * calculateDataRange(this._bounds).z) : null\n };\n }\n \n return baseInfo;\n }\n\n /**\n * Fit view to data bounds with smart camera positioning.\n * データ境界にスマートなカメラ位置でビューをフィットします。\n * @param {Object} bounds - Target bounds (optional, uses current data bounds if not provided) / 対象境界\n * @param {Object} options - Fit view options / フィットビューオプション\n * @returns {Promise} Promise that resolves when camera movement is complete / カメラ移動完了時に解決するPromise\n */\n async fitView(bounds = null, options = {}) {\n try {\n const targetBounds = bounds || this._bounds;\n if (!targetBounds) {\n Logger.warn('No bounds available for fitView');\n return;\n }\n\n // 境界の妥当性チェック\n if (!this._isValidBounds(targetBounds)) {\n Logger.warn('Invalid bounds provided to fitView:', targetBounds);\n return;\n }\n\n const fitOptions = {\n ...this.options.fitViewOptions,\n ...options\n };\n\n Logger.debug('fitView called with bounds:', targetBounds, 'options:', fitOptions);\n\n // データ境界の中心とサイズを計算\n const centerLon = (targetBounds.minLon + targetBounds.maxLon) / 2;\n const centerLat = (targetBounds.minLat + targetBounds.maxLat) / 2;\n const centerAlt = (targetBounds.minAlt + targetBounds.maxAlt) / 2;\n\n // データ範囲の計算(極端なケースの処理)\n const dataRange = calculateDataRange(targetBounds);\n const maxRange = Math.max(dataRange.x, dataRange.y, dataRange.z);\n \n // 極小データの保護\n if (maxRange < 10) {\n Logger.debug('Very small data range detected, applying minimum scale');\n return this._handleMinimalDataRange(centerLon, centerLat, centerAlt, fitOptions);\n }\n \n // 極大データの保護\n if (maxRange > 100000) {\n Logger.debug('Very large data range detected, applying maximum scale');\n return this._handleLargeDataRange(targetBounds, fitOptions);\n }\n\n // パディングの計算(範囲制限)\n const paddingPercent = Math.max(0.05, Math.min(0.5, fitOptions.paddingPercent));\n const paddingMeters = paddingPercent * maxRange;\n \n // カメラ高度の計算(ピッチと視野角を考慮)\n const cameraHeight = this._calculateOptimalCameraHeight(\n maxRange, \n paddingMeters, \n fitOptions\n );\n\n // カメラ移動の実行\n return this._executeCameraMovement(\n centerLon, \n centerLat, \n centerAlt, \n cameraHeight, \n fitOptions,\n maxRange,\n paddingMeters\n );\n\n } catch (error) {\n Logger.error('fitView failed:', error);\n throw error;\n }\n }\n\n /**\n * Validate bounds object.\n * 境界オブジェクトの妥当性をチェックします。\n * @param {Object} bounds - Bounds to validate / 検証する境界\n * @returns {boolean} True if valid / 有効な場合true\n * @private\n */\n _isValidBounds(bounds) {\n return bounds &&\n typeof bounds.minLon === 'number' && !isNaN(bounds.minLon) &&\n typeof bounds.maxLon === 'number' && !isNaN(bounds.maxLon) &&\n typeof bounds.minLat === 'number' && !isNaN(bounds.minLat) &&\n typeof bounds.maxLat === 'number' && !isNaN(bounds.maxLat) &&\n typeof bounds.minAlt === 'number' && !isNaN(bounds.minAlt) &&\n typeof bounds.maxAlt === 'number' && !isNaN(bounds.maxAlt) &&\n bounds.minLon <= bounds.maxLon &&\n bounds.minLat <= bounds.maxLat &&\n bounds.minAlt <= bounds.maxAlt;\n }\n\n /**\n * Handle minimal data range case.\n * 極小データ範囲の場合の処理\n * @param {number} centerLon - Center longitude / 中心経度\n * @param {number} centerLat - Center latitude / 中心緯度\n * @param {number} centerAlt - Center altitude / 中心高度\n * @param {Object} fitOptions - Fit options / フィットオプション\n * @returns {Promise} Camera movement promise / カメラ移動Promise\n * @private\n */\n async _handleMinimalDataRange(centerLon, centerLat, centerAlt, fitOptions) {\n Logger.debug('Handling minimal data range');\n \n const destination = Cesium.Cartesian3.fromDegrees(centerLon, centerLat, centerAlt + 2000);\n const heading = Cesium.Math.toRadians(fitOptions.heading);\n const pitch = Cesium.Math.toRadians(fitOptions.pitch);\n \n return this.viewer.camera.flyTo({\n destination,\n orientation: { heading, pitch, roll: 0 },\n duration: 1.5\n });\n }\n\n /**\n * Handle large data range case.\n * 極大データ範囲の場合の処理\n * @param {Object} bounds - Target bounds / 対象境界\n * @param {Object} fitOptions - Fit options / フィットオプション\n * @returns {Promise} Camera movement promise / カメラ移動Promise\n * @private\n */\n async _handleLargeDataRange(bounds, fitOptions) {\n Logger.debug('Handling large data range with bounding sphere');\n \n const centerLon = (bounds.minLon + bounds.maxLon) / 2;\n const centerLat = (bounds.minLat + bounds.maxLat) / 2;\n const centerAlt = (bounds.minAlt + bounds.maxAlt) / 2;\n \n const dataRange = calculateDataRange(bounds);\n const maxRange = Math.max(dataRange.x, dataRange.y, dataRange.z);\n \n const boundingSphere = new Cesium.BoundingSphere(\n Cesium.Cartesian3.fromDegrees(centerLon, centerLat, centerAlt),\n maxRange / 2\n );\n \n const heading = Cesium.Math.toRadians(fitOptions.heading);\n const pitch = Cesium.Math.toRadians(fitOptions.pitch);\n \n return this.viewer.camera.flyToBoundingSphere(boundingSphere, {\n duration: 2.5,\n offset: new Cesium.HeadingPitchRange(heading, pitch, 0)\n });\n }\n\n /**\n * Calculate optimal camera height.\n * 最適なカメラ高度を計算します。\n * @param {number} maxRange - Maximum data range / 最大データ範囲\n * @param {number} paddingMeters - Padding in meters / パディング(メートル)\n * @param {Object} fitOptions - Fit options / フィットオプション\n * @returns {number} Optimal camera height / 最適なカメラ高度\n * @private\n */\n _calculateOptimalCameraHeight(maxRange, paddingMeters, fitOptions) {\n if (fitOptions.altitudeStrategy !== 'auto') {\n return fitOptions.altitude || 5000;\n }\n\n try {\n const pitch = Cesium.Math.toRadians(fitOptions.pitch);\n const fov = this.viewer.camera.frustum.fovy || Cesium.Math.toRadians(60);\n \n // 幾何学的計算: データがフレームに収まる高度を計算\n const adjustedRange = maxRange + paddingMeters;\n const baseCameraHeight = adjustedRange / (2 * Math.tan(fov / 2));\n \n // ピッチ補正(斜め視点での見え方調整)\n const absPitch = Math.abs(pitch);\n const pitchFactor = Math.max(0.5, Math.sin(Math.PI/2 - absPitch) + 0.3);\n let cameraHeight = baseCameraHeight * pitchFactor;\n \n // アスペクト比補正(極端に細長いデータの場合)\n const aspectRatio = maxRange / Math.min(maxRange, 100);\n if (aspectRatio > 5) {\n cameraHeight *= Math.log10(aspectRatio) + 1;\n }\n \n // 制限値適用(データ範囲に基づく適応的制限)\n const minHeight = Math.max(500, maxRange * 0.1);\n const maxHeight = Math.min(100000, maxRange * 10);\n cameraHeight = Math.max(minHeight, Math.min(maxHeight, cameraHeight));\n \n Logger.debug(`Camera height calculated: ${cameraHeight.toFixed(0)}m (range: ${maxRange.toFixed(0)}m, pitch: ${fitOptions.pitch}°)`);\n return cameraHeight;\n \n } catch (error) {\n Logger.warn('Camera height calculation failed, using fallback:', error);\n return Math.max(2000, maxRange * 2);\n }\n }\n\n /**\n * Execute camera movement.\n * カメラ移動を実行します。\n * @param {number} centerLon - Center longitude / 中心経度\n * @param {number} centerLat - Center latitude / 中心緯度\n * @param {number} centerAlt - Center altitude / 中心高度\n * @param {number} cameraHeight - Camera height / カメラ高度\n * @param {Object} fitOptions - Fit options / フィットオプション\n * @param {number} maxRange - Maximum range / 最大範囲\n * @param {number} paddingMeters - Padding meters / パディング(メートル)\n * @returns {Promise} Camera movement promise / カメラ移動Promise\n * @private\n */\n async _executeCameraMovement(centerLon, centerLat, centerAlt, cameraHeight, fitOptions, maxRange, paddingMeters) {\n try {\n // 目標カメラ位置\n const destination = Cesium.Cartesian3.fromDegrees(\n centerLon, \n centerLat, \n centerAlt + cameraHeight\n );\n\n // カメラの向き設定\n const heading = Cesium.Math.toRadians(fitOptions.heading);\n const pitch = Cesium.Math.toRadians(fitOptions.pitch);\n const roll = 0;\n\n const orientation = {\n heading,\n pitch,\n roll\n };\n\n Logger.debug(`Camera target: position=${centerLon.toFixed(6)},${centerLat.toFixed(6)},${(centerAlt + cameraHeight).toFixed(0)}, heading=${fitOptions.heading}°, pitch=${fitOptions.pitch}°`);\n\n // 距離に応じた移動時間の調整\n const duration = Math.max(1.0, Math.min(3.0, Math.log10(maxRange) * 0.8));\n\n // プライマリ: flyTo を使用\n const flyPromise = this.viewer.camera.flyTo({\n destination,\n orientation,\n duration,\n complete: () => {\n Logger.debug('fitView camera movement completed');\n },\n cancel: () => {\n Logger.debug('fitView camera movement cancelled');\n }\n });\n\n // flyToが利用できない場合のフォールバック\n if (!flyPromise) {\n Logger.debug('Using fallback: flyToBoundingSphere');\n const boundingSphere = new Cesium.BoundingSphere(\n Cesium.Cartesian3.fromDegrees(centerLon, centerLat, centerAlt),\n maxRange / 2 + paddingMeters\n );\n \n await this.viewer.camera.flyToBoundingSphere(boundingSphere, {\n duration,\n offset: new Cesium.HeadingPitchRange(heading, pitch, 0)\n });\n } else {\n await flyPromise;\n }\n\n Logger.info('fitView completed successfully');\n \n } catch (error) {\n Logger.error('Camera movement execution failed:', error);\n throw error;\n }\n }\n\n /**\n * Filter entity array (utility static method).\n * エンティティ配列をフィルタします(ユーティリティ・静的メソッド)。\n * @param {Cesium.Entity[]} entities - Entity array / エンティティ配列\n * @param {Function} predicate - Predicate function / フィルタ関数\n * @returns {Cesium.Entity[]} Filtered array / フィルタ済み配列\n */\n static filterEntities(entities, predicate) {\n if (!Array.isArray(entities) || typeof predicate !== 'function') return [];\n return entities.filter(predicate);\n }\n}\n"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__50__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","d","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","DEFAULT_OPTIONS","voxelSize","opacity","emptyOpacity","showOutline","showEmptyVoxels","minColor","maxColor","maxRenderVoxels","batchMode","debug","autoVoxelSize","colorMap","diverging","divergingPivot","highlightTopN","highlightStyle","outlineWidth","boostOpacity","voxelGap","outlineOpacity","outlineWidthResolver","outlineEmulation","outlineInset","outlineInsetMode","enableThickFrames","outlineRenderMode","adaptiveOutlines","outlineWidthPreset","boxOpacityResolver","outlineOpacityResolver","adaptiveParams","neighborhoodRadius","densityThreshold","cameraDistanceFactor","overlapRiskFactor","renderLimitStrategy","minCoverageRatio","coverageBinsXY","autoVoxelSizeMode","autoVoxelTargetFill","renderBudgetMode","autoView","fitViewOptions","paddingPercent","pitch","heading","altitudeStrategy","PERFORMANCE_LIMITS","ERROR_MESSAGES","Math","PI","currentLogLevel","process","env","DEBUG","Logger","error","args","console","warn","info","log","setLogLevel","options","isValidEntities","entities","Array","isArray","length","validateAndNormalizeOptions","normalized","isNaN","Error","max","min","map","c","floor","includes","parseFloat","v","inset","Boolean","n","parseInt","Number","isFinite","f","padding","estimateVoxelSizeBasic","bounds","entityCount","dataRange","calculateDataRange","volume","x","y","z","density","estimatedSize","sqrt","round","centerLat","minLat","maxLat","cosLat","cos","lonRangeMeters","maxLon","minLon","latRangeMeters","altRangeMeters","maxAlt","minAlt","DEVICE_TIER_RANGES","low","mid","high","CoordinateTransformer","calculateBounds","Infinity","validCount","currentTime","Cesium","now","forEach","entity","index","position","getValue","cartographic","fromCartesian","lon","toDegrees","longitude","lat","latitude","alt","height","centerLon","centerAlt","voxelIndexToCoordinate","grid","numVoxelsX","numVoxelsY","numVoxelsZ","coordinateToCartesian3","fromDegrees","VoxelGrid","createGrid","voxelSizeMeters","ceil","cellSizeX","cellSizeY","cellSizeZ","totalVoxels","getVoxelKey","parseVoxelKey","split","iterateAllVoxels","callback","DataProcessor","classifyEntitiesIntoVoxels","voxelData","Map","processedCount","skippedCount","lonDen","latDen","altDen","voxelX","voxelY","voxelZ","voxelKey","has","set","count","voxelInfo","push","size","calculateStatistics","renderedVoxels","nonEmptyVoxels","emptyVoxels","totalEntities","minCount","maxCount","averageCount","autoAdjusted","originalVoxelSize","finalVoxelSize","adjustmentReason","counts","from","values","voxel","reduce","sum","stats","getTopNVoxels","topN","sortedVoxels","sort","a","b","slice","COLOR_MAPS","viridis","inferno","VoxelRenderer","constructor","viewer","wireframeOnly","heightBased","voxelEntities","_calculateAdaptiveParams","isTopN","statistics","boxOpacity","shouldUseEmulation","normalizedDensity","neighborhoodDensity","neighborCount","radius","dx","dy","dz","neighborKey","neighbor","isDenseArea","cameraFactor","overlapRisk","adaptiveWidth","adaptiveBoxOpacity","adaptiveOutlineOpacity","render","clear","voxelDataSize","_shouldShowBounds","_renderBoundingBox","displayVoxels","topNVoxels","Set","maxVoxels","entries","selectionResult","_selectVoxelsForRendering","selectedVoxels","_selectionStats","strategy","clippedNonEmpty","coverageRatio","add","renderedCount","color","LIGHTGRAY","interpolateColor","resolverCtx","resolverOpacity","e","baseCellSizeZ","finalOutlineWidth","finalOutlineOpacity","boxHeight","resolverParams","outlineColorWithOpacity","withAlpha","shouldShowStandardOutline","shouldShowInsetOutline","shouldUseEmulationOnly","emulateThickForThis","entityConfig","box","dimensions","outline","outlineColor","properties","type","description","createVoxelDescription","material","TRANSPARENT","fill","_shouldApplyInsetOutline","insetAmount","_createInsetOutline","centerCart","maxInsetX","maxInsetY","maxInsetZ","baseInset","autoInsetX","autoInsetY","autoInsetZ","effInsetX","effInsetY","effInsetZ","midSizeX","midSizeY","midSizeZ","_addEdgePolylines","widthMeters","depthMeters","heightMeters","boundingBox","YELLOW","toFixed","center","width","depth","sx","sy","sz","halfX","halfY","halfZ","enu","eastNorthUpToFixedFrame","toWorld","local","multiplyByPoint","C","i","j","poly","polyline","positions","arcType","NONE","rawValue","_interpolateDivergingColor","_interpolateFromColorMap","minR","minG","minB","maxR","maxG","maxB","r","g","fromBytes","normalizedValue","colorMapName","scaledValue","lowerIndex","upperIndex","fraction","r1","g1","b1","r2","g2","b2","pivot","isDestroyed","remove","showBounds","baseSizeX","baseSizeY","baseSizeZ","effectiveInsetX","effectiveInsetY","effectiveInsetZ","insetSizeX","insetSizeY","insetSizeZ","insetEntity","parentKey","insetSize","_createThickOutlineFrames","originalSize","effectiveInset","outerX","outerY","outerZ","innerX","innerY","innerZ","frameColor","frameThickX","frameThickY","frameThickZ","outerBoundX","outerBoundY","outerBoundZ","innerBoundX","innerBoundY","innerBoundZ","frameThick","outerBound","innerBound","frames","pos","name","frame","DEG_PER_METER_LON","DEG_PER_METER_LAT","frameLon","frameLat","frameAlt","frameEntity","frameName","setVisible","show","allVoxels","clippedCount","_selectByCoverage","selected","hybridResult","_selectByHybrid","_selectByDensity","forceInclude","sorted","included","binsXY","bins","filter","binKey","binKeys","keys","binIndex","binVoxels","shift","delete","splice","indexOf","remainingCount","adjustedCoverageCount","adjustedDensityCount","actualCoverageRatio","getSelectionStats","scene","canvas","getContext","isValidViewer","mergedOptions","detection","webglInfo","document","createElement","gl","webgl2","maxTextureSize","maxRenderbufferSize","getParameter","MAX_TEXTURE_SIZE","MAX_RENDERBUFFER_SIZE","getWebGLInfo","deviceInfo","deviceMemory","navigator","hardwareConcurrency","devicePixelRatio","window","screenPixels","screen","pow","userAgent","getDeviceInfo","tier","detectionMethod","adjustedScore","range","detectDeviceTier","updatedOptions","_autoRenderBudget","autoMaxRenderVoxels","applyAutoRenderBudget","renderer","_bounds","_grid","_voxelData","_statistics","_eventHandler","_initializeEventListeners","setData","autoAdjustmentInfo","sizeOptions","targetFill","currentSize","iteration","expectedOccupied","exp","currentFill","abs","finalSize","estimateVoxelSizeByOccupancy","estimateInitialVoxelSize","tempGrid","validation","result","valid","warning","recommendedSize","validateVoxelCount","enabled","mode","adjusted","reason","renderedVoxelCount","fitView","createFromEntities","getStatistics","destroy","dispose","getOptions","updateOptions","newOptions","setInputAction","movement","pickedObject","pick","id","dummyEntity","selectedEntity","LEFT_CLICK","selectionStats","selectionStrategy","renderBudgetTier","occupancyRatio","getBounds","getDebugInfo","baseInfo","autoVoxelSizeInfo","estimatedDensity","targetBounds","_isValidBounds","fitOptions","maxRange","_handleMinimalDataRange","_handleLargeDataRange","paddingMeters","cameraHeight","_calculateOptimalCameraHeight","_executeCameraMovement","destination","toRadians","camera","flyTo","orientation","roll","duration","boundingSphere","flyToBoundingSphere","offset","altitude","fov","frustum","fovy","baseCameraHeight","tan","absPitch","sin","aspectRatio","log10","minHeight","maxHeight","flyPromise","complete","cancel","filterEntities","predicate"],"sourceRoot":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cesium-heatbox",
|
|
3
|
+
"version": "0.1.9-alpha.2",
|
|
4
|
+
"description": "3D voxel-based heatmap visualization library for CesiumJS",
|
|
5
|
+
"main": "dist/cesium-heatbox.umd.min.js",
|
|
6
|
+
"module": "dist/cesium-heatbox.min.js",
|
|
7
|
+
"types": "types/index.d.ts",
|
|
8
|
+
"browser": "dist/cesium-heatbox.umd.min.js",
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"types/",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE",
|
|
15
|
+
"CHANGELOG.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "webpack serve --mode development",
|
|
19
|
+
"build": "npm run build:esm && npm run build:umd && npm run build:types",
|
|
20
|
+
"build:esm": "webpack --mode production --env target=esm",
|
|
21
|
+
"build:umd": "webpack --mode production --env target=umd",
|
|
22
|
+
"build:types": "node tools/build-types.js",
|
|
23
|
+
"build:watch": "webpack --mode development --watch",
|
|
24
|
+
"test": "jest",
|
|
25
|
+
"test:watch": "jest --watch",
|
|
26
|
+
"test:coverage": "jest --coverage",
|
|
27
|
+
"lint": "eslint \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\"",
|
|
28
|
+
"lint:fix": "eslint \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\" --fix",
|
|
29
|
+
"type-check": "tsc --noEmit",
|
|
30
|
+
"benchmark": "node tools/benchmark.js",
|
|
31
|
+
"docs": "jsdoc src/ -d docs/api -c jsdoc.config.json",
|
|
32
|
+
"wiki:sync": "node tools/wiki-sync.js",
|
|
33
|
+
"wiki:publish": "bash tools/wiki/publish-wiki.sh hiro-nyon cesium-heatbox",
|
|
34
|
+
"wiki:update": "npm run docs && npm run wiki:sync && npm run wiki:publish",
|
|
35
|
+
"clean": "rm -rf dist/ types/ coverage/",
|
|
36
|
+
"prepublishOnly": "npm run clean && npm run build && npm test"
|
|
37
|
+
},
|
|
38
|
+
"exports": {
|
|
39
|
+
".": {
|
|
40
|
+
"types": "./types/index.d.ts",
|
|
41
|
+
"import": "./dist/cesium-heatbox.min.js",
|
|
42
|
+
"require": "./dist/cesium-heatbox.umd.min.js",
|
|
43
|
+
"default": "./dist/cesium-heatbox.umd.min.js"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"cesium",
|
|
48
|
+
"heatmap",
|
|
49
|
+
"3d",
|
|
50
|
+
"voxel",
|
|
51
|
+
"visualization",
|
|
52
|
+
"gis",
|
|
53
|
+
"spatial",
|
|
54
|
+
"analysis"
|
|
55
|
+
],
|
|
56
|
+
"author": "hiro-nyon",
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/hiro-nyon/cesium-heatbox.git"
|
|
61
|
+
},
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/hiro-nyon/cesium-heatbox/issues"
|
|
64
|
+
},
|
|
65
|
+
"homepage": "https://github.com/hiro-nyon/cesium-heatbox#readme",
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"cesium": "^1.120.0"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@babel/core": "^7.26.0",
|
|
71
|
+
"@babel/eslint-parser": "^7.25.0",
|
|
72
|
+
"@babel/preset-env": "^7.26.0",
|
|
73
|
+
"@babel/preset-typescript": "^7.26.0",
|
|
74
|
+
"@types/node": "^22.10.0",
|
|
75
|
+
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
|
76
|
+
"@typescript-eslint/parser": "^8.15.0",
|
|
77
|
+
"babel-jest": "^30.0.0",
|
|
78
|
+
"babel-loader": "^9.2.0",
|
|
79
|
+
"eslint": "^8.57.0",
|
|
80
|
+
"eslint-config-standard": "^17.1.0",
|
|
81
|
+
"eslint-plugin-import": "^2.29.0",
|
|
82
|
+
"eslint-plugin-jest": "^29.0.0",
|
|
83
|
+
"eslint-plugin-n": "^16.6.0",
|
|
84
|
+
"eslint-plugin-promise": "^6.1.0",
|
|
85
|
+
"eslint-webpack-plugin": "^4.2.0",
|
|
86
|
+
"jest": "^30.0.0",
|
|
87
|
+
"jest-environment-jsdom": "^30.0.0",
|
|
88
|
+
"jsdoc": "^4.0.4",
|
|
89
|
+
"jsdom": "^22.0.0",
|
|
90
|
+
"typescript": "^5.7.0",
|
|
91
|
+
"webpack": "^5.97.0",
|
|
92
|
+
"webpack-cli": "^6.0.0",
|
|
93
|
+
"webpack-dev-server": "^5.2.0"
|
|
94
|
+
},
|
|
95
|
+
"engines": {
|
|
96
|
+
"node": ">=18.0.0",
|
|
97
|
+
"npm": ">=8.0.0"
|
|
98
|
+
},
|
|
99
|
+
"publishConfig": {
|
|
100
|
+
"tag": "latest"
|
|
101
|
+
}
|
|
102
|
+
}
|