Saltar al contenido
Carta Astral · Neología
Persona A
Persona B
Calculando carta astral...
Persona A Persona B
Aspectos cruzados
AAspectoBOrbe
Neología

Neología · Método Boada

Albert Boada · Psicoastrología

Interpretación de Pareja
Posiciones planetarias
PlanetaGradoCasaR
Punto de la Edad
Neología

Neología · Método Boada

Albert Boada · Psicoastrología

Interpretación Neología
Generando interpretación...

Neología · Método Boada

Neología

Neología · Método Boada

Albert Boada · Psicoastrología

${subtitulo ? '
' + subtitulo + '
' : ''}
${titulo}
${body}
`; const win = window.open('', '_blank'); win.document.open(); win.document.write(html); win.document.close(); } // ================================================================ // CARTA NODAL — Método Huber // ================================================================ async function interpretarNodal() { if (!window._nodalData) { alert('Primero calcula la carta nodal'); return; } const nodal = window._nodalData; const radix = window._lastData; const nombre = (document.getElementById('nd-name') ? document.getElementById('nd-name').value : '') || 'el consultante'; const SIGN_NAMES_FULL = ['Aries','Tauro','Géminis','Cáncer','Leo','Virgo','Libra','Escorpio','Sagitario','Capricornio','Acuario','Piscis']; const PLANET_NAMES_FULL = ['Sol','Luna','Mercurio','Venus','Marte','Júpiter','Saturno','Urano','Neptuno','Plutón']; const NN = nodal.NN_natal; const nnSign = SIGN_NAMES_FULL[Math.floor(NN / 30)]; const nnDeg = (NN % 30).toFixed(1); const nnCasa = nodal.planets_nodal.find(p => { const arc = ((NN - nodal.AC_nodal) % 360 + 360) % 360; return Math.floor(arc / 30) + 1; }); const nnHouse = (() => { const arc = ((NN - nodal.AC_nodal) % 360 + 360) % 360; return Math.floor(arc / 30) + 1; })(); const NS = (NN + 180) % 360; const nsSign = SIGN_NAMES_FULL[Math.floor(NS / 30)]; const nsHouse = (() => { const arc = ((NS - nodal.AC_nodal) % 360 + 360) % 360; return Math.floor(arc / 30) + 1; })(); // Planetas y sus posiciones en la nodal let planetasDesc = `PLANETAS EN LA CARTA NODAL:\n`; nodal.planets_nodal.forEach(p => { const sIdx = Math.floor(p.lon / 30); const deg = (p.lon % 30).toFixed(1); planetasDesc += `- ${PLANET_NAMES_FULL[p.idx]}: ${SIGN_NAMES_FULL[sIdx]} ${deg}° · Casa nodal ${p.casa_nodal}\n`; }); // Aspectos al eje nodal (NN y NS) let aspectosEje = `ASPECTOS AL EJE NODAL (tensiones y dones kármicos):\n`; const ASP_NAMES = ['Conjunción','Sextil','Cuadratura','Trígono','Inconjunto','Oposición']; const ASP_GRADOS = [0, 60, 90, 120, 150, 180]; const ASP_ORBE = [8, 4, 6, 6, 3, 8]; const ASP_TIPO = ['tensión','armonía','tensión','armonía','neutro','armonía']; nodal.planets_nodal.forEach(p => { [NN, NS].forEach((nodo, ni) => { let dis = Math.abs(p.lon - nodo); if (dis > 180) dis = 360 - dis; ASP_GRADOS.forEach((aspG, ai) => { const orb = Math.abs(dis - aspG); if (orb <= ASP_ORBE[ai]) { aspectosEje += `- ${PLANET_NAMES_FULL[p.idx]} en ${ASP_NAMES[ai]} con ${ni===0?'Nodo Norte':'Nodo Sur'} (${ASP_TIPO[ai]}, orbe ${orb.toFixed(1)}°)\n`; } }); }); }); const userPrompt = `Genera el informe de Vidas Pasadas del Método Boada para ${nombre}. DATOS DE LA CARTA NODAL: - Nodo Norte: ${nnSign} ${nnDeg}° · Casa ${nnHouse} (escenario principal de vidas pasadas) - Nodo Sur: ${nsSign} · Casa ${nsHouse} (misión de esta vida) ${planetasDesc} ${aspectosEje} Escribe en español. Sigue exactamente la estructura del sistema: EL ALMA QUE LLEGA → QUIÉN FUISTE → LO QUE TRAES → LAS HERIDAS SIN CERRAR → TU MISIÓN EN ESTA VIDA. Sin argot astrológico. Tono cálido, evocador y respetuoso.`; const section = document.getElementById('nodal-interp-section'); section.style.display = 'block'; document.getElementById('nodal-interp-loading').style.display = 'block'; document.getElementById('nodal-interp-content').innerHTML = ''; document.getElementById('btn-nodal-interp').disabled = true; document.getElementById('nodal-interp-pdf-wrap').style.display = 'none'; try { const resp = await fetch('https://xeni-b118678e.base44.app/functions/interpretNeologia', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ system: NODAL_SYSTEM, carta: userPrompt }) }); if (!resp.ok) throw new Error('Error servidor: ' + resp.status); const result = await resp.json(); if (result.error) throw new Error(result.error); const texto = result.interpretation || result.text || ''; const html = texto.split('\n').filter(l => l.trim()).map(function(l) { if (l.startsWith('## ') || l.startsWith('# ')) return '

' + l.replace(/^#+\s*/,'') + '

'; if (l.trim().startsWith('**') && l.trim().endsWith('**')) return '

' + l.replace(/\*\*/g,'') + '

'; return '

' + l.replace(/\*\*(.*?)\*\*/g,'$1') + '

'; }).join(''); document.getElementById('nodal-interp-content').innerHTML = html; window._nodalInterpContent = texto; document.getElementById('nodal-interp-pdf-wrap').style.display = 'block'; } catch(e) { document.getElementById('nodal-interp-content').innerHTML = '

Error: ' + e.message + '

'; } finally { document.getElementById('nodal-interp-loading').style.display = 'none'; document.getElementById('btn-nodal-interp').disabled = false; } } function exportNodalPDF() { const nombre = (document.getElementById('nd-name') ? document.getElementById('nd-name').value : '') || 'consultante'; const texto = window._nodalInterpContent || ''; if (!texto) return; const { jsPDF } = window.jspdf; const doc = new jsPDF({ unit: 'mm', format: 'a4' }); const W = doc.internal.pageSize.getWidth(); const M = 18; let y = 18; // Header doc.setFillColor(106, 27, 154); doc.rect(0, 0, W, 28, 'F'); if (window._logoB64) { try { doc.addImage(window._logoB64, 'PNG', M, 4, 22, 20); } catch(e) {} } doc.setTextColor(255,255,255); doc.setFontSize(13); doc.setFont('helvetica','bold'); doc.text('Registro de Vidas Pasadas', W/2, 12, { align: 'center' }); doc.setFontSize(10); doc.setFont('helvetica','normal'); doc.text(nombre + ' · Método Boada', W/2, 20, { align: 'center' }); y = 36; doc.setTextColor(30,10,50); const lines = texto.split('\n').filter(l => l.trim()); for (const line of lines) { const clean = line.replace(/\*\*/g,'').replace(/^#+\s*/,''); const isTitle = line.startsWith('#') || (line.trim().startsWith('**') && line.trim().endsWith('**')); if (isTitle) { doc.setFontSize(11); doc.setFont('helvetica','bold'); doc.setTextColor(106, 27, 154); } else { doc.setFontSize(9.5); doc.setFont('helvetica','normal'); doc.setTextColor(30,10,50); } const wrapped = doc.splitTextToSize(clean, W - M*2); if (y + wrapped.length * 5 > 280) { doc.addPage(); y = 16; } doc.text(wrapped, M, y); y += wrapped.length * (isTitle ? 6 : 5) + (isTitle ? 2 : 1); } // Footer doc.setFontSize(8); doc.setTextColor(150,100,180); doc.text('Neología · Albert Boada · Psicoastrología', W/2, 290, { align: 'center' }); doc.save('vidas_pasadas_' + nombre.replace(/\s+/g,'_') + '.pdf'); } function resetNodal() { document.getElementById('nodal-wrap').style.display = 'none'; document.getElementById('nodal-form').style.display = 'block'; } async function calcularNodal() { const name = document.getElementById('nd-name').value.trim(); const surname = document.getElementById('nd-surname').value.trim(); const day = parseInt(document.getElementById('nd-day').value); const month = parseInt(document.getElementById('nd-month').value); const year = parseInt(document.getElementById('nd-year').value); const hour = parseInt(document.getElementById('nd-hour').value); const min = parseInt(document.getElementById('nd-min').value); const city = document.getElementById('nd-city').value.trim(); const errEl = document.getElementById('nd-error'); errEl.style.display = 'none'; if (!day || !month || !year || isNaN(hour) || isNaN(min) || !city) { errEl.textContent = 'Por favor, completa todos los campos.'; errEl.style.display = 'block'; return; } document.getElementById('nd-loading').style.display = 'block'; try { const resp = await fetch('https://xeni-b118678e.base44.app/functions/calcChart3', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ day, month, year, hour, minute: min, city }) }); const data = await resp.json(); if (data.error) throw new Error(data.error); document.getElementById('nd-loading').style.display = 'none'; document.getElementById('nodal-form').style.display = 'none'; const nodalData = computeNodalChart(data); const fullName = [name, surname].filter(Boolean).join(' ') || 'Carta Nodal'; document.getElementById('nd-chart-title').textContent = '\u263d Carta Nodal \u00b7 ' + fullName; document.getElementById('nd-chart-sub').textContent = day+'/'+month+'/'+year+' '+String(hour).padStart(2,'0')+':'+String(min).padStart(2,'0')+' \u00b7 '+city; window._nodalData = nodalData; window._lastData = data; drawNodalChart(nodalData, data); fillNodalTable(nodalData, data); fillCrossAxisInfo(nodalData, data); document.getElementById('nodal-wrap').style.display = 'block'; document.getElementById('nodal-interp-section').style.display = 'none'; document.getElementById('nodal-interp-content').innerHTML = ''; } catch(e) { document.getElementById('nd-loading').style.display = 'none'; errEl.textContent = 'Error: ' + e.message; errEl.style.display = 'block'; } } function computeNodalChart(radix) { // El backend devuelve northNode o trueNode const nn_lon = radix.northNode !== undefined ? radix.northNode : radix.trueNode !== undefined ? radix.trueNode : (() => { throw new Error('Nodo Norte no disponible en los datos del backend'); })(); // AC nodal = grado exacto del Nodo Norte en la radix const AC_nodal = nn_lon; // Casas iguales de 30°, empezando desde AC_nodal en sentido directo (antihorario zodiacal) const cusps = []; for (let i = 0; i < 12; i++) { cusps.push(((AC_nodal + i * 30) % 360 + 360) % 360); } // Los planetas NO cambian de posición en el zodíaco — solo se recalcula su casa nodal const planets_nodal = radix.planets.map((p, idx) => { const lon = typeof p === 'object' ? p.lon : p; // Casa nodal: en qué casa de 30° cae este planeta respecto al AC nodal const arcFromAC = ((lon - AC_nodal) % 360 + 360) % 360; const casa = Math.floor(arcFromAC / 30) + 1; return { lon, lon_nodal: lon, casa_nodal: casa, idx }; }); return { AC_nodal, cusps, planets_nodal, AC_natal: radix.houses[0], NN_natal: nn_lon }; } function drawNodalChart(nodal, radix) { const dpr = window.devicePixelRatio || 1; const SZ = Math.min(window.innerWidth, window.innerHeight, 520); const cv = document.getElementById('nd-canvas'); cv.width = SZ * dpr; cv.height = SZ * dpr; cv.style.width = SZ + 'px'; cv.style.height = SZ + 'px'; const ctx = cv.getContext('2d'); ctx.scale(dpr, dpr); const cx = SZ / 2, cy = SZ / 2; const R = SZ / 2 * 0.85; // ── Fórmulas AstroNex NodalChart ──────────────────────────────── // offsets_plan_degree(lon) = (180 - NN) + lon → planetas // get_sign_cusps()[h] = 30*h - offset (offset = 30 - NN%30) // d_radial_lines angle = 180 - sign_cusp → divisiones de signos // get_sign_offsets (glifos) = sign_base + 30*i + 15, pero en HTML = eso - 90 // donde sign_base = (11 - ascIdx)*30 + offset - 90 // get_cross_offset = 180 + NN → cúspides de casas // ───────────────────────────────────────────────────────────────── const NN = nodal.NN_natal; const ascIdx = Math.floor(NN / 30); // índice signo del NN (0=Aries…) const offset = 30 - (NN % 30); // grados hasta siguiente inicio signo // Ángulo canvas de un planeta (longitud zodiacal real) const offPlan = lon => r2a(((180 - NN) + lon + 360) % 360); // Ángulo canvas de una cúspide de casa const offCusp = lon => r2a(((180 + NN) - lon + 360) % 360); // Ángulo canvas de una división de signo (d_radial_lines: 180 - sign_cusp) const offSignDiv = h => r2a(((180 - (30*h - offset)) % 360 + 360) % 360); // Ángulo canvas del centro del glifo del signo i // = centro del sector i = 180 + offset - 30*i - 15 const offSignGlyph = i => r2a(((180 + offset - 30*i - 15) % 360 + 360) % 360); const rvi = R * R_VERYINNER; const ri = R * R_INNER; const rri = R * R_RULEDINNER; const rro = R * R_RULEDOUTER; const rrm = R * R_RULEDMID; const rpl = R * R_PL; const rasp = R * R_ASP; ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, SZ, SZ); // Tinte lila muy suave para distinguir de la radix ctx.fillStyle = 'rgba(180,150,255,0.06)'; ctx.beginPath(); ctx.arc(cx, cy, rro, 0, 2 * PI); ctx.fill(); function circle(r, col, lw) { ctx.beginPath(); ctx.arc(cx, cy, r, 0, 2 * PI); ctx.strokeStyle = col; ctx.lineWidth = lw; ctx.stroke(); } circle(rrm, '#dde', 0.6); circle(rro, '#aab', 0.9); circle(rri, '#aab', 0.9); // Rulers — desde el NN, avanzando en el sentido de offPlan for (let t = 0; t < 360; t++) { const ang = offPlan(NN + t); const o = t % 10 === 0 ? rro * 0.032 : t % 5 === 0 ? rro * 0.020 : rro * 0.008; ctx.beginPath(); ctx.moveTo(cx + rro * Math.cos(ang), cy + rro * Math.sin(ang)); ctx.lineTo(cx + (rro + o) * Math.cos(ang), cy + (rro + o) * Math.sin(ang)); ctx.strokeStyle = '#888'; ctx.lineWidth = t % 10 === 0 ? 1.4 : t % 5 === 0 ? 0.9 : 0.4; ctx.stroke(); const ii = t % 10 === 0 ? rri * 0.034 : t % 5 === 0 ? rri * 0.022 : rri * 0.008; ctx.beginPath(); ctx.moveTo(cx + rri * Math.cos(ang), cy + rri * Math.sin(ang)); ctx.lineTo(cx + (rri - ii) * Math.cos(ang), cy + (rri - ii) * Math.sin(ang)); ctx.strokeStyle = '#888'; ctx.lineWidth = t % 10 === 0 ? 1.4 : t % 5 === 0 ? 0.9 : 0.4; ctx.stroke(); } // Divisiones de signos — AstroNex: angle = 180 - (30*h - offset) for (let h = 0; h < 12; h++) { const ang = offSignDiv(h); ctx.beginPath(); ctx.moveTo(cx + rri * Math.cos(ang), cy + rri * Math.sin(ang)); ctx.lineTo(cx + rro * 1.01 * Math.cos(ang), cy + rro * 1.01 * Math.sin(ang)); ctx.strokeStyle = '#aab'; ctx.lineWidth = 0.6; ctx.stroke(); } // SIGNOS vectoriales — AstroNex get_sign_offsets - 90 (ajuste HTML canvas) const ringH = rro - rri; const signScale = (ringH * 0.80) / 38; const signRad = (rri + rro) / 2; for (let i = 0; i < 12; i++) { const rotRad = offSignGlyph(i); // Signo que aparece en el sector i: orden inverso desde el signo del NN const sigIdx = ((ascIdx - i) % 12 + 12) % 12; const glyph = GLYPHS.signs[SIGN_NAMES[sigIdx]]; if (!glyph) continue; const col = ZCOL[SIGN_EL[sigIdx]]; const ex = glyph.e; const gx = cx + signRad * Math.cos(rotRad), gy = cy + signRad * Math.sin(rotRad); ctx.save(); ctx.translate(gx, gy); ctx.rotate(rotRad + PI / 2); ctx.translate(-(ex[0] + ex[2] / 2) * signScale, -(ex[1] + ex[3] / 2) * signScale); ctx.scale(signScale, signScale); ctx.fillStyle = col; ctx.beginPath(); for (const seg of glyph.p) { const cseg = seg.c; switch (seg.t) { case 0: ctx.moveTo(cseg[0], cseg[1]); break; case 1: ctx.lineTo(cseg[0], cseg[1]); break; case 2: ctx.bezierCurveTo(cseg[0], cseg[1], cseg[2], cseg[3], cseg[4], cseg[5]); break; case 3: ctx.closePath(); break; } } ctx.fill(); ctx.restore(); } // CÚSPIDES — AstroNex get_cross_offset = 180 + NN → offCusp const cfont = CUSP_FONT * rro * MAGICK; const cwidths = [1.4, 0.5, 0.5]; for (let i = 0; i < 12; i++) { const ha = offCusp(nodal.cusps[i]); ctx.beginPath(); ctx.moveTo(cx + rri * Math.cos(ha), cy + rri * Math.sin(ha)); ctx.lineTo(cx + (rri + (rro - rri) * 0.25) * Math.cos(ha), cy + (rri + (rro - rri) * 0.25) * Math.sin(ha)); ctx.strokeStyle = HCOLS[i % 3]; ctx.lineWidth = cwidths[i % 3]; ctx.stroke(); ctx.beginPath(); ctx.moveTo(cx + rro * Math.cos(ha), cy + rro * Math.sin(ha)); ctx.lineTo(cx + rro * 1.055 * Math.cos(ha), cy + rro * 1.055 * Math.sin(ha)); ctx.strokeStyle = HCOLS[i % 3]; ctx.lineWidth = cwidths[i % 3]; ctx.stroke(); const hnum_r = rro * 1.10; const isCardinal = [0, 3, 6, 9].includes(i); ctx.font = isCardinal ? `bold ${cfont * 0.85}px sans-serif` : `bold ${cfont}px Astrodotbasic`; ctx.fillStyle = HCOLS[i % 3]; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(CNAMES[i], cx + hnum_r * Math.cos(ha), cy + hnum_r * Math.sin(ha)); } // ASPECTOS entre longitudes zodiacales reales de los planetas // NN: en la carta nodal se posiciona con la longitud del AC natal (= offPlan(AC_natal)) // Esto lo coloca en la zona del IC nodal, igual que en AstroNex const AC_natal_lon = nodal.AC_natal; const plons = [...nodal.planets_nodal.map(p => p.lon), AC_natal_lon]; const aspects = []; for (let i = 0; i < plons.length; i++) { for (let j = i + 1; j < plons.length; j++) { let dis = Math.abs(plons[i] - plons[j]); if (dis > 180) dis = 360 - dis; let nsig = Math.floor(dis / 30), orb = dis % 30; if (orb > 20) { nsig++; orb = 30 - orb; } nsig = nsig % 12; const pc1 = PLANCLASS[i] ?? 1, pc2 = PLANCLASS[j] ?? 1, acl = ASPCLASS[nsig]; const o1 = ORBS[pc1][acl], o2 = ORBS[pc2][acl]; if (orb <= o1 * 1.1 || orb <= o2 * 1.1) { aspects.push({ i, j, nsig, p1: offPlan(plons[i]), p2: offPlan(plons[j]), f1: orb / o1, f2: orb / o2, col: ASP_COLS[nsig] }); } } } const gw = aspects.filter(asp => asp.f1 > 1 && asp.f2 > 1); const rest = aspects.filter(asp => !(asp.f1 > 1 && asp.f2 > 1)); const conj = rest.filter(asp => asp.nsig === 0); const uni = rest.filter(asp => asp.nsig !== 0 && (asp.f1 > 1 || asp.f2 > 1)); const fusus = rest.filter(asp => asp.nsig !== 0 && asp.f1 <= 1 && asp.f2 <= 1); const orange = '#e07020'; for (const asp of gw) { const x1=cx+rasp*Math.cos(asp.p1), y1=cy+rasp*Math.sin(asp.p1); const x2=cx+rasp*Math.cos(asp.p2), y2=cy+rasp*Math.sin(asp.p2); ctx.save(); ctx.setLineDash([10,5]); ctx.strokeStyle=asp.col; ctx.lineWidth=0.5; ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.stroke(); ctx.restore(); } for (const asp of conj) { const x1=cx+rasp*Math.cos(asp.p1), y1=cy+rasp*Math.sin(asp.p1); const x2=cx+rasp*Math.cos(asp.p2), y2=cy+rasp*Math.sin(asp.p2); ctx.save(); ctx.strokeStyle=orange; ctx.lineWidth=2.5; ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.stroke(); ctx.restore(); } for (const asp of uni) { const x1=cx+rasp*Math.cos(asp.p1), y1=cy+rasp*Math.sin(asp.p1); const x2=cx+rasp*Math.cos(asp.p2), y2=cy+rasp*Math.sin(asp.p2); const [sx,sy,ex2,ey2] = asp.f1 ({ idx, lon, degree: ((180 - NN + lon) % 360 + 360) % 360, fac: 1.0 })); // Separación de planetas cercanos const sorted = [...rawPlots].sort((a, b) => a.lon - b.lon); const used = new Array(rawPlots.length).fill(false); for (let i = 0; i < sorted.length; i++) { if (used[i]) continue; const group = [sorted[i]]; for (let j = i + 1; j < sorted.length; j++) { let d = sorted[j].lon - sorted[i].lon; if (d > 180) d = 360 - d; if (d <= 6.5) { group.push(sorted[j]); used[j] = true; } } used[i] = true; if (group.length > 1) group.forEach((p, k) => { p.fac = [0.93, 1.07][k % 2]; }); } const scl = R * PLAN_SCALE; for (const plt of rawPlots) { const ang = r2a(plt.degree); const rr = rpl * plt.fac; const px = cx + rr * Math.cos(ang), py = cy + rr * Math.sin(ang); const pname = PLANET_NAMES[plt.idx]; const glyph = GLYPHS.planets[pname]; if (!glyph) continue; // NN y otros sin glifo vectorial se saltan aquí const col = PCOL[PLANET_CAT[plt.idx]] || '#9966cc'; const ex = glyph.e; const glH = Math.abs(ex[3]); const ps = scl * (PLANET_SZ[plt.idx] || 1.0) / glH; ctx.save(); ctx.translate(px, py); ctx.translate(-(ex[0] + ex[2] / 2) * ps, -(ex[1] + ex[3] / 2) * ps); ctx.scale(ps, ps); ctx.fillStyle = col; ctx.beginPath(); for (const seg of glyph.p) { const cseg = seg.c; switch (seg.t) { case 0: ctx.moveTo(cseg[0], cseg[1]); break; case 1: ctx.lineTo(cseg[0], cseg[1]); break; case 2: ctx.bezierCurveTo(cseg[0], cseg[1], cseg[2], cseg[3], cseg[4], cseg[5]); break; case 3: ctx.closePath(); break; } } ctx.fill(); ctx.restore(); } // Inner circles (encima de planetas) circle(ri, '#667', 0.9); ctx.beginPath(); ctx.arc(cx, cy, rvi, 0, 2 * PI); ctx.fillStyle = '#ffffff'; ctx.fill(); ctx.strokeStyle = '#aab'; ctx.lineWidth = 0.8; ctx.stroke(); // ── Nodo Norte ☊ — se dibuja igual que los demás planetas con offPlan(lon) ── { // El NN mantiene su longitud zodiacal real (igual que los demás planetas). // offPlan(NN) = (180 - NN) + NN = 180° → canvas 180° = AC nodal (lado izquierdo). // Como en la radix el NN está en casa 4, en la nodal aparece reflejado en casa 4. const nnAngRad = offPlan(nodal.AC_natal); const nnR = rpl; const nnPx = cx + nnR * Math.cos(nnAngRad), nnPy = cy + nnR * Math.sin(nnAngRad); // Pline interior ctx.beginPath(); ctx.moveTo(cx + ri * Math.cos(nnAngRad), cy + ri * Math.sin(nnAngRad)); ctx.lineTo(cx + ri * 0.91 * Math.cos(nnAngRad), cy + ri * 0.91 * Math.sin(nnAngRad)); ctx.strokeStyle = '#9966cc'; ctx.lineWidth = 1.2; ctx.stroke(); // Símbolo ☊ ctx.font = `bold ${R * 0.052}px sans-serif`; ctx.fillStyle = '#9966cc'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('☊', nnPx, nnPy); } // Etiqueta central ctx.font = `bold ${R * 0.048}px sans-serif`; ctx.fillStyle = '#9966cc'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('☽N', cx, cy); } function fillNodalTable(nodal, radix) { const SNAMES = ['Ari','Tau','Gem','Can','Leo','Vir','Lib','Esc','Sag','Cap','Acu','Pis']; const PNAMES = ['Sol','Luna','Mercurio','Venus','Marte','Júpiter','Saturno','Urano','Neptuno','Plutón']; const GLYPHS_MAP = {'Sol':'\u2609','Luna':'\u263d','Mercurio':'\u263f','Venus':'\u2640','Marte':'\u2642','Júpiter':'\u2643','Saturno':'\u2644','Urano':'\u26e2','Neptuno':'\u2646','Plutón':'\u2647'}; const COLORS_MAP = {'Sol':'#b8860b','Luna':'#555599','Mercurio':'#27ae60','Venus':'#27ae60','Marte':'#c0392b','Júpiter':'#c0392b','Saturno':'#2980b9','Urano':'#2980b9','Neptuno':'#2980b9','Plutón':'#c0392b'}; const tbody = document.getElementById('nd-ptbody'); tbody.innerHTML = ''; nodal.planets_nodal.forEach((p, i) => { const name = PNAMES[p.idx !== undefined ? p.idx : i] || '?'; const si = Math.floor(((p.lon_nodal%360)+360)%360/30); const dg = ((p.lon_nodal%30)+30)%30; const col = COLORS_MAP[name]||'#444'; const tr = document.createElement('tr'); tr.innerHTML = ''+(GLYPHS_MAP[name]||'')+''+name+''+(SNAMES[si]||'')+''+dg.toFixed(1)+'\u00b0'+p.casa_nodal+''; tbody.appendChild(tr); }); } function fillCrossAxisInfo(nodal, radix) { const SN = ['Aries','Tauro','G\u00e9minis','C\u00e1ncer','Leo','Virgo','Libra','Escorpio','Sagitario','Capricornio','Acuario','Piscis']; const nnS = SN[Math.floor(nodal.NN_natal / 30)]; const nnD = (nodal.NN_natal % 30).toFixed(1); // Eje nodal: AC (NN) y su oposición (NS) const ns_lon = (nodal.AC_nodal + 180) % 360; const nsS = SN[Math.floor(ns_lon / 30)]; const nsD = (ns_lon % 30).toFixed(1); document.getElementById('nd-cross-info').innerHTML = 'AC Nodal (\u2605 Nodo Norte): ' + nnD + '\u00b0 ' + nnS + '
' + 'DC Nodal (\u2606 Nodo Sur): ' + nsD + '\u00b0 ' + nsS + '
' + 'Casas iguales de 30\u00b0 desde el Nodo Norte. Los planetas mantienen su posici\u00f3n zodiacal exacta.'; }

Este sitio web utiliza Cookies propias y de terceros, para recopilar información con la finalidad de mejorar nuestros servicios. Si continua navegando, supone la aceptación de la instalación de las mismas. El usuario tiene la posibilidad de configurar su navegador pudiendo, si así lo desea, impedir que sean instaladas en su disco duro, aunque deberá tener en cuenta que dicha acción podrá ocasionar dificultades de navegación de la página web. Más información

Los ajustes de cookies en esta web están configurados para «permitir las cookies» y ofrecerte la mejor experiencia de navegación posible. Si sigues usando esta web sin cambiar tus ajustes de cookies o haces clic en «Aceptar», estarás dando tu consentimiento a esto.

Cerrar