feat: adiciona constelações astronômicas opcionais
This commit is contained in:
parent
820f941b4f
commit
740c9b836b
6 changed files with 191 additions and 0 deletions
|
|
@ -14,6 +14,9 @@
|
||||||
<entry name="ChuvaMode" type="Bool">
|
<entry name="ChuvaMode" type="Bool">
|
||||||
<default>false</default>
|
<default>false</default>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry name="ShowConstellations" type="Bool">
|
||||||
|
<default>true</default>
|
||||||
|
</entry>
|
||||||
<entry name="Latitude" type="Double">
|
<entry name="Latitude" type="Double">
|
||||||
<default>-24.72</default>
|
<default>-24.72</default>
|
||||||
</entry>
|
</entry>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ ColumnLayout {
|
||||||
property alias cfg_ShowSkeleton: skeletonCheck.checked
|
property alias cfg_ShowSkeleton: skeletonCheck.checked
|
||||||
property alias cfg_BaladaMode: baladaCheck.checked
|
property alias cfg_BaladaMode: baladaCheck.checked
|
||||||
property alias cfg_ChuvaMode: chuvaCheck.checked
|
property alias cfg_ChuvaMode: chuvaCheck.checked
|
||||||
|
property alias cfg_ShowConstellations: constellationsCheck.checked
|
||||||
property double cfg_Latitude
|
property double cfg_Latitude
|
||||||
property double cfg_Longitude
|
property double cfg_Longitude
|
||||||
|
|
||||||
|
|
@ -37,6 +38,12 @@ ColumnLayout {
|
||||||
onCheckedChanged: if (checked) baladaCheck.checked = false
|
onCheckedChanged: if (checked) baladaCheck.checked = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
id: constellationsCheck
|
||||||
|
Kirigami.FormData.label: i18n("Constelações:")
|
||||||
|
text: i18n("Ligar estrelas e mostrar os nomes")
|
||||||
|
}
|
||||||
|
|
||||||
Kirigami.Separator { Kirigami.FormData.isSection: true }
|
Kirigami.Separator { Kirigami.FormData.isSection: true }
|
||||||
|
|
||||||
// Observador do céu realista (aceita vírgula ou ponto decimal)
|
// Observador do céu realista (aceita vírgula ou ponto decimal)
|
||||||
|
|
|
||||||
21
plugin/contents/ui/constellations.js
Normal file
21
plugin/contents/ui/constellations.js
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1200,6 +1200,7 @@ body.chuva #sunChuvaFace { opacity: 1; transition: opacity 5s ease; }
|
||||||
</div><!-- .scene -->
|
</div><!-- .scene -->
|
||||||
|
|
||||||
<script src="starcatalog.js"></script>
|
<script src="starcatalog.js"></script>
|
||||||
|
<script src="constellations.js"></script>
|
||||||
<script>
|
<script>
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
CONSTANTS
|
CONSTANTS
|
||||||
|
|
@ -1217,6 +1218,7 @@ const canvas = document.getElementById('starfield');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
let obsLat = -24.72, obsLon = -53.74; // Toledo-PR; sobrescrito pela config
|
let obsLat = -24.72, obsLon = -53.74; // Toledo-PR; sobrescrito pela config
|
||||||
|
let showConstellations = false;
|
||||||
const VIEW_AZ = 90; // centro da tela olha para o LESTE — a tela física do
|
const VIEW_AZ = 90; // centro da tela olha para o LESTE — a tela física do
|
||||||
// usuário está voltada p/ leste, então o wallpaper age
|
// usuário está voltada p/ leste, então o wallpaper age
|
||||||
// como janela: estrelas nascem subindo dentro da cena
|
// como janela: estrelas nascem subindo dentro da cena
|
||||||
|
|
@ -1398,6 +1400,73 @@ function renderMilkyWay(lstDeg, glareOn) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Figuras convencionais das 88 constelações, ancoradas em RA/Dec J2000.
|
||||||
|
São desenhadas antes das estrelas para os pontos reais ficarem por cima. */
|
||||||
|
function drawConstellations(c, lst, W, H, horizonPx) {
|
||||||
|
if (!showConstellations || typeof CONSTELLATIONS === 'undefined') return;
|
||||||
|
const rankAlpha = [0, 0.52, 0.38, 0.25];
|
||||||
|
const rankWidth = [0, 1.35, 1.05, 0.82];
|
||||||
|
|
||||||
|
c.save();
|
||||||
|
c.lineCap = 'round';
|
||||||
|
c.lineJoin = 'round';
|
||||||
|
c.shadowColor = 'rgba(60,185,255,0.65)';
|
||||||
|
c.shadowBlur = 7;
|
||||||
|
for (const constellation of CONSTELLATIONS) {
|
||||||
|
const rank = Math.max(1, Math.min(3, constellation.rank || 3));
|
||||||
|
c.strokeStyle = `rgba(105,205,255,${rankAlpha[rank]})`;
|
||||||
|
c.lineWidth = rankWidth[rank];
|
||||||
|
for (const line of constellation.lines) {
|
||||||
|
c.beginPath();
|
||||||
|
let previous = null;
|
||||||
|
for (const point of line) {
|
||||||
|
const aa = altAz(point[0], point[1], lst);
|
||||||
|
const sc = skyToScreen(aa.alt, aa.az, W, horizonPx);
|
||||||
|
if (!sc) {
|
||||||
|
previous = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (previous && Math.hypot(sc.x - previous.x, sc.y - previous.y) > W * 0.34) {
|
||||||
|
c.moveTo(sc.x, sc.y);
|
||||||
|
previous = sc;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (previous) c.lineTo(sc.x, sc.y);
|
||||||
|
else c.moveTo(sc.x, sc.y);
|
||||||
|
previous = sc;
|
||||||
|
}
|
||||||
|
c.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nomes só nas figuras principais/intermediárias para não lotar a tela. */
|
||||||
|
c.shadowBlur = 5;
|
||||||
|
c.font = `${Math.max(10, Math.round(H * 0.0105))}px ui-monospace, monospace`;
|
||||||
|
c.textAlign = 'center';
|
||||||
|
c.textBaseline = 'middle';
|
||||||
|
c.fillStyle = 'rgba(170,225,255,0.66)';
|
||||||
|
const occupied = [];
|
||||||
|
for (const constellation of CONSTELLATIONS) {
|
||||||
|
if (constellation.rank > 2 || !constellation.label) continue;
|
||||||
|
const aa = altAz(constellation.label[0], constellation.label[1], lst);
|
||||||
|
const sc = skyToScreen(aa.alt, aa.az, W, horizonPx);
|
||||||
|
if (!sc || sc.y < 24 || sc.y > horizonPx - 18) continue;
|
||||||
|
const width = c.measureText(constellation.name).width + 14;
|
||||||
|
const box = { x1: sc.x - width / 2, y1: sc.y - 9,
|
||||||
|
x2: sc.x + width / 2, y2: sc.y + 9 };
|
||||||
|
if (occupied.some(o => box.x1 < o.x2 && box.x2 > o.x1 &&
|
||||||
|
box.y1 < o.y2 && box.y2 > o.y1)) continue;
|
||||||
|
occupied.push(box);
|
||||||
|
c.fillText(constellation.name, sc.x, sc.y);
|
||||||
|
}
|
||||||
|
c.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setShowConstellations(on) {
|
||||||
|
showConstellations = !!on;
|
||||||
|
projectSky();
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Passo de projeção: recalcula posições de tela (a cada 30s o céu gira
|
/* ── Passo de projeção: recalcula posições de tela (a cada 30s o céu gira
|
||||||
~0.125°, imperceptível). Camada estática (Via Láctea + estrelas fracas)
|
~0.125°, imperceptível). Camada estática (Via Láctea + estrelas fracas)
|
||||||
é pré-renderizada em baseCanvas; só as brilhantes cintilam por frame ── */
|
é pré-renderizada em baseCanvas; só as brilhantes cintilam por frame ── */
|
||||||
|
|
@ -1431,6 +1500,8 @@ function projectSky() {
|
||||||
bctx.restore();
|
bctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawConstellations(bctx, lst, W, H, horizonPx);
|
||||||
|
|
||||||
for (let i = 0; i < STAR_DATA.length; i++) {
|
for (let i = 0; i < STAR_DATA.length; i++) {
|
||||||
const [ra, dec, mag, ci] = STAR_DATA[i];
|
const [ra, dec, mag, ci] = STAR_DATA[i];
|
||||||
const aa = altAz(ra, dec, lst);
|
const aa = altAz(ra, dec, lst);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ WallpaperItem {
|
||||||
webView.runJavaScript("setShowSkeleton(" + Plasmoid.configuration.ShowSkeleton + ")")
|
webView.runJavaScript("setShowSkeleton(" + Plasmoid.configuration.ShowSkeleton + ")")
|
||||||
webView.runJavaScript("setBaladaMode(" + Plasmoid.configuration.BaladaMode + ")")
|
webView.runJavaScript("setBaladaMode(" + Plasmoid.configuration.BaladaMode + ")")
|
||||||
webView.runJavaScript("setChuvaMode(" + Plasmoid.configuration.ChuvaMode + ")")
|
webView.runJavaScript("setChuvaMode(" + Plasmoid.configuration.ChuvaMode + ")")
|
||||||
|
webView.runJavaScript("setShowConstellations(" + Plasmoid.configuration.ShowConstellations + ")")
|
||||||
webView.runJavaScript("setObserverLocation(" + Plasmoid.configuration.Latitude + ","
|
webView.runJavaScript("setObserverLocation(" + Plasmoid.configuration.Latitude + ","
|
||||||
+ Plasmoid.configuration.Longitude + ")")
|
+ Plasmoid.configuration.Longitude + ")")
|
||||||
}
|
}
|
||||||
|
|
@ -20,6 +21,7 @@ WallpaperItem {
|
||||||
function onShowSkeletonChanged() { applyConfig() }
|
function onShowSkeletonChanged() { applyConfig() }
|
||||||
function onBaladaModeChanged() { applyConfig() }
|
function onBaladaModeChanged() { applyConfig() }
|
||||||
function onChuvaModeChanged() { applyConfig() }
|
function onChuvaModeChanged() { applyConfig() }
|
||||||
|
function onShowConstellationsChanged() { applyConfig() }
|
||||||
function onLatitudeChanged() { applyConfig() }
|
function onLatitudeChanged() { applyConfig() }
|
||||||
function onLongitudeChanged() { applyConfig() }
|
function onLongitudeChanged() { applyConfig() }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
87
tools/build_constellations.py
Normal file
87
tools/build_constellations.py
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Gera constellations.js com figuras convencionais em coordenadas J2000.
|
||||||
|
|
||||||
|
Fonte: d3-celestial, de Olaf Frohn, licença BSD-3-Clause.
|
||||||
|
Os dados são compactados para uso offline pelo wallpaper.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import urllib.request
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
BASE = "https://raw.githubusercontent.com/ofrohn/d3-celestial/master/data/"
|
||||||
|
OUT = Path(__file__).resolve().parent.parent / "plugin/contents/ui/constellations.js"
|
||||||
|
|
||||||
|
LICENSE = """Copyright (c) 2015, Olaf Frohn
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holder nor contributors may be used to
|
||||||
|
endorse or promote products derived from this software without permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DAMAGES ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def fetch(name: str) -> dict:
|
||||||
|
req = urllib.request.Request(BASE + name, headers={"User-Agent": "skeledance-build/1.0"})
|
||||||
|
return json.loads(urllib.request.urlopen(req, timeout=30).read())
|
||||||
|
|
||||||
|
|
||||||
|
def rounded_point(point: list[float]) -> list[float]:
|
||||||
|
return [round(float(point[0]), 4), round(float(point[1]), 4)]
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
line_data = fetch("constellations.lines.json")["features"]
|
||||||
|
name_data = fetch("constellations.json")["features"]
|
||||||
|
metadata = {
|
||||||
|
feature["id"]: {
|
||||||
|
"name": feature["properties"].get("name", feature["id"]),
|
||||||
|
"label": rounded_point(feature["geometry"]["coordinates"]),
|
||||||
|
}
|
||||||
|
for feature in name_data
|
||||||
|
}
|
||||||
|
|
||||||
|
merged: dict[str, dict] = {}
|
||||||
|
for feature in line_data:
|
||||||
|
ident = feature["id"]
|
||||||
|
item = merged.setdefault(
|
||||||
|
ident,
|
||||||
|
{
|
||||||
|
"id": ident,
|
||||||
|
"name": metadata.get(ident, {}).get("name", ident),
|
||||||
|
"rank": int(feature["properties"].get("rank", 3)),
|
||||||
|
"label": metadata.get(ident, {}).get("label"),
|
||||||
|
"lines": [],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
item["rank"] = min(item["rank"], int(feature["properties"].get("rank", 3)))
|
||||||
|
item["lines"].extend(
|
||||||
|
[[rounded_point(point) for point in line]
|
||||||
|
for line in feature["geometry"]["coordinates"]]
|
||||||
|
)
|
||||||
|
|
||||||
|
payload = json.dumps(list(merged.values()), ensure_ascii=False, separators=(",", ":"))
|
||||||
|
OUT.write_text(
|
||||||
|
"/* Gerado por tools/build_constellations.py.\n"
|
||||||
|
" d3-celestial constellation lines, coordenadas equatoriais J2000.\n\n"
|
||||||
|
+ "\n".join(" " + line for line in LICENSE.rstrip().splitlines())
|
||||||
|
+ " */\nconst CONSTELLATIONS=" + payload + ";\n",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
print(f"{len(merged)} constelações -> {OUT} ({OUT.stat().st_size / 1024:.0f} KB)")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue