CoolFace
Apppublic

glitchlab/geoscatter-3d-raycast-geometry-sampler

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
script.js441 linesDownload Raw Back to root
1// Shared JavaScript for GeoScatter 3D Application2 3// DOM Elements4let canvasContainer;5let loadingOverlay;6let modelSelectBtn;7let modelDropdown;8let resetViewBtn;9let toggleGridBtn;10let rayCountSlider;11let rayValueSpan;12let visualizeRaysCheckbox;13let densityButtons;14let modeRadios;15let startSamplingBtn;16let clearRaysBtn;17let zoomInBtn;18let zoomOutBtn;19let activeRaysSpan;20 21// Sample Distribution Data (mock data)22const sampleData = {23    sphere: [65, 42, 38, 28, 17],24    cylinder: [42, 56, 45, 32, 15],25    organic: [38, 52, 48, 41, 22],26    torus: [28, 46, 52, 47, 31]27};28 29// Current Selected Model30let currentModel = 'sphere';31 32// Initialize when DOM is loaded33document.addEventListener('DOMContentLoaded', function() {34    // Get DOM Elements35    canvasContainer = document.getElementById('canvasContainer');36    loadingOverlay = document.getElementById('loadingOverlay');37    modelSelectBtn = document.getElementById('modelSelectBtn');38    modelDropdown = document.getElementById('modelDropdown');39    resetViewBtn = document.getElementById('resetView');40    toggleGridBtn = document.getElementById('toggleGrid');41    rayCountSlider = document.getElementById('rayCount');42    rayValueSpan = document.getElementById('rayValue');43    visualizeRaysCheckbox = document.getElementById('visualizeRays');44    densityButtons = document.querySelectorAll('.density-btn');45    modeRadios = document.querySelectorAll('input[name="mode"]');46    startSamplingBtn = document.getElementById('startSampling');47    clearRaysBtn = document.getElementById('clearRays');48    zoomInBtn = document.getElementById('zoomIn');49    zoomOutBtn = document.getElementById('zoomOut');50    activeRaysSpan = document.getElementById('activeRays');51    52    // Get coordinate display elements53    const coordX = document.getElementById('coordX');54    const coordY = document.getElementById('coordY');55    const coordZ = document.getElementById('coordZ');56    57    // Model Selection Logic58    const modelOptions = document.querySelectorAll('.model-option');59    modelOptions.forEach(option => {60        option.addEventListener('click', function() {61            const model = this.getAttribute('data-model');62            selectModel(model);63            64            // Close dropdown65            modelDropdown.style.display = 'none';66            67            // Update UI68            this.classList.add('bg-primary', 'text-white');69            this.classList.remove('hover:bg-gray-700');70            modelOptions.forEach(opt => {71                if (opt !== this) {72                    opt.classList.remove('bg-primary', 'text-white');73                    opt.classList.add('hover:bg-gray-700');74                }75            });76        });77    });78    79    // Toggle model dropdown80    if (modelSelectBtn) {81        modelSelectBtn.addEventListener('click', function() {82            modelDropdown.style.display = modelDropdown.style.display === 'block' ? 'none' : 'block';83        });84    }85    86    // Ray Count Slider87    if (rayCountSlider) {88        rayCountSlider.addEventListener('input', function() {89            const value = this.value;90            if (rayValueSpan) {91                rayValueSpan.textContent = value;92            }93            if (activeRaysSpan) {94                activeRaysSpan.textContent = value;95            }96            97            // Update visualization in scene (simulate)98            if (window.sceneManager) {99                window.sceneManager.updateRayCount(value);100            }101        });102    }103    104    // Density Buttons105    if (densityButtons) {106        densityButtons.forEach(btn => {107            btn.addEventListener('click', function() {108                const density = this.getAttribute('data-density');109                selectDensity(density);110                111                // Update UI112                densityButtons.forEach(b => {113                    b.classList.remove('bg-primary', 'text-white');114                    b.classList.add('bg-gray-100', 'dark:bg-gray-800', 'hover:bg-gray-200', 'dark:hover:bg-gray-700');115                });116                this.classList.add('bg-primary', 'text-white');117                this.classList.remove('hover:bg-gray-200', 'dark:hover:bg-gray-700');118            });119        });120    }121    122    // Algorithm Mode Selection123    if (modeRadios) {124        modeRadios.forEach(radio => {125            radio.addEventListener('change', function() {126                selectMode(this.value);127            });128        });129    }130    131    // Start Sampling Button132    if (startSamplingBtn) {133        startSamplingBtn.addEventListener('click', function() {134            startSampling();135        });136    }137    138    // Clear Rays Button139    if (clearRaysBtn) {140        clearRaysBtn.addEventListener('click', function() {141            clearRays();142        });143    }144    145    // Toggle Grid Button146    if (toggleGridBtn) {147        toggleGridBtn.addEventListener('click', function() {148            toggleGridVisibility();149        });150    }151    152    // Reset View Button153    if (resetViewBtn) {154        resetViewBtn.addEventListener('click', function() {155            resetCameraView();156        });157    }158    159    // Zoom Controls160    if (zoomInBtn) {161        zoomInBtn.addEventListener('click', function() {162            zoomCamera('in');163        });164    }165    166    if (zoomOutBtn) {167        zoomOutBtn.addEventListener('click', function() {168            zoomCamera('out');169        });170    }171    172    // Visualize Rays Checkbox173    if (visualizeRaysCheckbox) {174        visualizeRaysCheckbox.addEventListener('change', function() {175            toggleRayVisualization(this.checked);176        });177    }178    179    // Update sample chart based on model180    updateSampleChart(currentModel);181    182    // Hide loading overlay after 2 seconds (simulate loading)183    setTimeout(() => {184        if (loadingOverlay) {185            loadingOverlay.style.opacity = '0';186            setTimeout(() => {187                loadingOverlay.style.display = 'none';188            }, 300);189        }190    }, 1500);191    192    // Update coordinates display (simulate 3D interaction)193    if (coordX && coordY && coordZ) {194        simulateCameraMovement(coordX, coordY, coordZ);195    }196    197    // Event Listeners for Ray Visualization198    document.addEventListener('rayCreated', function(e) {199        if (e.detail && e.detail.count) {200            updateRayStats(e.detail.count);201        }202    });203});204 205// Model Selection Function206function selectModel(model) {207    currentModel = model;208    console.log(`Selected model: ${model}`);209    210    // Update UI211    const modelIcon = document.querySelector('#modelSelectBtn i');212    if (modelIcon) {213        modelIcon.setAttribute('data-feather', getModelIcon(model));214        feather.replace();215    }216    217    // Update sample chart218    updateSampleChart(model);219    220    // Update Three.js scene221    if (window.sceneManager) {222        window.sceneManager.changeModel(model);223    }224    225    // Dispatch event226    const event = new CustomEvent('modelChanged', { detail: { model: model } });227    document.dispatchEvent(event);228}229 230// Get icon name based on model231function getModelIcon(model) {232    const icons = {233        sphere: 'circle',234        cylinder: 'square',235        organic: 'hexagon',236        torus: 'triangle'237    };238    return icons[model] || 'circle';239}240 241// Density Selection Function242function selectDensity(density) {243    console.log(`Selected density: ${density}`);244    245    // Update UI246    const densityValueSpan = document.getElementById('densityValue');247    if (densityValueSpan) {248        densityValueSpan.textContent = density.charAt(0).toUpperCase() + density.slice(1);249    }250    251    // Dispatch event252    const event = new CustomEvent('densityChanged', { detail: { density: density } });253    document.dispatchEvent(event);254}255 256// Mode Selection Function257function selectMode(mode) {258    console.log(`Selected mode: ${mode}`);259    260    // Dispatch event261    const event = new CustomEvent('modeChanged', { detail: { mode: mode } });262    document.dispatchEvent(event);263}264 265// Start Sampling Function266function startSampling() {267    console.log('Starting outside-in ray sampling...');268    269    // Show visual feedback270    if (startSamplingBtn) {271        startSamplingBtn.innerHTML = '<i data-feather="loader" class="w-4 h-4 mr-2 animate-spin"></i>Sampling...';272        feather.replace();273        274        setTimeout(() => {275            startSamplingBtn.innerHTML = '<i data-feather="check" class="w-4 h-4 mr-2"></i>Sampling Complete';276            feather.replace();277        }, 2000);278    }279    280    // Dispatch event281    const event = new CustomEvent('samplingStarted');282    document.dispatchEvent(event);283}284 285// Clear Rays Function286function clearRays() {287    console.log('Clearing all ray visualizations...');288    289    // Dispatch event290    const event = new CustomEvent('raysCleared');291    document.dispatchEvent(event);292}293 294// Grid Visibility Toggle295function toggleGridVisibility() {296    console.log('Toggling grid visibility...');297    298    // Dispatch event299    const event = new CustomEvent('gridToggled');300    document.dispatchEvent(event);301}302 303// Camera Reset Function304function resetCameraView() {305    console.log('Resetting camera view...');306    307    // Dispatch event308    const event = new CustomEvent('cameraReset');309    document.dispatchEvent(event);310}311 312// Camera Zoom Function313function zoomCamera(direction) {314    console.log(`Zooming camera ${direction}...`);315    316    // Dispatch event317    const event = new CustomEvent('cameraZoomed', { detail: { direction: direction } });318    document.dispatchEvent(event);319}320 321// Ray Visualization Toggle322function toggleRayVisualization(visible) {323    console.log(`Ray visualization ${visible ? 'enabled' : 'disabled'}`);324    325    // Dispatch event326    const event = new CustomEvent('rayVisualizationToggled', { detail: { visible: visible } });327    document.dispatchEvent(event);328}329 330// Update Sample Chart Function331function updateSampleChart(model) {332    if (window.updateSampleChart) {333        window.updateSampleChart(model);334    }335}336 337// Simulate Camera Movement for Coordinates Display338function simulateCameraMovement(coordX, coordY, coordZ) {339    let x = 0, y = 0, z = 0;340    let increment = 0.01;341    342    function updateCoordinates() {343        x += (Math.random() - 0.5) * increment;344        y += (Math.random() - 0.5) * increment;345        z += (Math.random() - 0.5) * increment;346        347        // Apply some damping348        x *= 0.99;349        y *= 0.99;350        z *= 0.99;351        352        if (coordX) coordX.textContent = x.toFixed(2);353        if (coordY) coordY.textContent = y.toFixed(2);354        if (coordZ) coordZ.textContent = z.toFixed(2);355        356        requestAnimationFrame(updateCoordinates);357    }358    359    updateCoordinates();360}361 362// Update Ray Statistics363function updateRayStats(count) {364    const totalSamples = document.getElementById('totalSamples');365    const rayCollisions = document.getElementById('rayCollisions');366    const shellAccuracy = document.getElementById('shellAccuracy');367    const avgDistance = document.getElementById('avgDistance');368    369    if (totalSamples) {370        totalSamples.textContent = count * 4;371    }372    373    if (rayCollisions) {374        const collisions = Math.floor(count * 3.8);375        rayCollisions.textContent = collisions;376    }377    378    if (shellAccuracy) {379        const accuracy = 90 + Math.floor(Math.random() * 10);380        shellAccuracy.textContent = `${accuracy}.${Math.floor(Math.random() * 10)}%`;381    }382    383    if (avgDistance) {384        const distance = 0.8 + Math.random() * 0.4;385        avgDistance.textContent = `${distance.toFixed(2)}m`;386    }387}388 389// Add event listeners for custom events390document.addEventListener('modelChanged', function(e) {391    console.log(`Model changed to: ${e.detail.model}`);392});393 394document.addEventListener('densityChanged', function(e) {395    console.log(`Density changed to: ${e.detail.density}`);396});397 398document.addEventListener('modeChanged', function(e) {399    console.log(`Mode changed to: ${e.detail.mode}`);400});401 402document.addEventListener('samplingStarted', function() {403    console.log('Sampling process started.');404});405 406document.addEventListener('raysCleared', function() {407    console.log('All rays cleared.');408});409 410document.addEventListener('gridToggled', function() {411    console.log('Grid toggled.');412});413 414document.addEventListener('cameraReset', function() {415    console.log('Camera view reset.');416});417 418document.addEventListener('cameraZoomed', function(e) {419    console.log(`Camera zoomed ${e.detail.direction}`);420});421 422document.addEventListener('rayVisualizationToggled', function(e) {423    console.log(`Ray visualization toggled: ${e.detail.visible}`);424});425 426// Export Functions for Use in Other Scripts427window.updateSampleChart = function(model) {428    console.log(`Sample chart updated for model: ${model}`);429    430    // Update UI elements431    const sampleChartBars = document.querySelectorAll('#sampleChart div div');432    if (sampleChartBars.length >= 5) {433        const data = sampleData[model] || sampleData.sphere;434        for (let i = 0; i < data.length; i++) {435            const height = data[i];436            if (sampleChartBars[i]) {437                sampleChartBars[i].style.height = `${height * 0.2}px`;438            }439        }440    }441};