feat(prezentacja): linie aspektów na kosmogramie (PRE-12, etap 3)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m36s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m35s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 28s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 21s
build / build (push) Successful in 48s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m34s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m36s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 31s
Testy / Kontrola składni wszystkich warstw (push) Successful in 17s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m36s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m35s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 28s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 21s
build / build (push) Successful in 48s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m34s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m36s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 31s
Testy / Kontrola składni wszystkich warstw (push) Successful in 17s
Trzeci etap rysowania koła: linie aspektów w środku. Domyka rdzeń PRE-12 — kosmogram ma teraz znaki, domy, osie, obiekty i aspekty. Linie łączą PRAWDZIWE pozycje obiektów (nie rozsunięte glify — aspekt dotyczy tego, gdzie planeta faktycznie stoi) na okręgu piasty, w środku koła. Kodowanie jak w klasycznych programach: - KOLOR = charakter aspektu: niebieski harmonijny (trygon, sekstyl), czerwony napięty (kwadratura, opozycja), zielony koniunkcja. Dwa kolory na środku od razu mówią „gdzie łatwo, gdzie tarcie". - GRUBOŚĆ i JASNOŚĆ = orb: im ciaśniej, tym mocniej. Poniżej 1° wyraźne pogrubienie (wprost z wymagania) — najściślejsze aspekty rzucają się w oczy, a szerokie ledwo majaczą, żeby nie robić ze środka plątaniny. Rysowane jako pierwsze, pod resztą: obiekty siedzą na R_PLANET=150, daleko od piasty (R_HUB=48), więc glify i linie się nie stykają, a osie i szprychy lądują na wierzchu. Motyw druku (PDF, PRE-24) dostaje własne, ciemniejsze kolory aspektów bez zmiennych CSS — samodzielny konwerter SVG arkusza nie widzi. Weryfikacja na horoskopie referencyjnym: 24 aspekty, 5 ciasnych (<1°) faktycznie pogrubionych; kolory zgodne z typem (9 czerwonych napiętych, 10 niebieskich harmonijnych, 5 zielonych koniunkcji); print bez zmiennych CSS. Sprawdzone wizualnie — pełny aspektarian, czytelny. Testy: 8 nowych (linie obecne, kolor wg typu, pogrubienie <1°, prawdziwa pozycja nie rozsunięta, pominięcie aspektu do obiektu bez pozycji, brak aspektów, motyw druku). Całość: prezentacja 138 passed. PRE-12 -> Zrobione. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #36.
This commit is contained in:
@@ -193,3 +193,79 @@ def test_empty_when_cusps_lack_longitude():
|
||||
for c in chart["cusps"]:
|
||||
del c["decimal"]
|
||||
assert chartwheel.render(chart) == ""
|
||||
|
||||
|
||||
# ───────────────────────────── linie aspektów ────────────────────────────
|
||||
|
||||
def _chart_with_aspects():
|
||||
chart = _chart_with_objects()
|
||||
chart["positions"].append({"name": "Mars", "decimal": 220.0, "glyph": "♂", "direction": "D"})
|
||||
chart["aspects"] = [
|
||||
{"obj1": "Sun", "obj2": "Mars", "aspect": "trine", "orb": 0.2, "allowed": 8.0},
|
||||
{"obj1": "Moon", "obj2": "Mars", "aspect": "square", "orb": 5.0, "allowed": 8.0},
|
||||
{"obj1": "Mercury", "obj2": "Venus", "aspect": "conjunction", "orb": 0.4, "allowed": 10.0},
|
||||
]
|
||||
return chart
|
||||
|
||||
|
||||
def test_aspect_lines_are_drawn():
|
||||
"""Każdy aspekt, którego oba obiekty mają pozycję, dostaje linię — porównujemy
|
||||
TEN SAM wykres z aspektami i bez, żeby różnica była wyłącznie aspektami."""
|
||||
chart = _chart_with_aspects()
|
||||
with_asp = chartwheel.render(chart).count("<line")
|
||||
chart_no = _chart_with_aspects()
|
||||
chart_no["aspects"] = []
|
||||
without = chartwheel.render(chart_no).count("<line")
|
||||
assert with_asp - without == 3
|
||||
|
||||
|
||||
def test_aspect_color_encodes_type():
|
||||
"""Niebieski = harmonijny, czerwony = napięty, zielony = koniunkcja."""
|
||||
svg = chartwheel.render(_chart_with_aspects())
|
||||
assert "#6aa6c9" in svg # trine — harmonijny (niebieski)
|
||||
assert "#cf6a6a" in svg # square — napięty (czerwony)
|
||||
assert "#8fae7a" in svg # conjunction — zielony
|
||||
|
||||
|
||||
def test_tight_aspect_is_bold():
|
||||
"""Poniżej 1° linia pogrubiona (2.0) — wprost z wymagania. Szeroki aspekt
|
||||
(square, orb 5°) NIE jest pogrubiony."""
|
||||
svg = chartwheel.render(_chart_with_aspects())
|
||||
assert 'stroke-width="2.0"' in svg # Sun–Mars trine 0.2° i Mercury–Venus 0.4°
|
||||
# dwa ciasne aspekty → dwie pogrubione linie
|
||||
assert svg.count('stroke-width="2.0"') == 2
|
||||
|
||||
|
||||
def test_aspect_uses_true_position_not_spread():
|
||||
"""Linia aspektu łączy PRAWDZIWE pozycje. Mercury(27.36) i Venus(0.41° od
|
||||
siebie) są rozsuwane jako glify, ale linia koniunkcji ma iść między ich
|
||||
faktycznymi punktami na piaście."""
|
||||
chart = _chart_with_aspects()
|
||||
asc = chart["angles"]["Asc"]["decimal"]
|
||||
# punkt Wenus na piaście z prawdziwej długości
|
||||
vx, vy = chartwheel._pt(27.77, asc, chartwheel.R_HUB)
|
||||
svg = chartwheel.render(chart)
|
||||
assert f'x1="{vx:.2f}"' in svg or f'x2="{vx:.2f}"' in svg
|
||||
|
||||
|
||||
def test_aspect_to_missing_object_is_skipped():
|
||||
"""Aspekt do obiektu bez pozycji nie może wywalić rysunku."""
|
||||
chart = _chart_with_aspects()
|
||||
chart["aspects"].append(
|
||||
{"obj1": "Sun", "obj2": "Chiron", "aspect": "trine", "orb": 1.0, "allowed": 8.0})
|
||||
svg = chartwheel.render(chart)
|
||||
assert svg and "☉" in svg
|
||||
|
||||
|
||||
def test_no_aspect_lines_without_aspects():
|
||||
chart = _chart_with_objects() # bez klucza 'aspects'
|
||||
a = chartwheel.render(chart).count("<line")
|
||||
chart["aspects"] = []
|
||||
assert chartwheel.render(chart).count("<line") == a
|
||||
|
||||
|
||||
def test_print_theme_aspect_colors_have_no_css_vars():
|
||||
"""Motyw druku (PDF) — konkretne kolory aspektów, bez zmiennych CSS."""
|
||||
svg = chartwheel.render(_chart_with_aspects(), theme="print")
|
||||
assert "var(--" not in svg
|
||||
assert "#a83232" in svg # square napięty w wariancie druku
|
||||
|
||||
Reference in New Issue
Block a user