446 lines
12 KiB
TypeScript
446 lines
12 KiB
TypeScript
// === SISTEMA ALPHA CENTAURI — Simulazione TypeScript ===
|
|
// Sistema triplo: Alpha Cen A + Alpha Cen B + Proxima Centauri
|
|
// Distanza totale: 4.37 anni luce dalla Terra
|
|
|
|
interface CorpoCeleste {
|
|
nome: string;
|
|
raggio: number;
|
|
asseMaggiore: number;
|
|
eccentricita: number;
|
|
velocita: number;
|
|
colore: string;
|
|
angoli?: number[];
|
|
raggiMondi?: number[];
|
|
coloriMondi?: string[];
|
|
nomiMondi?: string[];
|
|
velocitaMondi?: number[];
|
|
anelli?: boolean;
|
|
dettagli?: Dettaglio[];
|
|
}
|
|
|
|
interface Dettaglio {
|
|
tipo: string;
|
|
colore: string;
|
|
x?: number;
|
|
y?: number;
|
|
r?: number;
|
|
}
|
|
|
|
const canvas = document.getElementById("alpha") as HTMLCanvasElement;
|
|
const ctx = canvas.getContext("2d")!;
|
|
|
|
canvas.width = window.innerWidth;
|
|
canvas.height = window.innerHeight;
|
|
|
|
// === DATI ASTROFISICI ===
|
|
// Alpha Centauri A (Rigil Kentaurus): G2V, 1.1 M☉, 1.221 R☉
|
|
// Alpha Centauri B (Toliman): K1V, 0.907 M☉, 0.863 R☉
|
|
// Orbita A-B: a=23.4 UA, e=0.517, P=79.91 anni
|
|
// Proxima Centauri: M5.5Ve, 0.122 M☉
|
|
// Orbita Proxima: a~125 UA, e~0.509, P~547 anni
|
|
|
|
// === PIANETI CONFERMATI ===
|
|
// Alpha Cen Bb: 0.011 M⊕, 3.236 giorni, 0.064 UA (controverso)
|
|
// Alpha Cen Ab: 1.1 M⊕, 224 giorni, ~1.25 UA (confermato HARPS 2012)
|
|
// Proxima d: 0.26 M⊕, 5.122 giorni, 0.029 UA (2022)
|
|
// Proxima b: 1.07 M⊕, 11.186 giorni, 0.0485 UA (2016)
|
|
// Proxima c: ~7 M⊕, ~5.28 anni, ~1.489 UA (2019)
|
|
|
|
let tempo = 0;
|
|
|
|
// Stelle del sistema triplo
|
|
interface Stella {
|
|
nome: string;
|
|
tipo: string;
|
|
colore: string;
|
|
raggio: number;
|
|
asseMaggiore: number;
|
|
eccentricita: number;
|
|
velocita: number;
|
|
angoloIniziale: number;
|
|
massa: string;
|
|
coloreTesto: string;
|
|
}
|
|
|
|
const stelle: Stella[] = [
|
|
{
|
|
nome: "Alpha Cen A",
|
|
tipo: "G2V",
|
|
colore: "#fff4e0",
|
|
raggio: 18,
|
|
asseMaggiore: 175,
|
|
eccentricita: 0.517,
|
|
velocita: 0.0125, // P=79.91 anni → scala
|
|
angoloIniziale: 0,
|
|
massa: "1.1 M☉",
|
|
coloreTesto: "rgba(255,244,224,0.8)",
|
|
},
|
|
{
|
|
nome: "Alpha Cen B",
|
|
tipo: "K1V",
|
|
colore: "#ffcc66",
|
|
raggio: 14,
|
|
asseMaggiore: 215,
|
|
eccentricita: 0.517,
|
|
velocita: 0.0125,
|
|
angoloIniziale: Math.PI, // opposto ad A
|
|
massa: "0.907 M☉",
|
|
coloreTesto: "rgba(255,204,102,0.8)",
|
|
},
|
|
{
|
|
nome: "Proxima Cen",
|
|
tipo: "M5.5Ve",
|
|
colore: "#cc4422",
|
|
raggio: 10,
|
|
asseMaggiore: 650,
|
|
eccentricita: 0.509,
|
|
velocita: 0.00091, // P=547 anni → scala
|
|
angoloIniziale: Math.PI * 0.7,
|
|
massa: "0.122 M☉",
|
|
coloreTesto: "rgba(255,150,100,0.8)",
|
|
},
|
|
];
|
|
|
|
// Pianeti: [stella_ospite, dati_pianeta]
|
|
type Pianeta = [number, CorpoCeleste];
|
|
|
|
const pianeti: Pianeta[] = [
|
|
// === SU ALPHA CENTAURI B ===
|
|
[
|
|
1, // Alpha Cen B
|
|
{
|
|
nome: "Alpha Cen Ab",
|
|
raggio: 7,
|
|
asseMaggiore: 55,
|
|
eccentricita: 0.02,
|
|
velocita: 1.63, // 224 giorni → scala: 10s orbita
|
|
colore: "#5a8ab5",
|
|
angoli: [0],
|
|
dettagli: [
|
|
{ tipo: "oceano", colore: "#3a6a9a", x: -2, y: -1, r: 3 },
|
|
{ tipo: "continente", colore: "#4a8a4a", x: 2, y: 1, r: 2.5 },
|
|
{ tipo: "nuvola", colore: "rgba(255,255,255,0.25)", x: 0, y: -2, r: 1.5 },
|
|
],
|
|
},
|
|
],
|
|
|
|
// === SU PROXIMA CENTAURI ===
|
|
[
|
|
2, // Proxima Centauri
|
|
{
|
|
nome: "Proxima d",
|
|
raggio: 3,
|
|
asseMaggiore: 30,
|
|
eccentricita: 0.04,
|
|
velocita: 2.094, // 10 secondi orbita
|
|
colore: "#6b7b8d",
|
|
angoli: [0],
|
|
dettagli: [
|
|
{ tipo: "superficie", colore: "#5a6a7a", x: -1, y: -1, r: 1.5 },
|
|
{ tipo: "superficie", colore: "#7a8a9a", x: 1, y: 1, r: 1 },
|
|
],
|
|
},
|
|
],
|
|
[
|
|
2,
|
|
{
|
|
nome: "Proxima b",
|
|
raggio: 8,
|
|
asseMaggiore: 50,
|
|
eccentricita: 0.11,
|
|
velocita: 0.959, // ~22 secondi orbita
|
|
colore: "#4a90d9",
|
|
angoli: [0],
|
|
dettagli: [
|
|
{ tipo: "oceano", colore: "#2a5a8a", x: -3, y: -2, r: 4 },
|
|
{ tipo: "continente", colore: "#3a7a3a", x: 2, y: 1, r: 3 },
|
|
{ tipo: "continente", colore: "#4a8a4a", x: -1, y: 3, r: 2.5 },
|
|
{ tipo: "nuvola", colore: "rgba(255,255,255,0.3)", x: 0, y: -3, r: 2 },
|
|
],
|
|
},
|
|
],
|
|
[
|
|
2,
|
|
{
|
|
nome: "Proxima c",
|
|
raggio: 14,
|
|
asseMaggiore: 200,
|
|
eccentricita: 0.04,
|
|
velocita: 0.00559, // ~62 minuti orbita
|
|
colore: "#c8944a",
|
|
angoli: [0],
|
|
raggiMondi: [35, 55, 75],
|
|
coloriMondi: ["#d4c4a4", "#b4a484", "#948464"],
|
|
nomiMondi: ["Candidate-m1", "Candidate-m2", "Candidate-m3"],
|
|
velocitaMondi: [8, 4, 2.5],
|
|
anelli: true,
|
|
dettagli: [
|
|
{ tipo: "banda", colore: "#a8743a", y: -4 },
|
|
{ tipo: "banda", colore: "#b8844a", y: 0 },
|
|
{ tipo: "banda", colore: "#98642a", y: 4 },
|
|
],
|
|
},
|
|
],
|
|
];
|
|
|
|
// === FUNZIONI DI DISEGNO ===
|
|
|
|
function disegnaStelle() {
|
|
stelleSfondo.forEach((s) => {
|
|
ctx.fillStyle = `rgba(255,255,255,${s.a})`;
|
|
ctx.beginPath();
|
|
ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
});
|
|
}
|
|
|
|
function disegnaStella(stella: Stella, x: number, y: number) {
|
|
// Glow
|
|
const grad = ctx.createRadialGradient(x, y, stella.raggio * 0.3, x, y, stella.raggio * 4);
|
|
grad.addColorStop(0, stella.colore);
|
|
grad.addColorStop(0.3, stella.colore.replace(")", ",0.5)").replace("#", "rgba(").replace(/(..)(..)(..)/, (m, r, g, b) => {
|
|
const red = parseInt(r, 16);
|
|
const green = parseInt(g, 16);
|
|
const blue = parseInt(b, 16);
|
|
return `rgba(${red},${green},${blue}`;
|
|
}) + ",0.3)");
|
|
grad.addColorStop(1, "rgba(0,0,0,0)");
|
|
|
|
// Glow semplificato per tipo di stella
|
|
if (stella.tipo === "G2V") {
|
|
// Gialla come il Sole
|
|
const g = ctx.createRadialGradient(x, y, stella.raggio * 0.5, x, y, stella.raggio * 5);
|
|
g.addColorStop(0, "#fff8e0");
|
|
g.addColorStop(0.2, "#ffdd44");
|
|
g.addColorStop(0.5, "rgba(255,221,68,0.2)");
|
|
g.addColorStop(1, "rgba(255,200,0,0)");
|
|
ctx.fillStyle = g;
|
|
} else if (stella.tipo === "K1V") {
|
|
// Arancione
|
|
const g = ctx.createRadialGradient(x, y, stella.raggio * 0.5, x, y, stella.raggio * 4);
|
|
g.addColorStop(0, "#ffe0a0");
|
|
g.addColorStop(0.2, "#ffaa44");
|
|
g.addColorStop(0.5, "rgba(255,170,68,0.2)");
|
|
g.addColorStop(1, "rgba(255,150,0,0)");
|
|
ctx.fillStyle = g;
|
|
} else {
|
|
// Rossa (Proxima)
|
|
const g = ctx.createRadialGradient(x, y, stella.raggio * 0.3, x, y, stella.raggio * 4);
|
|
g.addColorStop(0, "rgba(255,100,50,0.8)");
|
|
g.addColorStop(0.2, "rgba(200,50,20,0.4)");
|
|
g.addColorStop(0.5, "rgba(150,30,10,0.1)");
|
|
g.addColorStop(1, "rgba(100,20,5,0)");
|
|
ctx.fillStyle = g;
|
|
}
|
|
|
|
ctx.beginPath();
|
|
ctx.arc(x, y, stella.raggio * 5, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
|
|
// Stella
|
|
ctx.fillStyle = stella.colore;
|
|
ctx.shadowColor = stella.colore;
|
|
ctx.shadowBlur = stella.raggio * 2;
|
|
ctx.beginPath();
|
|
ctx.arc(x, y, stella.raggio, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
ctx.shadowBlur = 0;
|
|
}
|
|
|
|
function disegnaAnelli(cx: number, cy: number, raggio: number) {
|
|
ctx.strokeStyle = "rgba(210, 180, 140, 0.4)";
|
|
ctx.lineWidth = 3;
|
|
ctx.beginPath();
|
|
ctx.ellipse(cx, cy, raggio * 2.0, raggio * 0.5, 0, 0, Math.PI * 2);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeStyle = "rgba(190, 160, 120, 0.25)";
|
|
ctx.lineWidth = 2;
|
|
ctx.beginPath();
|
|
ctx.ellipse(cx, cy, raggio * 2.4, raggio * 0.6, 0, 0, Math.PI * 2);
|
|
ctx.stroke();
|
|
}
|
|
|
|
function disegnaOrbita(cx: number, cy: number, a: number, b: number) {
|
|
ctx.strokeStyle = "rgba(255,255,255,0.06)";
|
|
ctx.lineWidth = 1;
|
|
ctx.setLineDash([3, 3]);
|
|
ctx.beginPath();
|
|
ctx.ellipse(cx, cy, a, b, 0, 0, Math.PI * 2);
|
|
ctx.stroke();
|
|
ctx.setLineDash([]);
|
|
}
|
|
|
|
function disegnaDettaglioPianeta(
|
|
dettagli: Dettaglio[],
|
|
x: number,
|
|
y: number,
|
|
raggio: number
|
|
) {
|
|
dettagli.forEach((d) => {
|
|
ctx.fillStyle = d.colore;
|
|
ctx.beginPath();
|
|
ctx.arc(x + (d.x || 0), y + (d.y || 0), d.r || 1, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
});
|
|
}
|
|
|
|
function disegnaCorpo(
|
|
c: CorpoCeleste,
|
|
stellaX: number,
|
|
stellaY: number,
|
|
angolo: number
|
|
) {
|
|
const a = c.asseMaggiore;
|
|
const b = a * Math.sqrt(1 - c.eccentricita * c.eccentricita);
|
|
const x = stellaX + a * Math.cos(angolo);
|
|
const y = stellaY + b * Math.sin(angolo);
|
|
|
|
// Orbita
|
|
disegnaOrbita(stellaX, stellaY, a, b);
|
|
|
|
// Anelli
|
|
if (c.anelli) {
|
|
disegnaAnelli(x, y, c.raggio);
|
|
}
|
|
|
|
// Pianeta
|
|
ctx.fillStyle = c.colore;
|
|
ctx.beginPath();
|
|
ctx.arc(x, y, c.raggio, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
|
|
// Dettagli
|
|
if (c.dettagli) {
|
|
disegnaDettaglioPianeta(c.dettagli, x, y, c.raggio);
|
|
}
|
|
|
|
// Lune
|
|
if (c.raggiMondi && c.coloriMondi) {
|
|
const coloriM = c.coloriMondi;
|
|
c.raggiMondi.forEach((raggioM, i) => {
|
|
const velocitaM = c.velocitaMondi?.[i] ?? 3;
|
|
const angoloM = angolo + (c.angoli?.[i] || 0) + tempo * velocitaM;
|
|
const mx = stellaX + Math.cos(angoloM) * raggioM;
|
|
const my = stellaY + Math.sin(angoloM) * raggioM;
|
|
|
|
ctx.strokeStyle = "rgba(255,255,255,0.04)";
|
|
ctx.lineWidth = 0.5;
|
|
ctx.setLineDash([2, 2]);
|
|
ctx.beginPath();
|
|
ctx.arc(stellaX, stellaY, raggioM, 0, Math.PI * 2);
|
|
ctx.stroke();
|
|
ctx.setLineDash([]);
|
|
|
|
ctx.fillStyle = coloriM[i];
|
|
ctx.beginPath();
|
|
ctx.arc(mx, my, 2, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
|
|
ctx.fillStyle = "rgba(255,255,255,0.3)";
|
|
ctx.font = "7px monospace";
|
|
ctx.fillText(c.nomiMondi?.[i] || "", mx + 3, my - 3);
|
|
});
|
|
}
|
|
|
|
// Etichetta
|
|
ctx.fillStyle = "rgba(255,255,255,0.6)";
|
|
ctx.font = "11px monospace";
|
|
ctx.fillText(c.nome, x + c.raggio + 5, y - 5);
|
|
}
|
|
|
|
function disegnaLineaTraStelle(x1: number, y1: number, x2: number, y2: number) {
|
|
ctx.strokeStyle = "rgba(255,255,255,0.03)";
|
|
ctx.lineWidth = 1;
|
|
ctx.setLineDash([5, 10]);
|
|
ctx.beginPath();
|
|
ctx.moveTo(x1, y1);
|
|
ctx.lineTo(x2, y2);
|
|
ctx.stroke();
|
|
ctx.setLineDash([]);
|
|
}
|
|
|
|
function animazione() {
|
|
// Sfondo
|
|
ctx.fillStyle = "#000010";
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Stelle
|
|
disegnaStelle();
|
|
|
|
// Centro del sistema (baricentro A-B)
|
|
const cx = canvas.width / 2;
|
|
const cy = canvas.height / 2;
|
|
|
|
// Calcola posizioni stelle relative al baricentro
|
|
const posizioniStelle: { x: number; y: number }[] = [];
|
|
|
|
stelle.forEach((s) => {
|
|
const a = s.asseMaggiore;
|
|
const b = a * Math.sqrt(1 - s.eccentricita * s.eccentricita);
|
|
const angolo = tempo * s.velocita + s.angoloIniziale;
|
|
const x = cx + a * Math.cos(angolo);
|
|
const y = cy + b * Math.sin(angolo);
|
|
posizioniStelle.push({ x, y });
|
|
});
|
|
|
|
// Calcola baricentro del triangolo formato dalle tre stelle
|
|
const baricentroX = (posizioniStelle[0].x + posizioniStelle[1].x + posizioniStelle[2].x) / 3;
|
|
const baricentroY = (posizioniStelle[0].y + posizioniStelle[1].y + posizioniStelle[2].y) / 3;
|
|
|
|
// Offset per centrare tutto il sistema sul canvas
|
|
const offsetX = baricentroX - cx;
|
|
const offsetY = baricentroY - cy;
|
|
|
|
// Linea tra Alpha Cen A e B
|
|
disegnaLineaTraStelle(
|
|
posizioniStelle[0].x - offsetX,
|
|
posizioniStelle[0].y - offsetY,
|
|
posizioniStelle[1].x - offsetX,
|
|
posizioniStelle[1].y - offsetY
|
|
);
|
|
|
|
// Disegna stelle
|
|
stelle.forEach((s, i) => {
|
|
disegnaStella(s, posizioniStelle[i].x - offsetX, posizioniStelle[i].y - offsetY);
|
|
});
|
|
|
|
// Pianeti
|
|
pianeti.forEach(([stellaIdx, p]) => {
|
|
const angolo = tempo * p.velocita;
|
|
disegnaCorpo(p, posizioniStella[stellaIdx].x - offsetX, posizioniStelle[stellaIdx].y - offsetY, angolo);
|
|
});
|
|
|
|
// Info
|
|
ctx.fillStyle = "rgba(255,255,255,0.4)";
|
|
ctx.font = "10px monospace";
|
|
ctx.fillText(
|
|
"Alpha Centauri — Sistema triplo (4.37 anni luce) | A+B orbita: 79.9 anni | Proxima orbita: 547 anni",
|
|
10,
|
|
canvas.height - 10
|
|
);
|
|
|
|
tempo += 0.005;
|
|
requestAnimationFrame(animazione);
|
|
}
|
|
|
|
// Stelle di sfondo
|
|
const stelleSfondo: { x: number; y: number; r: number; a: number }[] = [];
|
|
for (let i = 0; i < 300; i++) {
|
|
stelleSfondo.push({
|
|
x: Math.random() * canvas.width,
|
|
y: Math.random() * canvas.height,
|
|
r: Math.random() * 1.2,
|
|
a: Math.random() * 0.5 + 0.2,
|
|
});
|
|
}
|
|
|
|
// Resize
|
|
window.addEventListener("resize", () => {
|
|
canvas.width = window.innerWidth;
|
|
canvas.height = window.innerHeight;
|
|
});
|
|
|
|
// Avvia
|
|
animazione();
|