Files
MoundHunters/ui/src/batch-renderer.js

136 lines
4.1 KiB
JavaScript

/**
* Batch Renderer for Hopewell Lidar Tiles
*
* Usage in dev console with loaded app:
* import { batchRenderTiles } from './batch-renderer.js';
* const app = document.querySelector('#app').__vue_app__;
* const sandboxRef = app._instance.refs.sandboxRef;
* const tileCache = app._instance.data.tileCache;
*
* await batchRenderTiles(sandboxRef, tileCache, tileNames);
*/
/**
* Download a data URL as a file
*/
function downloadDataURL(dataURL, filename) {
const link = document.createElement('a');
link.href = dataURL;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
/**
* Download text content as a file
*/
function downloadText(text, filename) {
const blob = new Blob([text], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
/**
* Batch render tiles using already-loaded app
*
* @param {Object} sandboxRef - Vue ref to ShadingSandbox component
* @param {Object} tileCache - Cache of loaded tile data
* @param {string[]} tileNames - Array of tile names to render
* @param {Object} options - Options
* @param {Object} options.renderSettings - Override render settings
* @param {number} options.renderQuality - Render quality (default: 1024)
*
* @returns {Promise<Object[]>} Array of results
*/
export async function batchRenderTiles(sandboxRef, tileCache, tileNames, options = {}) {
const {
renderSettings = null, // Use sandbox defaults if null
renderQuality = 1024
} = options;
console.log(`[BatchRenderer] Starting batch render of ${tileNames.length} tiles`);
console.log(`[BatchRenderer] Quality: ${renderQuality}px`);
const results = [];
const startTime = Date.now();
for (let i = 0; i < tileNames.length; i++) {
const tileName = tileNames[i];
const current = i + 1;
const total = tileNames.length;
console.log(`[BatchRenderer] [${current}/${total}] Processing ${tileName}...`);
try {
const tileData = tileCache[tileName];
if (!tileData) {
throw new Error(`Tile ${tileName} not found in cache`);
}
// Render
console.log(`[BatchRenderer] Rendering...`);
const renderResult = await sandboxRef.renderTileWithSettings(
tileData,
renderSettings || sandboxRef.getSettings(),
renderQuality
);
if (!renderResult.success) {
throw new Error(renderResult.error || 'Render failed');
}
console.log(`[BatchRenderer] Rendered in ${renderResult.renderTime}ms`);
// Generate metadata
const metadata = {
tileName,
bounds: tileData.bounds,
renderSettings: renderSettings || sandboxRef.getSettings(),
renderQuality,
pointCount: tileData.pointCount,
triangleCount: tileData.triangleCount,
renderedAt: new Date().toISOString()
};
// Download
downloadDataURL(renderResult.dataURL, `${tileName}.png`);
downloadText(JSON.stringify(metadata, null, 2), `${tileName}.json`);
results.push({
tileName,
metadata,
renderTime: renderResult.renderTime,
success: true
});
console.log(`[BatchRenderer] ✓ Complete`);
// Small delay
await new Promise(resolve => setTimeout(resolve, 100));
} catch (err) {
console.error(`[BatchRenderer] ✗ Failed: ${err.message}`);
results.push({
tileName,
success: false,
error: err.message
});
}
}
const totalTime = Date.now() - startTime;
const successCount = results.filter(r => r.success).length;
const failCount = results.filter(r => !r.success).length;
console.log(`[BatchRenderer] Batch complete in ${(totalTime / 1000).toFixed(1)}s`);
console.log(`[BatchRenderer] Success: ${successCount}, Failed: ${failCount}`);
return results;
}