{"id":5523,"date":"2026-03-04T22:56:25","date_gmt":"2026-03-05T01:56:25","guid":{"rendered":"https:\/\/fisica2.fica.unsl.edu.ar\/?page_id=5523"},"modified":"2026-04-18T18:08:54","modified_gmt":"2026-04-18T21:08:54","slug":"ley_de_coulomb","status":"publish","type":"page","link":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/","title":{"rendered":"Ley_de_coulomb"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"5523\" class=\"elementor elementor-5523\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-fec4194 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"fec4194\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7c1c0ee\" data-id=\"7c1c0ee\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-90c2305 elementor-widget elementor-widget-html\" data-id=\"90c2305\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"es\">\r\n<head>\r\n    <meta charset=\"UTF-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n    <title>Ley de Coulomb - Simulacion 3D Interactiva<\/title>\r\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\r\n    <link href=\"https:\/\/fonts.googleapis.com\/css2?family=JetBrains+Mono:wght@400;600&family=Space+Grotesk:wght@400;500;700&display=swap\" rel=\"stylesheet\">\r\n    <style>\r\n        :root {\r\n            --bg-primary: #0a0e17;\r\n            --bg-secondary: #111827;\r\n            --bg-tertiary: #1a2332;\r\n            --text-primary: #e8edf5;\r\n            --text-secondary: #94a3b8;\r\n            --accent-cyan: #22d3ee;\r\n            --accent-red: #ef4444;\r\n            --accent-blue: #3b82f6;\r\n            --accent-green: #10b981;\r\n            --accent-yellow: #f59e0b;\r\n            --accent-orange: #f97316;\r\n            --border-color: #2d3748;\r\n        }\r\n        \r\n        * { margin: 0; padding: 0; box-sizing: border-box; }\r\n        \r\n        body {\r\n            font-family: 'Space Grotesk', sans-serif;\r\n            background: var(--bg-primary);\r\n            color: var(--text-primary);\r\n            overflow: hidden;\r\n        }\r\n        \r\n        .mono { font-family: 'JetBrains Mono', monospace; }\r\n        \r\n        #canvas-container {\r\n            position: fixed;\r\n            top: 0; left: 0;\r\n            width: 100%; height: 100%;\r\n            z-index: 1;\r\n        }\r\n        \r\n        .panel {\r\n            background: linear-gradient(145deg, rgba(17, 24, 39, 0.95), rgba(10, 14, 23, 0.98));\r\n            border: 1px solid var(--border-color);\r\n            backdrop-filter: blur(12px);\r\n            border-radius: 12px;\r\n        }\r\n        \r\n        .control-panel {\r\n            position: fixed; top: 20px; left: 20px;\r\n            width: 340px; max-height: calc(100vh - 40px);\r\n            overflow-y: auto; z-index: 100; padding: 20px;\r\n        }\r\n        \r\n        .control-panel::-webkit-scrollbar { width: 6px; }\r\n        .control-panel::-webkit-scrollbar-track { background: var(--bg-tertiary); border-radius: 3px; }\r\n        .control-panel::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 3px; }\r\n        \r\n        .info-panel {\r\n            position: fixed; top: 20px; right: 20px;\r\n            width: 380px; max-height: calc(100vh - 40px);\r\n            overflow-y: auto; z-index: 100; padding: 20px;\r\n        }\r\n        \r\n        .info-panel::-webkit-scrollbar { width: 6px; }\r\n        .info-panel::-webkit-scrollbar-track { background: var(--bg-tertiary); border-radius: 3px; }\r\n        .info-panel::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 3px; }\r\n        \r\n        .branding-header { display: flex; align-items: center; gap: 12px; padding-bottom: 16px; margin-bottom: 16px; border-bottom: 1px solid var(--border-color); }\r\n        .branding-logo-small { height: 28px; width: auto; object-fit: contain; background: rgba(255, 255, 255, 0.95); padding: 2px 4px; border-radius: 4px; }\r\n        .branding-text-box { display: flex; flex-direction: column; line-height: 1.2; }\r\n        .branding-inst { font-weight: 700; font-size: 15px; color: var(--text-primary); letter-spacing: 0.5px; }\r\n        .branding-year { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--accent-cyan); margin-top: 2px; }\r\n        \r\n        .section-title {\r\n            font-size: 11px; font-weight: 600; text-transform: uppercase;\r\n            letter-spacing: 1.5px; color: var(--text-secondary);\r\n            margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border-color);\r\n        }\r\n        \r\n        .charge-control { background: var(--bg-tertiary); border-radius: 10px; padding: 14px; margin-bottom: 12px; border: 1px solid transparent; transition: all 0.3s ease; }\r\n        .charge-control:hover { border-color: var(--border-color); }\r\n        .charge-control.positive { border-left: 3px solid var(--accent-red); }\r\n        .charge-control.negative { border-left: 3px solid var(--accent-blue); }\r\n        \r\n        .charge-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }\r\n        .charge-label { font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 8px; }\r\n        .charge-indicator { width: 12px; height: 12px; border-radius: 50%; }\r\n        .charge-indicator.positive { background: var(--accent-red); box-shadow: 0 0 8px var(--accent-red); }\r\n        .charge-indicator.negative { background: var(--accent-blue); box-shadow: 0 0 8px var(--accent-blue); }\r\n        .charge-value { font-family: 'JetBrains Mono', monospace; font-size: 13px; color: var(--accent-cyan); }\r\n        \r\n        \/* Estilos para las coordenadas *\/\r\n        .coords-display {\r\n            display: flex; gap: 8px; margin-bottom: 10px; margin-top: 4px;\r\n        }\r\n        .coord-box {\r\n            flex: 1; background: rgba(0,0,0,0.2); padding: 4px; border-radius: 4px; text-align: center;\r\n            font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--accent-yellow);\r\n        }\r\n        .coord-label { color: var(--text-secondary); font-size: 9px; display: block; margin-bottom: 2px; }\r\n        \r\n        .slider-container { margin-top: 8px; }\r\n        .slider-label { font-size: 11px; color: var(--text-secondary); margin-bottom: 4px; display: flex; justify-content: space-between; }\r\n        \r\n        input[type=\"range\"] {\r\n            width: 100%; height: 6px; border-radius: 3px;\r\n            background: var(--bg-primary); outline: none;\r\n            -webkit-appearance: none; cursor: pointer;\r\n        }\r\n        input[type=\"range\"]::-webkit-slider-thumb {\r\n            -webkit-appearance: none; width: 16px; height: 16px;\r\n            border-radius: 50%; background: var(--accent-cyan);\r\n            cursor: pointer; transition: transform 0.2s ease;\r\n        }\r\n        input[type=\"range\"]::-webkit-slider-thumb:hover { transform: scale(1.2); }\r\n        \r\n        select {\r\n            width: 100%; padding: 10px 14px; background: var(--bg-tertiary);\r\n            border: 1px solid var(--border-color); border-radius: 8px;\r\n            color: var(--text-primary); font-family: 'Space Grotesk', sans-serif;\r\n            font-size: 14px; cursor: pointer; outline: none; transition: all 0.3s ease;\r\n        }\r\n        select:hover { border-color: var(--accent-cyan); }\r\n        select:focus { border-color: var(--accent-cyan); box-shadow: 0 0 0 2px rgba(34, 211, 238, 0.2); }\r\n        \r\n        .force-card { background: var(--bg-tertiary); border-radius: 10px; padding: 14px; margin-bottom: 12px; }\r\n        .force-card-header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }\r\n        .force-card-title { font-weight: 600; font-size: 14px; }\r\n        \r\n        .force-vector-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 10px; margin: 4px 0; background: rgba(0,0,0,0.2); border-radius: 6px; font-size: 12px; }\r\n        .force-type-badge { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; border-radius: 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; }\r\n        .force-type-badge.attraction { background: rgba(16, 185, 129, 0.2); color: var(--accent-green); }\r\n        .force-type-badge.repulsion { background: rgba(249, 115, 22, 0.2); color: var(--accent-orange); }\r\n        \r\n        .net-force-card { background: linear-gradient(135deg, rgba(34, 211, 238, 0.15), rgba(34, 211, 238, 0.05)); border: 1px solid rgba(34, 211, 238, 0.3); }\r\n        .net-force-value { font-size: 18px; font-weight: 700; color: var(--accent-cyan); font-family: 'JetBrains Mono', monospace; }\r\n        \r\n        .vector-components { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 10px; }\r\n        .vector-comp { background: rgba(0,0,0,0.3); border-radius: 6px; padding: 8px; text-align: center; }\r\n        .vector-comp-label { font-size: 10px; color: var(--text-secondary); margin-bottom: 4px; }\r\n        .vector-comp-value { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--accent-cyan); }\r\n        \r\n        .distance-table { width: 100%; font-size: 11px; border-collapse: collapse; }\r\n        .distance-table th, .distance-table td { padding: 8px; text-align: center; border-bottom: 1px solid var(--border-color); }\r\n        .distance-table th { color: var(--text-secondary); font-weight: 500; }\r\n        .distance-table td { font-family: 'JetBrains Mono', monospace; color: var(--accent-yellow); }\r\n        \r\n        .formula-box { background: var(--bg-tertiary); border-radius: 8px; padding: 12px; margin-top: 12px; text-align: center; }\r\n        .formula { font-family: 'JetBrains Mono', monospace; font-size: 14px; color: var(--accent-cyan); }\r\n        \r\n        .instructions {\r\n            position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);\r\n            z-index: 100; padding: 10px 20px; font-size: 12px; color: var(--text-secondary);\r\n        }\r\n        \r\n        .legend { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px; }\r\n        .legend-item { display: flex; align-items: center; gap: 6px; font-size: 11px; }\r\n        .legend-color { width: 14px; height: 14px; border-radius: 3px; }\r\n        \r\n        .toggle-btn {\r\n            background: var(--bg-tertiary); border: 1px solid var(--border-color);\r\n            color: var(--text-primary); padding: 8px 12px; border-radius: 6px;\r\n            font-size: 11px; cursor: pointer; transition: all 0.3s ease;\r\n            margin-right: 6px; margin-bottom: 6px;\r\n        }\r\n        .toggle-btn:hover { border-color: var(--accent-cyan); }\r\n        .toggle-btn.active { background: rgba(34, 211, 238, 0.2); border-color: var(--accent-cyan); color: var(--accent-cyan); }\r\n        \r\n        @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }\r\n        .dragging-hint { animation: pulse 1.5s ease-in-out infinite; }\r\n        \r\n        @media (max-width: 768px) {\r\n            .control-panel, .info-panel { width: calc(100% - 40px); max-height: 40vh; }\r\n            .control-panel { top: auto; bottom: 20px; left: 20px; }\r\n            .info-panel { top: 20px; right: 20px; }\r\n        }\r\n    <\/style>\r\n<\/head>\r\n<body>\r\n    <div id=\"canvas-container\"><\/div>\r\n    \r\n    <!-- Panel de Control -->\r\n    <div class=\"panel control-panel\">\r\n        <div class=\"branding-header\">\r\n            <a href=\"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/FISAR_SIM\/\" target=\"_blank\"><img decoding=\"async\" src=\"FISAR_SIM_1\" alt=\"Logo FLUXAR\" class=\"branding-logo-small\" style=\"height:40px;\"><\/a>\r\n            <div class=\"branding-text-box\">\r\n                <span class=\"branding-inst\">FICA - UNSL<\/span>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <h2 style=\"font-size: 18px; color: var(--text-secondary); font-weight: 700; margin-bottom: 6px;\">Ley de Coulomb<\/h2>\r\n        <p style=\"font-size: 12px; color: var(--text-secondary); margin-bottom: 20px;\">Simulacion Interactiva 3D - Vectores de fuerza<\/p>\r\n        \r\n        <div class=\"section-title\">Configuracion<\/div>\r\n        \r\n        <div style=\"margin-bottom: 16px;\">\r\n            <label class=\"slider-label\" style=\"margin-bottom: 6px; display: block;\">Cantidad de cargas<\/label>\r\n            <select id=\"chargeCount\">\r\n                <option value=\"2\">2 Cargas<\/option>\r\n                <option value=\"3\">3 Cargas<\/option>\r\n                <option value=\"4\">4 Cargas<\/option>\r\n            <\/select>\r\n        <\/div>\r\n        \r\n        <div class=\"section-title\">Visualizacion de Fuerzas<\/div>\r\n        <div style=\"margin-bottom: 12px;\">\r\n            <button class=\"toggle-btn active\" id=\"toggleNetForce\">Fuerza Neta<\/button>\r\n            <button class=\"toggle-btn active\" id=\"toggleIndividual\">F. Individuales<\/button>\r\n            <button class=\"toggle-btn\" id=\"toggleLabels\">Etiquetas<\/button>\r\n        <\/div>\r\n        \r\n        <div class=\"section-title\">Cargas Puntuales<\/div>\r\n        <div id=\"chargeControls\"><\/div>\r\n        \r\n        <div class=\"formula-box\">\r\n            <div style=\"font-size: 11px; color: var(--text-secondary); margin-bottom: 4px;\">Ley de Coulomb (vectorial)<\/div>\r\n            <div class=\"formula\">F = k q1 q2 \/ r\u00b2 * r\u0302<\/div>\r\n            <div style=\"font-size: 10px; color: var(--text-secondary); margin-top: 6px;\">k = 8.99 x 10^9 N m^2\/C^2<\/div>\r\n        <\/div>\r\n        \r\n        <div class=\"legend\">\r\n            <div class=\"legend-item\"><div class=\"legend-color\" style=\"background: var(--accent-red);\"><\/div><span>Carga +<\/span><\/div>\r\n            <div class=\"legend-item\"><div class=\"legend-color\" style=\"background: var(--accent-blue);\"><\/div><span>Carga -<\/span><\/div>\r\n            <div class=\"legend-item\"><div class=\"legend-color\" style=\"background: var(--accent-cyan);\"><\/div><span>F. neta<\/span><\/div>\r\n            <div class=\"legend-item\"><div class=\"legend-color\" style=\"background: var(--accent-green);\"><\/div><span>Atraccion<\/span><\/div>\r\n            <div class=\"legend-item\"><div class=\"legend-color\" style=\"background: var(--accent-orange);\"><\/div><span>Repulsion<\/span><\/div>\r\n        <\/div>\r\n    <\/div>\r\n    \r\n    <!-- Panel de Informacion -->\r\n    <div class=\"panel info-panel\">\r\n        <div class=\"section-title\">Vectores de Fuerza sobre Cada Carga<\/div>\r\n        <div id=\"forcesInfo\"><\/div>\r\n        \r\n        <div class=\"section-title\" style=\"margin-top: 16px;\">Distancias entre Cargas<\/div>\r\n        <div id=\"distancesInfo\"><\/div>\r\n    <\/div>\r\n    \r\n    <!-- Instrucciones -->\r\n    <div class=\"panel instructions\">\r\n        <span class=\"dragging-hint\">Arrastra las cargas para moverlas<\/span> | \r\n        Rotar: click + arrastrar | Zoom: scroll gradual\r\n    <\/div>\r\n\r\n    <script type=\"importmap\">\r\n    {\r\n        \"imports\": {\r\n            \"three\": \"https:\/\/unpkg.com\/three@0.160.0\/build\/three.module.js\",\r\n            \"three\/addons\/\": \"https:\/\/unpkg.com\/three@0.160.0\/examples\/jsm\/\"\r\n        }\r\n    }\r\n    <\/script>\r\n\r\n    <script type=\"module\">\r\n        import * as THREE from 'three';\r\n        import { OrbitControls } from 'three\/addons\/controls\/OrbitControls.js';\r\n\r\n        \/\/ CONSTANTES FISICAS\r\n        const K_COULOMB = 8.99e9;\r\n        const FORCE_ARROW_SCALE = 0.00004;\r\n        const FORCE_COLORS = {\r\n            net: 0x22d3ee,\r\n            attraction: 0x10b981,\r\n            repulsion: 0xf97316\r\n        };\r\n        \r\n        \/\/ VARIABLES GLOBALES\r\n        let scene, camera, renderer, controls;\r\n        let charges = [];\r\n        let gridHelper;\r\n        let raycaster, mouse;\r\n        let selectedCharge = null;\r\n        let isDragging = false;\r\n        let dragPlane = new THREE.Plane();\r\n        let intersection = new THREE.Vector3();\r\n        let offset = new THREE.Vector3();\r\n        \r\n        let showNetForce = true;\r\n        let showIndividual = true;\r\n        let showLabels = false;\r\n        \r\n        \/\/ INICIALIZACION\r\n        function init() {\r\n            scene = new THREE.Scene();\r\n            scene.background = new THREE.Color(0x0a0e17);\r\n            scene.fog = new THREE.Fog(0x0a0e17, 40, 100);\r\n            \r\n            camera = new THREE.PerspectiveCamera(55, window.innerWidth \/ window.innerHeight, 0.1, 1000);\r\n            camera.position.set(18, 14, 18);\r\n            \r\n            renderer = new THREE.WebGLRenderer({ antialias: true });\r\n            renderer.setSize(window.innerWidth, window.innerHeight);\r\n            renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\r\n            renderer.shadowMap.enabled = true;\r\n            renderer.shadowMap.type = THREE.PCFSoftShadowMap;\r\n            document.getElementById('canvas-container').appendChild(renderer.domElement);\r\n            \r\n            \/\/ --- CONFIGURACION DE CONTROLES ---\r\n            controls = new OrbitControls(camera, renderer.domElement);\r\n            controls.enableDamping = true;\r\n            controls.dampingFactor = 0.05;\r\n            controls.enableZoom = false; \/\/ Desactivado para usar zoom manual\r\n            controls.enablePan = false;  \/\/ Desactivado para evitar desplazamientos\r\n            controls.rotateSpeed = 0.7;\r\n            \/\/ ----------------------------------\r\n            \r\n            raycaster = new THREE.Raycaster();\r\n            mouse = new THREE.Vector2();\r\n            \r\n            setupLighting();\r\n            setupGrid();\r\n            initCharges(2);\r\n            setupEventListeners();\r\n            animate();\r\n        }\r\n        \r\n        \/\/ --- NUEVA FUNCION DE ZOOM GRADUAL MANUAL ---\r\n        function setupCustomZoom() {\r\n            const canvas = renderer.domElement;\r\n            \r\n            canvas.addEventListener('wheel', (event) => {\r\n                event.preventDefault(); \r\n                \r\n                const zoomSpeed = 0.002; \r\n                const delta = event.deltaY * zoomSpeed;\r\n                \r\n                const direction = new THREE.Vector3();\r\n                camera.getWorldDirection(direction);\r\n                \r\n                camera.position.addScaledVector(direction, -delta * camera.position.length());\r\n                \r\n            }, { passive: false });\r\n        }\r\n        \/\/ --------------------------------------------\r\n        \r\n        function setupLighting() {\r\n            const ambientLight = new THREE.AmbientLight(0x404060, 0.5);\r\n            scene.add(ambientLight);\r\n            \r\n            const mainLight = new THREE.DirectionalLight(0xffffff, 0.9);\r\n            mainLight.position.set(15, 25, 15);\r\n            mainLight.castShadow = true;\r\n            mainLight.shadow.mapSize.width = 2048;\r\n            mainLight.shadow.mapSize.height = 2048;\r\n            scene.add(mainLight);\r\n            \r\n            const fillLight = new THREE.DirectionalLight(0x22d3ee, 0.2);\r\n            fillLight.position.set(-15, 10, -15);\r\n            scene.add(fillLight);\r\n        }\r\n        \r\n        function setupGrid() {\r\n            gridHelper = new THREE.GridHelper(40, 40, 0x1e293b, 0x0f172a);\r\n            gridHelper.position.y = -0.01;\r\n            scene.add(gridHelper);\r\n            \r\n            const planeGeometry = new THREE.PlaneGeometry(50, 50);\r\n            const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x0a0e17, transparent: true, opacity: 0.9, roughness: 0.95, metalness: 0.05 });\r\n            const plane = new THREE.Mesh(planeGeometry, planeMaterial);\r\n            plane.rotation.x = -Math.PI \/ 2;\r\n            plane.position.y = -0.02;\r\n            plane.receiveShadow = true;\r\n            scene.add(plane);\r\n            createAxes();\r\n        }\r\n        \r\n        function createAxes() {\r\n            const axisLength = 15;\r\n            createAxisLine(new THREE.Vector3(-axisLength, 0, 0), new THREE.Vector3(axisLength, 0, 0), 0xef4444);\r\n            createAxisLine(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, axisLength * 0.6, 0), 0x10b981);\r\n            createAxisLine(new THREE.Vector3(0, 0, -axisLength), new THREE.Vector3(0, 0, axisLength), 0x3b82f6);\r\n        }\r\n        \r\n        function createAxisLine(start, end, color) {\r\n            const material = new THREE.LineBasicMaterial({ color: color, transparent: true, opacity: 0.4 });\r\n            const geometry = new THREE.BufferGeometry().setFromPoints([start, end]);\r\n            const line = new THREE.Line(geometry, material);\r\n            scene.add(line);\r\n        }\r\n        \r\n        function initCharges(count) {\r\n            clearCharges();\r\n            const configs = {\r\n                2: [{ position: new THREE.Vector3(-6, 0, 0), charge: 2e-6 }, { position: new THREE.Vector3(6, 0, 0), charge: -2e-6 }],\r\n                3: [{ position: new THREE.Vector3(-5, 0, -4), charge: 3e-6 }, { position: new THREE.Vector3(5, 0, -4), charge: 2e-6 }, { position: new THREE.Vector3(0, 0, 5), charge: -2e-6 }],\r\n                4: [{ position: new THREE.Vector3(-5, 0, -5), charge: 3e-6 }, { position: new THREE.Vector3(5, 0, -5), charge: -2e-6 }, { position: new THREE.Vector3(5, 0, 5), charge: 2e-6 }, { position: new THREE.Vector3(-5, 0, 5), charge: -3e-6 }]\r\n            };\r\n            const config = configs[count];\r\n            for (let i = 0; i < count; i++) { createCharge(i, config[i].position, config[i].charge); }\r\n            createChargeControls(count); \/\/ Primero crear controles\r\n            updateForces(); \/\/ Luego actualizar f\u00edsica\r\n            updateChargeCoords(); \/\/ Finalmente actualizar coords iniciales\r\n        }\r\n        \r\n        function createCharge(index, position, chargeValue) {\r\n            const isPositive = chargeValue >= 0;\r\n            const magnitude = Math.abs(chargeValue);\r\n            const baseRadius = 0.9;\r\n            const radius = baseRadius + magnitude * 1e6 * 0.25;\r\n            const geometry = new THREE.SphereGeometry(radius, 32, 32);\r\n            const material = new THREE.MeshStandardMaterial({ color: isPositive ? 0xef4444 : 0x3b82f6, emissive: isPositive ? 0xef4444 : 0x3b82f6, emissiveIntensity: 0.25, roughness: 0.25, metalness: 0.75 });\r\n            const mesh = new THREE.Mesh(geometry, material);\r\n            mesh.position.copy(position);\r\n            mesh.castShadow = true;\r\n            mesh.receiveShadow = true;\r\n            \r\n            const glowGeometry = new THREE.SphereGeometry(radius * 1.6, 32, 32);\r\n            const glowMaterial = new THREE.MeshBasicMaterial({ color: isPositive ? 0xef4444 : 0x3b82f6, transparent: true, opacity: 0.12, side: THREE.BackSide });\r\n            const glow = new THREE.Mesh(glowGeometry, glowMaterial);\r\n            mesh.add(glow);\r\n            \r\n            const labelSprite = createTextLabel(`q${index + 1}`, '#ffffff');\r\n            labelSprite.position.y = radius + 1.2;\r\n            mesh.add(labelSprite);\r\n            scene.add(mesh);\r\n            \r\n            charges.push({ index: index, mesh: mesh, charge: chargeValue, radius: radius, netForce: new THREE.Vector3(), individualForces: [], arrowGroup: new THREE.Group(), netArrowGroup: new THREE.Group(), labelGroup: new THREE.Group() });\r\n            scene.add(charges[charges.length - 1].arrowGroup);\r\n            scene.add(charges[charges.length - 1].netArrowGroup);\r\n            scene.add(charges[charges.length - 1].labelGroup);\r\n        }\r\n        \r\n        function createTextLabel(text, color) {\r\n            const canvas = document.createElement('canvas');\r\n            const context = canvas.getContext('2d');\r\n            canvas.width = 256; canvas.height = 128;\r\n            context.fillStyle = 'transparent'; context.fillRect(0, 0, canvas.width, canvas.height);\r\n            context.font = 'bold 48px Space Grotesk'; context.fillStyle = color; context.textAlign = 'center'; context.textBaseline = 'middle';\r\n            context.fillText(text, canvas.width \/ 2, canvas.height \/ 2);\r\n            const texture = new THREE.CanvasTexture(canvas);\r\n            const material = new THREE.SpriteMaterial({ map: texture, transparent: true });\r\n            const sprite = new THREE.Sprite(material);\r\n            sprite.scale.set(2, 1, 1);\r\n            return sprite;\r\n        }\r\n        \r\n        function clearCharges() {\r\n            for (const charge of charges) {\r\n                scene.remove(charge.mesh); scene.remove(charge.arrowGroup); scene.remove(charge.netArrowGroup); scene.remove(charge.labelGroup);\r\n                charge.mesh.geometry.dispose(); charge.mesh.material.dispose();\r\n            }\r\n            charges = [];\r\n        }\r\n        \r\n        function calculateForces() {\r\n            const n = charges.length;\r\n            for (const charge of charges) { charge.netForce.set(0, 0, 0); charge.individualForces = []; }\r\n            for (let i = 0; i < n; i++) {\r\n                for (let j = i + 1; j < n; j++) {\r\n                    const q1 = charges[i]; const q2 = charges[j];\r\n                    const r12 = new THREE.Vector3().subVectors(q2.mesh.position, q1.mesh.position);\r\n                    const distance = r12.length();\r\n                    if (distance < 0.5) continue;\r\n                    const r12Unit = r12.clone().normalize();\r\n                    const forceMagnitude = K_COULOMB * Math.abs(q1.charge) * Math.abs(q2.charge) \/ (distance * distance);\r\n                    const sameSign = (q1.charge * q2.charge) > 0;\r\n                    let forceOn1;\r\n                    if (sameSign) forceOn1 = r12Unit.clone().multiplyScalar(-forceMagnitude);\r\n                    else forceOn1 = r12Unit.clone().multiplyScalar(forceMagnitude);\r\n                    const forceOn2 = forceOn1.clone().multiplyScalar(-1);\r\n                    q1.netForce.add(forceOn1); q2.netForce.add(forceOn2);\r\n                    q1.individualForces.push({ from: j, force: forceOn1.clone(), isAttraction: !sameSign, magnitude: forceMagnitude });\r\n                    q2.individualForces.push({ from: i, force: forceOn2.clone(), isAttraction: !sameSign, magnitude: forceMagnitude });\r\n                }\r\n            }\r\n        }\r\n        \r\n        function createArrow(origin, direction, length, color, headLength, headWidth) {\r\n            const group = new THREE.Group();\r\n            const safeLength = Number.isFinite(length) ? Math.max(0.1, Math.min(length, 15)) : 1;\r\n            const safeHeadLength = Number.isFinite(headLength) ? Math.max(0.05, headLength) : 0.2;\r\n            const safeHeadWidth = Number.isFinite(headWidth) ? Math.max(0.03, headWidth) : 0.15;\r\n            if (direction.lengthSq() < 0.0001) return group;\r\n            const dir = direction.clone().normalize();\r\n            const shaftLength = safeLength - safeHeadLength;\r\n            const shaftGeometry = new THREE.CylinderGeometry(0.06, 0.06, Math.max(0.1, shaftLength), 8);\r\n            const shaftMaterial = new THREE.MeshStandardMaterial({ color: color, emissive: color, emissiveIntensity: 0.3, roughness: 0.4, metalness: 0.6 });\r\n            const shaft = new THREE.Mesh(shaftGeometry, shaftMaterial);\r\n            shaft.position.y = shaftLength \/ 2;\r\n            group.add(shaft);\r\n            const headGeometry = new THREE.ConeGeometry(safeHeadWidth, safeHeadLength, 12);\r\n            const headMaterial = new THREE.MeshStandardMaterial({ color: color, emissive: color, emissiveIntensity: 0.4, roughness: 0.3, metalness: 0.7 });\r\n            const head = new THREE.Mesh(headGeometry, headMaterial);\r\n            head.position.y = shaftLength + safeHeadLength \/ 2;\r\n            group.add(head);\r\n            group.position.copy(origin);\r\n            const up = new THREE.Vector3(0, 1, 0);\r\n            const quaternion = new THREE.Quaternion();\r\n            quaternion.setFromUnitVectors(up, dir);\r\n            group.setRotationFromQuaternion(quaternion);\r\n            return group;\r\n        }\r\n        \r\n        function updateForces() {\r\n            calculateForces();\r\n            for (const charge of charges) { charge.arrowGroup.clear(); charge.netArrowGroup.clear(); charge.labelGroup.clear(); }\r\n            for (const charge of charges) {\r\n                const pos = charge.mesh.position.clone();\r\n                const chargeRadius = charge.radius;\r\n                if (showIndividual) {\r\n                    for (const indForce of charge.individualForces) {\r\n                        const forceDir = indForce.force.clone();\r\n                        const forceMag = forceDir.length();\r\n                        if (forceMag < 1e-10) continue;\r\n                        const scaledDir = forceDir.clone().multiplyScalar(FORCE_ARROW_SCALE);\r\n                        let arrowLength = scaledDir.length();\r\n                        arrowLength = Math.min(Math.max(arrowLength, 1), 12);\r\n                        const color = indForce.isAttraction ? FORCE_COLORS.attraction : FORCE_COLORS.repulsion;\r\n                        const arrowOrigin = pos.clone().add(forceDir.clone().normalize().multiplyScalar(chargeRadius * 1.1));\r\n                        const arrow = createArrow(arrowOrigin, forceDir.clone().normalize(), arrowLength, color, arrowLength * 0.2, arrowLength * 0.12);\r\n                        charge.arrowGroup.add(arrow);\r\n                        if (showLabels) {\r\n                            const labelPos = arrowOrigin.clone().add(forceDir.clone().normalize().multiplyScalar(arrowLength + 0.8));\r\n                            const label = createForceLabelSimple(forceMag, labelPos, color);\r\n                            charge.labelGroup.add(label);\r\n                        }\r\n                    }\r\n                }\r\n                if (showNetForce) {\r\n                    const netDir = charge.netForce.clone();\r\n                    const netMag = netDir.length();\r\n                    if (netMag > 1e-10) {\r\n                        const scaledNet = netDir.clone().multiplyScalar(FORCE_ARROW_SCALE);\r\n                        let netLength = scaledNet.length();\r\n                        netLength = Math.min(Math.max(netLength, 1.5), 14);\r\n                        const arrowOrigin = pos.clone().add(netDir.clone().normalize().multiplyScalar(chargeRadius * 1.1));\r\n                        const arrow = createArrow(arrowOrigin, netDir.clone().normalize(), netLength, FORCE_COLORS.net, netLength * 0.25, netLength * 0.15);\r\n                        charge.netArrowGroup.add(arrow);\r\n                        if (showLabels) {\r\n                            const labelPos = arrowOrigin.clone().add(netDir.clone().normalize().multiplyScalar(netLength + 1));\r\n                            const label = createForceLabelSimple(netMag, labelPos, FORCE_COLORS.net);\r\n                            charge.labelGroup.add(label);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            updateInfoPanel();\r\n        }\r\n        \r\n        \/\/ --- NUEVA FUNCION PARA ACTUALIZAR COORDENADAS EN UI ---\r\n        function updateChargeCoords() {\r\n            for (const charge of charges) {\r\n                const pos = charge.mesh.position;\r\n                const elX = document.getElementById(`coord-x-${charge.index}`);\r\n                const elY = document.getElementById(`coord-y-${charge.index}`);\r\n                const elZ = document.getElementById(`coord-z-${charge.index}`);\r\n                \r\n                if(elX) elX.innerText = pos.x.toFixed(2);\r\n                if(elY) elY.innerText = pos.y.toFixed(2);\r\n                if(elZ) elZ.innerText = pos.z.toFixed(2);\r\n            }\r\n        }\r\n        \/\/ -----------------------------------------------------\r\n        \r\n        \/\/ --- MEJORA: ETIQUETAS SIN FONDO Y M\u00c1S PEQUE\u00d1AS ---\r\n        function createForceLabelSimple(magnitude, position, colorHex) {\r\n            const canvas = document.createElement('canvas');\r\n            const context = canvas.getContext('2d');\r\n            \r\n            \/\/ Reducimos tama\u00f1o del canvas\r\n            canvas.width = 200; \r\n            canvas.height = 60;\r\n            \r\n            const text = magnitude.toExponential(1) + ' N';\r\n            \r\n            \/\/ Estilo de texto\r\n            context.font = 'bold 24px JetBrains Mono'; \/\/ Fuente m\u00e1s peque\u00f1a\r\n            context.textAlign = 'center'; \r\n            context.textBaseline = 'middle';\r\n            \r\n            \/\/ 1. Dibujar Borde (Stroke) para contraste\r\n            context.strokeStyle = 'rgba(0, 0, 0, 0.8)'; \/\/ Negro semitransparente\r\n            context.lineWidth = 4;\r\n            context.strokeText(text, canvas.width \/ 2, canvas.height \/ 2);\r\n            \r\n            \/\/ 2. Dibujar Relleno\r\n            \/\/ Convertir hex a string CSS\r\n            const colorStr = '#' + colorHex.toString(16).padStart(6, '0');\r\n            context.fillStyle = colorStr;\r\n            context.fillText(text, canvas.width \/ 2, canvas.height \/ 2);\r\n            \r\n            const texture = new THREE.CanvasTexture(canvas);\r\n            const material = new THREE.SpriteMaterial({ \r\n                map: texture, \r\n                transparent: true, \r\n                depthTest: false \/\/ Asegura que no se oculte detr\u00e1s de objetos\r\n            });\r\n            \r\n            const sprite = new THREE.Sprite(material);\r\n            \/\/ Escala ajustada al nuevo tama\u00f1o\r\n            sprite.scale.set(1.5, 0.45, 1); \r\n            sprite.position.copy(position);\r\n            \r\n            return sprite;\r\n        }\r\n        \/\/ ------------------------------------------------\r\n        \r\n        function createChargeControls(count) {\r\n            const container = document.getElementById('chargeControls');\r\n            container.innerHTML = '';\r\n            for (let i = 0; i < count; i++) {\r\n                const charge = charges[i];\r\n                const isPositive = charge.charge >= 0;\r\n                const chargeValueMicro = charge.charge * 1e6;\r\n                \r\n                const controlDiv = document.createElement('div');\r\n                controlDiv.className = `charge-control ${isPositive ? 'positive' : 'negative'}`;\r\n                controlDiv.id = `charge-control-${i}`;\r\n                controlDiv.innerHTML = `\r\n                    <div class=\"charge-header\">\r\n                        <div class=\"charge-label\">\r\n                            <div class=\"charge-indicator ${isPositive ? 'positive' : 'negative'}\"><\/div>\r\n                            Carga q${i + 1}\r\n                        <\/div>\r\n                        <div class=\"charge-value\" id=\"charge-display-${i}\">${chargeValueMicro >= 0 ? '+' : ''}${chargeValueMicro.toFixed(1)} uC<\/div>\r\n                    <\/div>\r\n                    \r\n                    <!-- COORDENADAS -->\r\n                    <div class=\"coords-display\">\r\n                        <div class=\"coord-box\"><span class=\"coord-label\">X<\/span><span id=\"coord-x-${i}\">${charge.mesh.position.x.toFixed(2)}<\/span><\/div>\r\n                        <div class=\"coord-box\"><span class=\"coord-label\">Y<\/span><span id=\"coord-y-${i}\">${charge.mesh.position.y.toFixed(2)}<\/span><\/div>\r\n                        <div class=\"coord-box\"><span class=\"coord-label\">Z<\/span><span id=\"coord-z-${i}\">${charge.mesh.position.z.toFixed(2)}<\/span><\/div>\r\n                    <\/div>\r\n                    \r\n                    <div class=\"slider-container\">\r\n                        <div class=\"slider-label\">\r\n                            <span>Valor de carga<\/span>\r\n                            <span id=\"slider-value-${i}\">${chargeValueMicro.toFixed(1)} uC<\/span>\r\n                        <\/div>\r\n                        <input type=\"range\" id=\"charge-slider-${i}\" min=\"-5\" max=\"5\" step=\"0.1\" value=\"${chargeValueMicro}\">\r\n                    <\/div>`;\r\n                container.appendChild(controlDiv);\r\n                \r\n                const slider = document.getElementById(`charge-slider-${i}`);\r\n                slider.addEventListener('input', (e) => { updateChargeValue(i, parseFloat(e.target.value) * 1e-6); });\r\n            }\r\n        }\r\n        \r\n        function updateChargeValue(index, newValue) {\r\n            if (index >= charges.length) return;\r\n            const charge = charges[index];\r\n            charge.charge = newValue;\r\n            const isPositive = newValue >= 0;\r\n            const magnitude = Math.abs(newValue);\r\n            charge.mesh.material.color.setHex(isPositive ? 0xef4444 : 0x3b82f6);\r\n            charge.mesh.material.emissive.setHex(isPositive ? 0xef4444 : 0x3b82f6);\r\n            const baseRadius = 0.9;\r\n            const newRadius = baseRadius + magnitude * 1e6 * 0.25;\r\n            charge.mesh.scale.setScalar(newRadius \/ charge.radius);\r\n            const glow = charge.mesh.children[0];\r\n            if (glow && glow.material) glow.material.color.setHex(isPositive ? 0xef4444 : 0x3b82f6);\r\n            const displayValue = (newValue * 1e6).toFixed(1);\r\n            const displayEl = document.getElementById(`charge-display-${index}`);\r\n            const sliderValueEl = document.getElementById(`slider-value-${index}`);\r\n            const controlEl = document.getElementById(`charge-control-${index}`);\r\n            if (displayEl) displayEl.textContent = `${displayValue >= 0 ? '+' : ''}${displayValue} uC`;\r\n            if (sliderValueEl) sliderValueEl.textContent = `${displayValue} uC`;\r\n            if (controlEl) {\r\n                controlEl.classList.remove('positive', 'negative');\r\n                controlEl.classList.add(isPositive ? 'positive' : 'negative');\r\n                const indicator = controlEl.querySelector('.charge-indicator');\r\n                if (indicator) { indicator.classList.remove('positive', 'negative'); indicator.classList.add(isPositive ? 'positive' : 'negative'); }\r\n            }\r\n            updateForces();\r\n        }\r\n        \r\n        function updateInfoPanel() { updateForcesInfo(); updateDistancesInfo(); }\r\n        \r\n        function updateForcesInfo() {\r\n            const container = document.getElementById('forcesInfo');\r\n            if (!container) return;\r\n            let html = '';\r\n            for (const charge of charges) {\r\n                const netMag = charge.netForce.length();\r\n                const isPositive = charge.charge >= 0;\r\n                const chargeColor = isPositive ? '#ef4444' : '#3b82f6';\r\n                html += `<div class=\"force-card\"><div class=\"force-card-header\"><div class=\"charge-indicator ${isPositive ? 'positive' : 'negative'}\"><\/div><div class=\"force-card-title\" style=\"color: ${chargeColor}\">Carga q${charge.index + 1} = ${(charge.charge * 1e6).toFixed(1)} uC<\/div><\/div>`;\r\n                if (charge.individualForces.length > 0) {\r\n                    html += `<div style=\"font-size: 11px; color: var(--text-secondary); margin-bottom: 8px;\">Fuerzas individuales:<\/div>`;\r\n                    for (const indForce of charge.individualForces) {\r\n                        const fMag = indForce.magnitude;\r\n                        const typeClass = indForce.isAttraction ? 'attraction' : 'repulsion';\r\n                        const typeText = indForce.isAttraction ? 'Atraccion' : 'Repulsion';\r\n                        const typeColor = indForce.isAttraction ? 'var(--accent-green)' : 'var(--accent-orange)';\r\n                        const fDir = indForce.force.clone().normalize();\r\n                        const theta = Math.acos(fDir.y) * 180 \/ Math.PI;\r\n                        const phi = Math.atan2(fDir.z, fDir.x) * 180 \/ Math.PI;\r\n                        html += `<div class=\"force-vector-row\"><div><span class=\"force-type-badge ${typeClass}\">${typeText}<\/span><span style=\"margin-left: 6px;\">por q${indForce.from + 1}<\/span><\/div><div style=\"font-family: 'JetBrains Mono', monospace; color: ${typeColor}\">${fMag.toExponential(3)} N<\/div><\/div><div style=\"font-size: 10px; color: var(--text-secondary); padding: 4px 10px 8px;\">Direccion: theta=${theta.toFixed(1)} deg, phi=${phi.toFixed(1)} deg<\/div>`;\r\n                    }\r\n                }\r\n                const netDir = charge.netForce.clone().normalize();\r\n                const netTheta = netMag > 1e-10 ? Math.acos(netDir.y) * 180 \/ Math.PI : 0;\r\n                const netPhi = netMag > 1e-10 ? Math.atan2(netDir.z, netDir.x) * 180 \/ Math.PI : 0;\r\n                html += `<div class=\"force-card net-force-card\" style=\"margin-top: 12px;\"><div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;\"><span style=\"font-weight: 600; font-size: 13px;\">FUERZA NETA<\/span><span class=\"net-force-value\">${netMag.toExponential(3)} N<\/span><\/div><div class=\"vector-components\"><div class=\"vector-comp\"><div class=\"vector-comp-label\">Fx<\/div><div class=\"vector-comp-value\">${charge.netForce.x.toExponential(2)}<\/div><\/div><div class=\"vector-comp\"><div class=\"vector-comp-label\">Fy<\/div><div class=\"vector-comp-value\">${charge.netForce.y.toExponential(2)}<\/div><\/div><div class=\"vector-comp\"><div class=\"vector-comp-label\">Fz<\/div><div class=\"vector-comp-value\">${charge.netForce.z.toExponential(2)}<\/div><\/div><\/div><div style=\"font-size: 11px; color: var(--text-secondary); margin-top: 8px; text-align: center;\">Direccion: theta=${netTheta.toFixed(1)} deg, phi=${netPhi.toFixed(1)} deg<\/div><\/div><\/div>`;\r\n            }\r\n            container.innerHTML = html;\r\n        }\r\n        \r\n        function updateDistancesInfo() {\r\n            const container = document.getElementById('distancesInfo');\r\n            if (!container) return;\r\n            const n = charges.length;\r\n            let html = '<table class=\"distance-table\"><thead><tr><th>Par<\/th><th>Distancia (m)<\/th><th>Tipo<\/th><\/tr><\/thead><tbody>';\r\n            for (let i = 0; i < n; i++) {\r\n                for (let j = i + 1; j < n; j++) {\r\n                    const distance = charges[i].mesh.position.distanceTo(charges[j].mesh.position);\r\n                    const sameSign = (charges[i].charge * charges[j].charge) > 0;\r\n                    const typeText = sameSign ? 'Repulsion' : 'Atraccion';\r\n                    const typeColor = sameSign ? 'var(--accent-orange)' : 'var(--accent-green)';\r\n                    html += `<tr><td>q${i + 1} - q${j + 1}<\/td><td>${distance.toFixed(3)}<\/td><td style=\"color: ${typeColor}\">${typeText}<\/td><\/tr>`;\r\n                }\r\n            }\r\n            html += '<\/tbody><\/table>';\r\n            container.innerHTML = html;\r\n        }\r\n        \r\n        function setupEventListeners() {\r\n            document.getElementById('chargeCount').addEventListener('change', (e) => { initCharges(parseInt(e.target.value)); });\r\n            document.getElementById('toggleNetForce').addEventListener('click', (e) => { showNetForce = !showNetForce; e.target.classList.toggle('active', showNetForce); updateForces(); });\r\n            document.getElementById('toggleIndividual').addEventListener('click', (e) => { showIndividual = !showIndividual; e.target.classList.toggle('active', showIndividual); updateForces(); });\r\n            document.getElementById('toggleLabels').addEventListener('click', (e) => { showLabels = !showLabels; e.target.classList.toggle('active', showLabels); updateForces(); });\r\n            \r\n            renderer.domElement.addEventListener('mousedown', onMouseDown);\r\n            renderer.domElement.addEventListener('mousemove', onMouseMove);\r\n            renderer.domElement.addEventListener('mouseup', onMouseUp);\r\n            renderer.domElement.addEventListener('touchstart', onTouchStart, { passive: false });\r\n            renderer.domElement.addEventListener('touchmove', onTouchMove, { passive: false });\r\n            renderer.domElement.addEventListener('touchend', onTouchEnd);\r\n            \r\n            setupCustomZoom(); \/\/ Zoom manual\r\n            \r\n            window.addEventListener('resize', onWindowResize);\r\n        }\r\n        \r\n        function onMouseDown(event) {\r\n            event.preventDefault();\r\n            mouse.x = (event.clientX \/ window.innerWidth) * 2 - 1;\r\n            mouse.y = -(event.clientY \/ window.innerHeight) * 2 + 1;\r\n            raycaster.setFromCamera(mouse, camera);\r\n            const meshes = charges.map(c => c.mesh);\r\n            const intersects = raycaster.intersectObjects(meshes);\r\n            if (intersects.length > 0) {\r\n                controls.enabled = false; isDragging = true;\r\n                const intersectedMesh = intersects[0].object;\r\n                selectedCharge = charges.find(c => c.mesh === intersectedMesh);\r\n                dragPlane.setFromNormalAndCoplanarPoint(camera.getWorldDirection(new THREE.Vector3()).negate(), intersectedMesh.position);\r\n                raycaster.ray.intersectPlane(dragPlane, intersection);\r\n                offset.subVectors(intersectedMesh.position, intersection);\r\n                renderer.domElement.style.cursor = 'grabbing';\r\n            }\r\n        }\r\n        \r\n        function onMouseMove(event) {\r\n            if (!isDragging || !selectedCharge) {\r\n                mouse.x = (event.clientX \/ window.innerWidth) * 2 - 1;\r\n                mouse.y = -(event.clientY \/ window.innerHeight) * 2 + 1;\r\n                raycaster.setFromCamera(mouse, camera);\r\n                const meshes = charges.map(c => c.mesh);\r\n                const intersects = raycaster.intersectObjects(meshes);\r\n                renderer.domElement.style.cursor = intersects.length > 0 ? 'grab' : 'default';\r\n                return;\r\n            }\r\n            event.preventDefault();\r\n            mouse.x = (event.clientX \/ window.innerWidth) * 2 - 1;\r\n            mouse.y = -(event.clientY \/ window.innerHeight) * 2 + 1;\r\n            raycaster.setFromCamera(mouse, camera);\r\n            raycaster.ray.intersectPlane(dragPlane, intersection);\r\n            selectedCharge.mesh.position.copy(intersection.add(offset));\r\n            \r\n            updateForces();\r\n            updateChargeCoords(); \r\n        }\r\n        \r\n        function onMouseUp() { isDragging = false; selectedCharge = null; controls.enabled = true; renderer.domElement.style.cursor = 'default'; }\r\n        \r\n        function onTouchStart(event) {\r\n            event.preventDefault();\r\n            const touch = event.touches[0];\r\n            mouse.x = (touch.clientX \/ window.innerWidth) * 2 - 1;\r\n            mouse.y = -(touch.clientY \/ window.innerHeight) * 2 + 1;\r\n            raycaster.setFromCamera(mouse, camera);\r\n            const meshes = charges.map(c => c.mesh);\r\n            const intersects = raycaster.intersectObjects(meshes);\r\n            if (intersects.length > 0) {\r\n                controls.enabled = false; isDragging = true;\r\n                const intersectedMesh = intersects[0].object;\r\n                selectedCharge = charges.find(c => c.mesh === intersectedMesh);\r\n                dragPlane.setFromNormalAndCoplanarPoint(camera.getWorldDirection(new THREE.Vector3()).negate(), intersectedMesh.position);\r\n                raycaster.ray.intersectPlane(dragPlane, intersection);\r\n                offset.subVectors(intersectedMesh.position, intersection);\r\n            }\r\n        }\r\n        \r\n        function onTouchMove(event) {\r\n            if (!isDragging || !selectedCharge) return;\r\n            event.preventDefault();\r\n            const touch = event.touches[0];\r\n            mouse.x = (touch.clientX \/ window.innerWidth) * 2 - 1;\r\n            mouse.y = -(touch.clientY \/ window.innerHeight) * 2 + 1;\r\n            raycaster.setFromCamera(mouse, camera);\r\n            raycaster.ray.intersectPlane(dragPlane, intersection);\r\n            selectedCharge.mesh.position.copy(intersection.add(offset));\r\n            updateForces();\r\n            updateChargeCoords();\r\n        }\r\n        \r\n        function onTouchEnd() { isDragging = false; selectedCharge = null; controls.enabled = true; }\r\n        \r\n        function onWindowResize() {\r\n            camera.aspect = window.innerWidth \/ window.innerHeight;\r\n            camera.updateProjectionMatrix();\r\n            renderer.setSize(window.innerWidth, window.innerHeight);\r\n        }\r\n        \r\n        function animate() {\r\n            requestAnimationFrame(animate);\r\n            controls.update();\r\n            const time = Date.now() * 0.001;\r\n            for (const charge of charges) {\r\n                const glow = charge.mesh.children[0];\r\n                if (glow && glow.material) glow.material.opacity = 0.08 + Math.sin(time * 2 + charge.index) * 0.04;\r\n            }\r\n            renderer.render(scene, camera);\r\n        }\r\n        \r\n        init();\r\n    <\/script>\r\n    \r\n    <style>\r\n  .btn-guia {\r\n    position: fixed;\r\n    bottom: 24px;\r\n    left: 24px;\r\n    z-index: 999;\r\n    background: #3fb950;\r\n    color: #0d1117;\r\n    font-family: 'Space Grotesk', sans-serif;\r\n    font-size: 0.82rem;\r\n    font-weight: 700;\r\n    letter-spacing: 1px;\r\n    text-transform: uppercase;\r\n    padding: 10px 18px;\r\n    border-radius: 8px;\r\n    border: none;\r\n    cursor: pointer;\r\n    box-shadow: 0 4px 20px rgba(63,185,80,0.35);\r\n    transition: transform 0.2s, box-shadow 0.2s;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n  }\r\n  .btn-guia:hover {\r\n    transform: translateY(-2px);\r\n    box-shadow: 0 6px 24px rgba(63,185,80,0.5);\r\n  }\r\n  .btn-guia svg { width: 15px; height: 15px; flex-shrink: 0; }\r\n  .guia-panel {\r\n    position: fixed;\r\n    bottom: 72px;\r\n    left: 24px;\r\n    width: 400px;\r\n    max-height: 70vh;\r\n    z-index: 1000;\r\n    background: #ffffff;\r\n    border: 1px solid #d0d7de;\r\n    border-radius: 12px;\r\n    box-shadow: 0 16px 48px rgba(0,0,0,0.4);\r\n    display: none;\r\n    flex-direction: column;\r\n    overflow: hidden;\r\n    font-family: 'Space Grotesk', sans-serif;\r\n  }\r\n  .guia-panel.visible { display: flex; }\r\n  .guia-header {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    padding: 12px 16px;\r\n    border-bottom: 1px solid #d0d7de;\r\n    flex-shrink: 0;\r\n    background: #f6f8fa;\r\n  }\r\n  .guia-header-title {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n    font-size: 0.85rem;\r\n    font-weight: 700;\r\n    color: #1f2328;\r\n  }\r\n  .guia-header-title svg { width: 15px; height: 15px; color: #3fb950; }\r\n  .guia-close {\r\n    background: none;\r\n    border: none;\r\n    color: #636c76;\r\n    font-size: 1rem;\r\n    cursor: pointer;\r\n    padding: 2px 7px;\r\n    border-radius: 4px;\r\n    transition: color 0.2s, background 0.2s;\r\n    line-height: 1;\r\n  }\r\n  .guia-close:hover { color: #1f2328; background: rgba(0,0,0,0.06); }\r\n  .guia-body {\r\n    overflow-y: auto;\r\n    padding: 18px 18px 20px;\r\n    color: #1f2328;\r\n    font-size: 0.83rem;\r\n    line-height: 1.65;\r\n    background: #ffffff;\r\n  }\r\n  .guia-body::-webkit-scrollbar { width: 5px; }\r\n  .guia-body::-webkit-scrollbar-track { background: transparent; }\r\n  .guia-body::-webkit-scrollbar-thumb { background: #d0d7de; border-radius: 3px; }\r\n  .guia-section-title {\r\n    font-size: 1rem;\r\n    font-weight: 700;\r\n    color: #1f2328;\r\n    margin: 0 0 12px 0;\r\n    padding-bottom: 8px;\r\n    border-bottom: 1px solid #d0d7de;\r\n  }\r\n  .guia-block { margin-bottom: 14px; }\r\n  .guia-label {\r\n    font-size: 0.72rem;\r\n    text-transform: uppercase;\r\n    letter-spacing: 1px;\r\n    color: #636c76;\r\n    margin-bottom: 4px;\r\n  }\r\n  .guia-text { color: #1f2328; }\r\n  .guia-formula {\r\n    background: #f6f8fa;\r\n    border: 1px solid #d0d7de;\r\n    border-radius: 6px;\r\n    padding: 10px 14px;\r\n    text-align: center;\r\n    font-family: 'JetBrains Mono', monospace;\r\n    font-size: 0.88rem;\r\n    color: #0550ae;\r\n    margin: 10px 0;\r\n  }\r\n  .guia-steps { list-style: none; margin: 0; padding: 0; counter-reset: steps; }\r\n  .guia-steps li {\r\n    counter-increment: steps;\r\n    display: flex;\r\n    gap: 10px;\r\n    margin-bottom: 8px;\r\n    align-items: flex-start;\r\n    color: #1f2328;\r\n  }\r\n  .guia-steps li::before {\r\n    content: counter(steps);\r\n    background: #dafbe1;\r\n    color: #1a7f37;\r\n    font-size: 0.72rem;\r\n    font-weight: 700;\r\n    width: 20px;\r\n    height: 20px;\r\n    border-radius: 50%;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    flex-shrink: 0;\r\n    margin-top: 1px;\r\n    border: 1px solid #1a7f37;\r\n  }\r\n  .guia-result {\r\n    background: #dafbe1;\r\n    border-left: 3px solid #1a7f37;\r\n    border-radius: 0 6px 6px 0;\r\n    padding: 10px 14px;\r\n    color: #1f2328;\r\n    font-size: 0.82rem;\r\n    margin-top: 10px;\r\n  }\r\n  .guia-params {\r\n    background: #f6f8fa;\r\n    border: 1px solid #d0d7de;\r\n    border-radius: 6px;\r\n    padding: 10px 14px;\r\n    font-size: 0.8rem;\r\n    color: #1f2328;\r\n  }\r\n  .guia-params span { color: #0550ae; font-family: 'JetBrains Mono', monospace; }\r\n  .var { font-family: 'JetBrains Mono', monospace; }\r\n  .var.pos { color: #cf222e; }\r\n  .var.neg { color: #0550ae; }\r\n  .var.neu { color: #7d4e00; }\r\n  .var.ok  { color: #1a7f37; }\r\n<\/style>\r\n\r\n<div class=\"guia-panel\" id=\"guiaPanel\">\r\n  <div class=\"guia-header\">\r\n    <div class=\"guia-header-title\">\r\n      <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\"\/><path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\"\/><\/svg>\r\n      Gu\u00eda de uso\r\n    <\/div>\r\n    <button class=\"guia-close\" onclick=\"toggleGuia()\">\u2715<\/button>\r\n  <\/div>\r\n\r\n  <div class=\"guia-body\">\r\n\r\n    <!--\u2605 BORRAR DESDE AQUI \u2605-->\r\n\r\n\r\n<div style=\"font-family: Arial, sans-serif; line-height: 1.6; color: #333;\">\r\n<h3 style=\"color: #0056b3; text-align: left;\"><strong><span style=\"font-size: 16px; color: #000080;\">Ley de Coulomb<\/span><span style=\"font-size: 16px; color: #000080;\">     <\/span><\/strong><\/h3>\r\n<span style=\"font-size: 16px;\"><strong>Objetivo:<\/strong> Visualizar y cuantificar la fuerza el\u00e9ctrica entre dos cargas puntuales y comprender c\u00f3mo depende de la magnitud de las cargas y de la distancia de separaci\u00f3n entre ellas.<\/span>\r\n\r\n<span style=\"font-size: 16px;\"><strong>Descripci\u00f3n breve:<\/strong> Simulaci\u00f3n interactiva que permite posicionar dos cargas puntuales, variar sus valores y su separaci\u00f3n para observar la direcci\u00f3n y magnitud de la fuerza resultante mediante vectores y lecturas num\u00e9ricas en tiempo real. La herramienta permite verificar la relaci\u00f3n matem\u00e1tica:<\/span>\r\n<div style=\"text-align: center; margin: 20px 0;\"><span style=\"font-size: 16px;\">\\( F = k_e \\cdot \\frac{|q_1 \\cdot q_2|}{r^2} \\)<\/span><\/div>\r\n<span style=\"font-size: 16px;\"><strong>C\u00f3mo usar (pasos):<\/strong><\/span>\r\n<ul style=\"margin-left: 20px;\">\r\n \t<li><span style=\"font-size: 16px;\">Seleccionar el signo y el valor de cada carga (\\(q_1\\) y \\(q_2\\)) mediante los selectores.<\/span><\/li>\r\n \t<li><span style=\"font-size: 16px;\">Arrastrar las cargas en el espacio de trabajo o utilizar el control para modificar la distancia de separaci\u00f3n \\(r\\).<\/span><\/li>\r\n \t<li><span style=\"font-size: 16px;\">Activar o desactivar la visualizaci\u00f3n de los vectores de fuerza para observar la direcci\u00f3n de la interacci\u00f3n.<\/span><\/li>\r\n \t<li><span style=\"font-size: 16px;\">Habilitar la visualizaci\u00f3n de la constante \\(k_e\\) y las unidades para realizar c\u00e1lculos comparativos.<\/span><\/li>\r\n \t<li><span style=\"font-size: 16px;\">Leer la magnitud de la fuerza en el panel de la interfaz para diferentes configuraciones.<\/span><\/li>\r\n<\/ul>\r\n<span style=\"font-size: 16px;\"><strong>Par\u00e1metros ajustables:<\/strong> Valor y signo de las cargas (\\(q\\)), distancia \\(r\\), unidades de medida, mostrar\/ocultar vectores de fuerza y f\u00f3rmulas representativas.<\/span>\r\n<p style=\"background-color: #f8f9fa; padding: 15px; border-left: 5px solid #0056b3;\"><span style=\"font-size: 16px;\"><strong>Resultados esperados \/ observaciones:<\/strong> Se comprueba que la fuerza es inversamente proporcional al cuadrado de la distancia; si la distancia se duplica, la fuerza se reduce a la cuarta parte. Cargas de distinto signo presentan fuerzas de atracci\u00f3n, mientras que cargas de igual signo se repelen. Cualquier cambio en la magnitud de las cargas modifica la fuerza de forma proporcional.<\/span><\/p>\r\n\r\n<\/div>\r\n\r\n\r\n   <!--\u2605 BORRAR HASTA AQUI \u2605-->\r\n\r\n  <\/div>\r\n<\/div>\r\n\r\n<button class=\"btn-guia\" onclick=\"toggleGuia()\">\r\n  <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\"\/><path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\"\/><\/svg>\r\n  Gu\u00eda de uso\r\n<\/button>\r\n\r\n<script>\r\n  function toggleGuia() {\r\n    document.getElementById('guiaPanel').classList.toggle('visible');\r\n  }\r\n<\/script>\r\n\r\n    \r\n    \r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-49b2bf9 elementor-widget elementor-widget-text-editor\" data-id=\"49b2bf9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Mas ande otro criollo pasa Mart\u00edn Fierro ha de pasar, Nada la hace recular Ni las fantasmas lo espantan; Y dende que todos cantan Yo tambi\u00e9n quiero cantar.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Ley de Coulomb &#8211; Simulacion 3D Interactiva FICA &#8211; UNSL Ley de Coulomb Simulacion Interactiva 3D &#8211; Vectores de fuerza Configuracion Cantidad de cargas 2&hellip;<\/p>\n","protected":false},"author":7,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-5523","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ley_de_coulomb - F\u00edsica 2<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ley_de_coulomb - F\u00edsica 2\" \/>\n<meta property=\"og:description\" content=\"Ley de Coulomb &#8211; Simulacion 3D Interactiva FICA &#8211; UNSL Ley de Coulomb Simulacion Interactiva 3D &#8211; Vectores de fuerza Configuracion Cantidad de cargas 2&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/\" \/>\n<meta property=\"og:site_name\" content=\"F\u00edsica 2\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-18T21:08:54+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/ley_de_coulomb\\\/\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/ley_de_coulomb\\\/\",\"name\":\"Ley_de_coulomb - F\u00edsica 2\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#website\"},\"datePublished\":\"2026-03-05T01:56:25+00:00\",\"dateModified\":\"2026-04-18T21:08:54+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/ley_de_coulomb\\\/#breadcrumb\"},\"inLanguage\":\"es-AR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/ley_de_coulomb\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/ley_de_coulomb\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Inicio\",\"item\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ley_de_coulomb\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#website\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/\",\"name\":\"F\u00edsica 2\",\"description\":\"FICA - UNSL\",\"publisher\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es-AR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#organization\",\"name\":\"SAC- Secretar\u00eda General FICA\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es-AR\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/wp-content\\\/uploads\\\/2021\\\/11\\\/SG-Logo.png\",\"contentUrl\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/wp-content\\\/uploads\\\/2021\\\/11\\\/SG-Logo.png\",\"width\":4483,\"height\":1231,\"caption\":\"SAC- Secretar\u00eda General FICA\"},\"image\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ley_de_coulomb - F\u00edsica 2","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/","og_locale":"es_ES","og_type":"article","og_title":"Ley_de_coulomb - F\u00edsica 2","og_description":"Ley de Coulomb &#8211; Simulacion 3D Interactiva FICA &#8211; UNSL Ley de Coulomb Simulacion Interactiva 3D &#8211; Vectores de fuerza Configuracion Cantidad de cargas 2&hellip;","og_url":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/","og_site_name":"F\u00edsica 2","article_modified_time":"2026-04-18T21:08:54+00:00","twitter_card":"summary_large_image","twitter_misc":{"Tiempo de lectura":"2 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/","url":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/","name":"Ley_de_coulomb - F\u00edsica 2","isPartOf":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#website"},"datePublished":"2026-03-05T01:56:25+00:00","dateModified":"2026-04-18T21:08:54+00:00","breadcrumb":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/#breadcrumb"},"inLanguage":"es-AR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/ley_de_coulomb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Inicio","item":"https:\/\/fisica2.fica.unsl.edu.ar\/"},{"@type":"ListItem","position":2,"name":"Ley_de_coulomb"}]},{"@type":"WebSite","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#website","url":"https:\/\/fisica2.fica.unsl.edu.ar\/","name":"F\u00edsica 2","description":"FICA - UNSL","publisher":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fisica2.fica.unsl.edu.ar\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es-AR"},{"@type":"Organization","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#organization","name":"SAC- Secretar\u00eda General FICA","url":"https:\/\/fisica2.fica.unsl.edu.ar\/","logo":{"@type":"ImageObject","inLanguage":"es-AR","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#\/schema\/logo\/image\/","url":"https:\/\/fisica2.fica.unsl.edu.ar\/wp-content\/uploads\/2021\/11\/SG-Logo.png","contentUrl":"https:\/\/fisica2.fica.unsl.edu.ar\/wp-content\/uploads\/2021\/11\/SG-Logo.png","width":4483,"height":1231,"caption":"SAC- Secretar\u00eda General FICA"},"image":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages\/5523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/comments?post=5523"}],"version-history":[{"count":124,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages\/5523\/revisions"}],"predecessor-version":[{"id":7094,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages\/5523\/revisions\/7094"}],"wp:attachment":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/media?parent=5523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}