glitchlab's picture
HTML/JavaScript application using Three.js for 3D rendering and geometry processing.
5db0090 verified
Raw
History Blame Contribute Delete
13.3 kB
// Shared JavaScript for GeoScatter 3D Application
// DOM Elements
let canvasContainer;
let loadingOverlay;
let modelSelectBtn;
let modelDropdown;
let resetViewBtn;
let toggleGridBtn;
let rayCountSlider;
let rayValueSpan;
let visualizeRaysCheckbox;
let densityButtons;
let modeRadios;
let startSamplingBtn;
let clearRaysBtn;
let zoomInBtn;
let zoomOutBtn;
let activeRaysSpan;
// Sample Distribution Data (mock data)
const sampleData = {
sphere: [65, 42, 38, 28, 17],
cylinder: [42, 56, 45, 32, 15],
organic: [38, 52, 48, 41, 22],
torus: [28, 46, 52, 47, 31]
};
// Current Selected Model
let currentModel = 'sphere';
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
// Get DOM Elements
canvasContainer = document.getElementById('canvasContainer');
loadingOverlay = document.getElementById('loadingOverlay');
modelSelectBtn = document.getElementById('modelSelectBtn');
modelDropdown = document.getElementById('modelDropdown');
resetViewBtn = document.getElementById('resetView');
toggleGridBtn = document.getElementById('toggleGrid');
rayCountSlider = document.getElementById('rayCount');
rayValueSpan = document.getElementById('rayValue');
visualizeRaysCheckbox = document.getElementById('visualizeRays');
densityButtons = document.querySelectorAll('.density-btn');
modeRadios = document.querySelectorAll('input[name="mode"]');
startSamplingBtn = document.getElementById('startSampling');
clearRaysBtn = document.getElementById('clearRays');
zoomInBtn = document.getElementById('zoomIn');
zoomOutBtn = document.getElementById('zoomOut');
activeRaysSpan = document.getElementById('activeRays');
// Get coordinate display elements
const coordX = document.getElementById('coordX');
const coordY = document.getElementById('coordY');
const coordZ = document.getElementById('coordZ');
// Model Selection Logic
const modelOptions = document.querySelectorAll('.model-option');
modelOptions.forEach(option => {
option.addEventListener('click', function() {
const model = this.getAttribute('data-model');
selectModel(model);
// Close dropdown
modelDropdown.style.display = 'none';
// Update UI
this.classList.add('bg-primary', 'text-white');
this.classList.remove('hover:bg-gray-700');
modelOptions.forEach(opt => {
if (opt !== this) {
opt.classList.remove('bg-primary', 'text-white');
opt.classList.add('hover:bg-gray-700');
}
});
});
});
// Toggle model dropdown
if (modelSelectBtn) {
modelSelectBtn.addEventListener('click', function() {
modelDropdown.style.display = modelDropdown.style.display === 'block' ? 'none' : 'block';
});
}
// Ray Count Slider
if (rayCountSlider) {
rayCountSlider.addEventListener('input', function() {
const value = this.value;
if (rayValueSpan) {
rayValueSpan.textContent = value;
}
if (activeRaysSpan) {
activeRaysSpan.textContent = value;
}
// Update visualization in scene (simulate)
if (window.sceneManager) {
window.sceneManager.updateRayCount(value);
}
});
}
// Density Buttons
if (densityButtons) {
densityButtons.forEach(btn => {
btn.addEventListener('click', function() {
const density = this.getAttribute('data-density');
selectDensity(density);
// Update UI
densityButtons.forEach(b => {
b.classList.remove('bg-primary', 'text-white');
b.classList.add('bg-gray-100', 'dark:bg-gray-800', 'hover:bg-gray-200', 'dark:hover:bg-gray-700');
});
this.classList.add('bg-primary', 'text-white');
this.classList.remove('hover:bg-gray-200', 'dark:hover:bg-gray-700');
});
});
}
// Algorithm Mode Selection
if (modeRadios) {
modeRadios.forEach(radio => {
radio.addEventListener('change', function() {
selectMode(this.value);
});
});
}
// Start Sampling Button
if (startSamplingBtn) {
startSamplingBtn.addEventListener('click', function() {
startSampling();
});
}
// Clear Rays Button
if (clearRaysBtn) {
clearRaysBtn.addEventListener('click', function() {
clearRays();
});
}
// Toggle Grid Button
if (toggleGridBtn) {
toggleGridBtn.addEventListener('click', function() {
toggleGridVisibility();
});
}
// Reset View Button
if (resetViewBtn) {
resetViewBtn.addEventListener('click', function() {
resetCameraView();
});
}
// Zoom Controls
if (zoomInBtn) {
zoomInBtn.addEventListener('click', function() {
zoomCamera('in');
});
}
if (zoomOutBtn) {
zoomOutBtn.addEventListener('click', function() {
zoomCamera('out');
});
}
// Visualize Rays Checkbox
if (visualizeRaysCheckbox) {
visualizeRaysCheckbox.addEventListener('change', function() {
toggleRayVisualization(this.checked);
});
}
// Update sample chart based on model
updateSampleChart(currentModel);
// Hide loading overlay after 2 seconds (simulate loading)
setTimeout(() => {
if (loadingOverlay) {
loadingOverlay.style.opacity = '0';
setTimeout(() => {
loadingOverlay.style.display = 'none';
}, 300);
}
}, 1500);
// Update coordinates display (simulate 3D interaction)
if (coordX && coordY && coordZ) {
simulateCameraMovement(coordX, coordY, coordZ);
}
// Event Listeners for Ray Visualization
document.addEventListener('rayCreated', function(e) {
if (e.detail && e.detail.count) {
updateRayStats(e.detail.count);
}
});
});
// Model Selection Function
function selectModel(model) {
currentModel = model;
console.log(`Selected model: ${model}`);
// Update UI
const modelIcon = document.querySelector('#modelSelectBtn i');
if (modelIcon) {
modelIcon.setAttribute('data-feather', getModelIcon(model));
feather.replace();
}
// Update sample chart
updateSampleChart(model);
// Update Three.js scene
if (window.sceneManager) {
window.sceneManager.changeModel(model);
}
// Dispatch event
const event = new CustomEvent('modelChanged', { detail: { model: model } });
document.dispatchEvent(event);
}
// Get icon name based on model
function getModelIcon(model) {
const icons = {
sphere: 'circle',
cylinder: 'square',
organic: 'hexagon',
torus: 'triangle'
};
return icons[model] || 'circle';
}
// Density Selection Function
function selectDensity(density) {
console.log(`Selected density: ${density}`);
// Update UI
const densityValueSpan = document.getElementById('densityValue');
if (densityValueSpan) {
densityValueSpan.textContent = density.charAt(0).toUpperCase() + density.slice(1);
}
// Dispatch event
const event = new CustomEvent('densityChanged', { detail: { density: density } });
document.dispatchEvent(event);
}
// Mode Selection Function
function selectMode(mode) {
console.log(`Selected mode: ${mode}`);
// Dispatch event
const event = new CustomEvent('modeChanged', { detail: { mode: mode } });
document.dispatchEvent(event);
}
// Start Sampling Function
function startSampling() {
console.log('Starting outside-in ray sampling...');
// Show visual feedback
if (startSamplingBtn) {
startSamplingBtn.innerHTML = '<i data-feather="loader" class="w-4 h-4 mr-2 animate-spin"></i>Sampling...';
feather.replace();
setTimeout(() => {
startSamplingBtn.innerHTML = '<i data-feather="check" class="w-4 h-4 mr-2"></i>Sampling Complete';
feather.replace();
}, 2000);
}
// Dispatch event
const event = new CustomEvent('samplingStarted');
document.dispatchEvent(event);
}
// Clear Rays Function
function clearRays() {
console.log('Clearing all ray visualizations...');
// Dispatch event
const event = new CustomEvent('raysCleared');
document.dispatchEvent(event);
}
// Grid Visibility Toggle
function toggleGridVisibility() {
console.log('Toggling grid visibility...');
// Dispatch event
const event = new CustomEvent('gridToggled');
document.dispatchEvent(event);
}
// Camera Reset Function
function resetCameraView() {
console.log('Resetting camera view...');
// Dispatch event
const event = new CustomEvent('cameraReset');
document.dispatchEvent(event);
}
// Camera Zoom Function
function zoomCamera(direction) {
console.log(`Zooming camera ${direction}...`);
// Dispatch event
const event = new CustomEvent('cameraZoomed', { detail: { direction: direction } });
document.dispatchEvent(event);
}
// Ray Visualization Toggle
function toggleRayVisualization(visible) {
console.log(`Ray visualization ${visible ? 'enabled' : 'disabled'}`);
// Dispatch event
const event = new CustomEvent('rayVisualizationToggled', { detail: { visible: visible } });
document.dispatchEvent(event);
}
// Update Sample Chart Function
function updateSampleChart(model) {
if (window.updateSampleChart) {
window.updateSampleChart(model);
}
}
// Simulate Camera Movement for Coordinates Display
function simulateCameraMovement(coordX, coordY, coordZ) {
let x = 0, y = 0, z = 0;
let increment = 0.01;
function updateCoordinates() {
x += (Math.random() - 0.5) * increment;
y += (Math.random() - 0.5) * increment;
z += (Math.random() - 0.5) * increment;
// Apply some damping
x *= 0.99;
y *= 0.99;
z *= 0.99;
if (coordX) coordX.textContent = x.toFixed(2);
if (coordY) coordY.textContent = y.toFixed(2);
if (coordZ) coordZ.textContent = z.toFixed(2);
requestAnimationFrame(updateCoordinates);
}
updateCoordinates();
}
// Update Ray Statistics
function updateRayStats(count) {
const totalSamples = document.getElementById('totalSamples');
const rayCollisions = document.getElementById('rayCollisions');
const shellAccuracy = document.getElementById('shellAccuracy');
const avgDistance = document.getElementById('avgDistance');
if (totalSamples) {
totalSamples.textContent = count * 4;
}
if (rayCollisions) {
const collisions = Math.floor(count * 3.8);
rayCollisions.textContent = collisions;
}
if (shellAccuracy) {
const accuracy = 90 + Math.floor(Math.random() * 10);
shellAccuracy.textContent = `${accuracy}.${Math.floor(Math.random() * 10)}%`;
}
if (avgDistance) {
const distance = 0.8 + Math.random() * 0.4;
avgDistance.textContent = `${distance.toFixed(2)}m`;
}
}
// Add event listeners for custom events
document.addEventListener('modelChanged', function(e) {
console.log(`Model changed to: ${e.detail.model}`);
});
document.addEventListener('densityChanged', function(e) {
console.log(`Density changed to: ${e.detail.density}`);
});
document.addEventListener('modeChanged', function(e) {
console.log(`Mode changed to: ${e.detail.mode}`);
});
document.addEventListener('samplingStarted', function() {
console.log('Sampling process started.');
});
document.addEventListener('raysCleared', function() {
console.log('All rays cleared.');
});
document.addEventListener('gridToggled', function() {
console.log('Grid toggled.');
});
document.addEventListener('cameraReset', function() {
console.log('Camera view reset.');
});
document.addEventListener('cameraZoomed', function(e) {
console.log(`Camera zoomed ${e.detail.direction}`);
});
document.addEventListener('rayVisualizationToggled', function(e) {
console.log(`Ray visualization toggled: ${e.detail.visible}`);
});
// Export Functions for Use in Other Scripts
window.updateSampleChart = function(model) {
console.log(`Sample chart updated for model: ${model}`);
// Update UI elements
const sampleChartBars = document.querySelectorAll('#sampleChart div div');
if (sampleChartBars.length >= 5) {
const data = sampleData[model] || sampleData.sphere;
for (let i = 0; i < data.length; i++) {
const height = data[i];
if (sampleChartBars[i]) {
sampleChartBars[i].style.height = `${height * 0.2}px`;
}
}
}
};