| |
|
|
| |
| 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; |
|
|
| |
| 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] |
| }; |
|
|
| |
| let currentModel = 'sphere'; |
|
|
| |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| 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'); |
| |
| |
| const coordX = document.getElementById('coordX'); |
| const coordY = document.getElementById('coordY'); |
| const coordZ = document.getElementById('coordZ'); |
| |
| |
| const modelOptions = document.querySelectorAll('.model-option'); |
| modelOptions.forEach(option => { |
| option.addEventListener('click', function() { |
| const model = this.getAttribute('data-model'); |
| selectModel(model); |
| |
| |
| modelDropdown.style.display = 'none'; |
| |
| |
| 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'); |
| } |
| }); |
| }); |
| }); |
| |
| |
| if (modelSelectBtn) { |
| modelSelectBtn.addEventListener('click', function() { |
| modelDropdown.style.display = modelDropdown.style.display === 'block' ? 'none' : 'block'; |
| }); |
| } |
| |
| |
| if (rayCountSlider) { |
| rayCountSlider.addEventListener('input', function() { |
| const value = this.value; |
| if (rayValueSpan) { |
| rayValueSpan.textContent = value; |
| } |
| if (activeRaysSpan) { |
| activeRaysSpan.textContent = value; |
| } |
| |
| |
| if (window.sceneManager) { |
| window.sceneManager.updateRayCount(value); |
| } |
| }); |
| } |
| |
| |
| if (densityButtons) { |
| densityButtons.forEach(btn => { |
| btn.addEventListener('click', function() { |
| const density = this.getAttribute('data-density'); |
| selectDensity(density); |
| |
| |
| 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'); |
| }); |
| }); |
| } |
| |
| |
| if (modeRadios) { |
| modeRadios.forEach(radio => { |
| radio.addEventListener('change', function() { |
| selectMode(this.value); |
| }); |
| }); |
| } |
| |
| |
| if (startSamplingBtn) { |
| startSamplingBtn.addEventListener('click', function() { |
| startSampling(); |
| }); |
| } |
| |
| |
| if (clearRaysBtn) { |
| clearRaysBtn.addEventListener('click', function() { |
| clearRays(); |
| }); |
| } |
| |
| |
| if (toggleGridBtn) { |
| toggleGridBtn.addEventListener('click', function() { |
| toggleGridVisibility(); |
| }); |
| } |
| |
| |
| if (resetViewBtn) { |
| resetViewBtn.addEventListener('click', function() { |
| resetCameraView(); |
| }); |
| } |
| |
| |
| if (zoomInBtn) { |
| zoomInBtn.addEventListener('click', function() { |
| zoomCamera('in'); |
| }); |
| } |
| |
| if (zoomOutBtn) { |
| zoomOutBtn.addEventListener('click', function() { |
| zoomCamera('out'); |
| }); |
| } |
| |
| |
| if (visualizeRaysCheckbox) { |
| visualizeRaysCheckbox.addEventListener('change', function() { |
| toggleRayVisualization(this.checked); |
| }); |
| } |
| |
| |
| updateSampleChart(currentModel); |
| |
| |
| setTimeout(() => { |
| if (loadingOverlay) { |
| loadingOverlay.style.opacity = '0'; |
| setTimeout(() => { |
| loadingOverlay.style.display = 'none'; |
| }, 300); |
| } |
| }, 1500); |
| |
| |
| if (coordX && coordY && coordZ) { |
| simulateCameraMovement(coordX, coordY, coordZ); |
| } |
| |
| |
| document.addEventListener('rayCreated', function(e) { |
| if (e.detail && e.detail.count) { |
| updateRayStats(e.detail.count); |
| } |
| }); |
| }); |
|
|
| |
| function selectModel(model) { |
| currentModel = model; |
| console.log(`Selected model: ${model}`); |
| |
| |
| const modelIcon = document.querySelector('#modelSelectBtn i'); |
| if (modelIcon) { |
| modelIcon.setAttribute('data-feather', getModelIcon(model)); |
| feather.replace(); |
| } |
| |
| |
| updateSampleChart(model); |
| |
| |
| if (window.sceneManager) { |
| window.sceneManager.changeModel(model); |
| } |
| |
| |
| const event = new CustomEvent('modelChanged', { detail: { model: model } }); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function getModelIcon(model) { |
| const icons = { |
| sphere: 'circle', |
| cylinder: 'square', |
| organic: 'hexagon', |
| torus: 'triangle' |
| }; |
| return icons[model] || 'circle'; |
| } |
|
|
| |
| function selectDensity(density) { |
| console.log(`Selected density: ${density}`); |
| |
| |
| const densityValueSpan = document.getElementById('densityValue'); |
| if (densityValueSpan) { |
| densityValueSpan.textContent = density.charAt(0).toUpperCase() + density.slice(1); |
| } |
| |
| |
| const event = new CustomEvent('densityChanged', { detail: { density: density } }); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function selectMode(mode) { |
| console.log(`Selected mode: ${mode}`); |
| |
| |
| const event = new CustomEvent('modeChanged', { detail: { mode: mode } }); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function startSampling() { |
| console.log('Starting outside-in ray sampling...'); |
| |
| |
| 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); |
| } |
| |
| |
| const event = new CustomEvent('samplingStarted'); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function clearRays() { |
| console.log('Clearing all ray visualizations...'); |
| |
| |
| const event = new CustomEvent('raysCleared'); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function toggleGridVisibility() { |
| console.log('Toggling grid visibility...'); |
| |
| |
| const event = new CustomEvent('gridToggled'); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function resetCameraView() { |
| console.log('Resetting camera view...'); |
| |
| |
| const event = new CustomEvent('cameraReset'); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function zoomCamera(direction) { |
| console.log(`Zooming camera ${direction}...`); |
| |
| |
| const event = new CustomEvent('cameraZoomed', { detail: { direction: direction } }); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function toggleRayVisualization(visible) { |
| console.log(`Ray visualization ${visible ? 'enabled' : 'disabled'}`); |
| |
| |
| const event = new CustomEvent('rayVisualizationToggled', { detail: { visible: visible } }); |
| document.dispatchEvent(event); |
| } |
|
|
| |
| function updateSampleChart(model) { |
| if (window.updateSampleChart) { |
| window.updateSampleChart(model); |
| } |
| } |
|
|
| |
| 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; |
| |
| |
| 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(); |
| } |
|
|
| |
| 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`; |
| } |
| } |
|
|
| |
| 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}`); |
| }); |
|
|
| |
| window.updateSampleChart = function(model) { |
| console.log(`Sample chart updated for model: ${model}`); |
| |
| |
| 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`; |
| } |
| } |
| } |
| }; |