kerykeion 4.8.1__py3-none-any.whl → 4.14.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kerykeion might be problematic. Click here for more details.
- kerykeion/__init__.py +3 -95
- kerykeion/aspects/aspects_utils.py +10 -21
- kerykeion/aspects/natal_aspects.py +9 -2
- kerykeion/aspects/synastry_aspects.py +11 -4
- kerykeion/astrological_subject.py +386 -146
- kerykeion/charts/charts_utils.py +390 -25
- kerykeion/charts/kerykeion_chart_svg.py +162 -439
- kerykeion/charts/templates/chart.xml +381 -358
- kerykeion/enums.py +1 -0
- kerykeion/ephemeris_data.py +174 -0
- kerykeion/fetch_geonames.py +2 -3
- kerykeion/kr_types/chart_types.py +4 -9
- kerykeion/kr_types/kr_literals.py +87 -54
- kerykeion/kr_types/kr_models.py +75 -97
- kerykeion/kr_types/settings_models.py +14 -28
- kerykeion/settings/kr.config.json +19 -5
- kerykeion/utilities.py +40 -23
- {kerykeion-4.8.1.dist-info → kerykeion-4.14.2.dist-info}/METADATA +128 -32
- kerykeion-4.14.2.dist-info/RECORD +33 -0
- kerykeion-4.8.1.dist-info/RECORD +0 -32
- {kerykeion-4.8.1.dist-info → kerykeion-4.14.2.dist-info}/LICENSE +0 -0
- {kerykeion-4.8.1.dist-info → kerykeion-4.14.2.dist-info}/WHEEL +0 -0
- {kerykeion-4.8.1.dist-info → kerykeion-4.14.2.dist-info}/entry_points.txt +0 -0
kerykeion/charts/charts_utils.py
CHANGED
|
@@ -2,6 +2,8 @@ import math
|
|
|
2
2
|
import datetime
|
|
3
3
|
from kerykeion.kr_types import KerykeionException, ChartType
|
|
4
4
|
from typing import Union
|
|
5
|
+
from kerykeion.kr_types.kr_models import AspectModel
|
|
6
|
+
from kerykeion.kr_types.settings_models import KerykeionLanguageCelestialPointModel, KerykeionSettingsAspectModel
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
def decHourJoin(inH: int, inM: int, inS: int) -> float:
|
|
@@ -126,7 +128,7 @@ def draw_zodiac_slice(
|
|
|
126
128
|
|
|
127
129
|
Args:
|
|
128
130
|
- c1 (Union[int, float]): The value of c1.
|
|
129
|
-
- chart_type (
|
|
131
|
+
- chart_type (ChartType): The type of chart.
|
|
130
132
|
- seventh_house_degree_ut (Union[int, float]): The degree of the seventh house.
|
|
131
133
|
- num (int): The number of the sign. Note: In OpenAstro it did refer to self.zodiac,
|
|
132
134
|
which is a list of the signs in order, starting with Aries. Eg:
|
|
@@ -212,8 +214,7 @@ def convert_longitude_coordinate_to_string(coord: Union[int, float], east_label:
|
|
|
212
214
|
def draw_aspect_line(
|
|
213
215
|
r: Union[int, float],
|
|
214
216
|
ar: Union[int, float],
|
|
215
|
-
|
|
216
|
-
degB: Union[int, float],
|
|
217
|
+
aspect: Union[AspectModel, dict],
|
|
217
218
|
color: str,
|
|
218
219
|
seventh_house_degree_ut: Union[int, float],
|
|
219
220
|
) -> str:
|
|
@@ -222,8 +223,7 @@ def draw_aspect_line(
|
|
|
222
223
|
Args:
|
|
223
224
|
- r (Union[int, float]): The value of r.
|
|
224
225
|
- ar (Union[int, float]): The value of ar.
|
|
225
|
-
-
|
|
226
|
-
- degB (Union[int, float]): The degree of B.
|
|
226
|
+
- aspect_dict (dict): The aspect dictionary.
|
|
227
227
|
- color (str): The color of the aspect.
|
|
228
228
|
- seventh_house_degree_ut (Union[int, float]): The degree of the seventh house.
|
|
229
229
|
|
|
@@ -231,15 +231,21 @@ def draw_aspect_line(
|
|
|
231
231
|
str: The SVG line element as a string.
|
|
232
232
|
"""
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
if isinstance(aspect, dict):
|
|
235
|
+
aspect = AspectModel(**aspect)
|
|
236
|
+
|
|
237
|
+
first_offset = (int(seventh_house_degree_ut) / -1) + int(aspect["p1_abs_pos"])
|
|
235
238
|
x1 = sliceToX(0, ar, first_offset) + (r - ar)
|
|
236
239
|
y1 = sliceToY(0, ar, first_offset) + (r - ar)
|
|
237
240
|
|
|
238
|
-
second_offset = (int(seventh_house_degree_ut) / -1) + int(
|
|
241
|
+
second_offset = (int(seventh_house_degree_ut) / -1) + int(aspect["p2_abs_pos"])
|
|
239
242
|
x2 = sliceToX(0, ar, second_offset) + (r - ar)
|
|
240
243
|
y2 = sliceToY(0, ar, second_offset) + (r - ar)
|
|
241
244
|
|
|
242
|
-
out =
|
|
245
|
+
out = ""
|
|
246
|
+
out += f'<g kr:node="Aspect" kr:aspectname="{aspect['aspect']}" kr:to="{aspect['p1_name']}" kr:tooriginaldegrees="{aspect["p1_abs_pos"]}" kr:from="{aspect["p2_name"]}" kr:fromoriginaldegrees="{aspect["p2_abs_pos"]}">'
|
|
247
|
+
out += f'<line class="aspect" x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {color}; stroke-width: 1; stroke-opacity: .9;"/>'
|
|
248
|
+
out += f"</g>"
|
|
243
249
|
|
|
244
250
|
return out
|
|
245
251
|
|
|
@@ -344,19 +350,21 @@ def draw_transit_ring_degree_steps(r: Union[int, float], seventh_house_degree_ut
|
|
|
344
350
|
y2 = sliceToY(0, r + 2, offset) - 2
|
|
345
351
|
out += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: #F00; stroke-width: 1px; stroke-opacity:.9;"/>'
|
|
346
352
|
out += "</g>"
|
|
347
|
-
|
|
353
|
+
|
|
348
354
|
return out
|
|
349
355
|
|
|
350
356
|
|
|
351
|
-
def draw_degree_ring(
|
|
357
|
+
def draw_degree_ring(
|
|
358
|
+
r: Union[int, float], c1: Union[int, float], seventh_house_degree_ut: Union[int, float], stroke_color: str
|
|
359
|
+
) -> str:
|
|
352
360
|
"""Draws the degree ring.
|
|
353
|
-
|
|
361
|
+
|
|
354
362
|
Args:
|
|
355
363
|
- r (Union[int, float]): The value of r.
|
|
356
364
|
- c1 (Union[int, float]): The value of c1.
|
|
357
365
|
- seventh_house_degree_ut (Union[int, float]): The degree of the seventh house.
|
|
358
366
|
- stroke_color (str): The color of the stroke.
|
|
359
|
-
|
|
367
|
+
|
|
360
368
|
Returns:
|
|
361
369
|
str: The SVG path of the degree ring.
|
|
362
370
|
"""
|
|
@@ -374,18 +382,19 @@ def draw_degree_ring(r: Union[int, float], c1: Union[int, float], seventh_house_
|
|
|
374
382
|
|
|
375
383
|
out += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {stroke_color}; stroke-width: 1px; stroke-opacity:.9;"/>'
|
|
376
384
|
out += "</g>"
|
|
377
|
-
|
|
385
|
+
|
|
378
386
|
return out
|
|
379
387
|
|
|
388
|
+
|
|
380
389
|
def draw_transit_ring(r: Union[int, float], paper_1_color: str, zodiac_transit_ring_3_color: str) -> str:
|
|
381
390
|
"""
|
|
382
391
|
Draws the transit ring.
|
|
383
|
-
|
|
392
|
+
|
|
384
393
|
Args:
|
|
385
394
|
- r (Union[int, float]): The value of r.
|
|
386
395
|
- paper_1_color (str): The color of paper 1.
|
|
387
396
|
- zodiac_transit_ring_3_color (str): The color of the zodiac transit ring
|
|
388
|
-
|
|
397
|
+
|
|
389
398
|
Returns:
|
|
390
399
|
str: The SVG path of the transit ring.
|
|
391
400
|
"""
|
|
@@ -397,16 +406,18 @@ def draw_transit_ring(r: Union[int, float], paper_1_color: str, zodiac_transit_r
|
|
|
397
406
|
return out
|
|
398
407
|
|
|
399
408
|
|
|
400
|
-
def draw_first_circle(
|
|
409
|
+
def draw_first_circle(
|
|
410
|
+
r: Union[int, float], stroke_color: str, chart_type: ChartType, c1: Union[int, float, None] = None
|
|
411
|
+
) -> str:
|
|
401
412
|
"""
|
|
402
413
|
Draws the first circle.
|
|
403
|
-
|
|
414
|
+
|
|
404
415
|
Args:
|
|
405
416
|
- r (Union[int, float]): The value of r.
|
|
406
417
|
- color (str): The color of the circle.
|
|
407
418
|
- chart_type (ChartType): The type of chart.
|
|
408
419
|
- c1 (Union[int, float]): The value of c1.
|
|
409
|
-
|
|
420
|
+
|
|
410
421
|
Returns:
|
|
411
422
|
str: The SVG path of the first circle.
|
|
412
423
|
"""
|
|
@@ -416,29 +427,383 @@ def draw_first_circle(r: Union[int, float], stroke_color: str, chart_type: Chart
|
|
|
416
427
|
if c1 is None:
|
|
417
428
|
raise KerykeionException("c1 is None")
|
|
418
429
|
|
|
419
|
-
return
|
|
430
|
+
return (
|
|
431
|
+
f'<circle cx="{r}" cy="{r}" r="{r - c1}" style="fill: none; stroke: {stroke_color}; stroke-width: 1px; " />'
|
|
432
|
+
)
|
|
420
433
|
|
|
421
434
|
|
|
422
|
-
def draw_second_circle(
|
|
435
|
+
def draw_second_circle(
|
|
436
|
+
r: Union[int, float], stroke_color: str, fill_color: str, chart_type: ChartType, c2: Union[int, float, None] = None
|
|
437
|
+
) -> str:
|
|
423
438
|
"""
|
|
424
439
|
Draws the second circle.
|
|
425
|
-
|
|
440
|
+
|
|
426
441
|
Args:
|
|
427
442
|
- r (Union[int, float]): The value of r.
|
|
428
443
|
- stroke_color (str): The color of the stroke.
|
|
429
444
|
- fill_color (str): The color of the fill.
|
|
430
445
|
- chart_type (ChartType): The type of chart.
|
|
431
446
|
- c2 (Union[int, float]): The value of c2.
|
|
432
|
-
|
|
447
|
+
|
|
433
448
|
Returns:
|
|
434
449
|
str: The SVG path of the second circle.
|
|
435
450
|
"""
|
|
436
|
-
|
|
451
|
+
|
|
437
452
|
if chart_type == "Synastry" or chart_type == "Transit":
|
|
438
453
|
return f'<circle cx="{r}" cy="{r}" r="{r - 72}" style="fill: {fill_color}; fill-opacity:.4; stroke: {stroke_color}; stroke-opacity:.4; stroke-width: 1px" />'
|
|
439
|
-
|
|
454
|
+
|
|
440
455
|
else:
|
|
441
456
|
if c2 is None:
|
|
442
457
|
raise KerykeionException("c2 is None")
|
|
443
458
|
|
|
444
|
-
return f'<circle cx="{r}" cy="{r}" r="{r - c2}" style="fill: {fill_color}; fill-opacity:.2; stroke: {stroke_color}; stroke-opacity:.4; stroke-width: 1px" />'
|
|
459
|
+
return f'<circle cx="{r}" cy="{r}" r="{r - c2}" style="fill: {fill_color}; fill-opacity:.2; stroke: {stroke_color}; stroke-opacity:.4; stroke-width: 1px" />'
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def draw_third_circle(
|
|
463
|
+
radius: Union[int, float],
|
|
464
|
+
stroke_color: str,
|
|
465
|
+
fill_color: str,
|
|
466
|
+
chart_type: ChartType,
|
|
467
|
+
c3: Union[int, float, None] = None,
|
|
468
|
+
) -> str:
|
|
469
|
+
"""
|
|
470
|
+
Draws the third circle in an SVG chart.
|
|
471
|
+
|
|
472
|
+
Parameters:
|
|
473
|
+
- radius (Union[int, float]): The radius of the circle.
|
|
474
|
+
- stroke_color (str): The stroke color of the circle.
|
|
475
|
+
- fill_color (str): The fill color of the circle.
|
|
476
|
+
- chart_type (ChartType): The type of the chart.
|
|
477
|
+
- c3 (Union[int, float, None], optional): The radius adjustment for non-Synastry and non-Transit charts.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
- str: The SVG element as a string.
|
|
481
|
+
"""
|
|
482
|
+
if chart_type in {"Synastry", "Transit"}:
|
|
483
|
+
# For Synastry and Transit charts, use a fixed radius adjustment of 160
|
|
484
|
+
return f'<circle cx="{radius}" cy="{radius}" r="{radius - 160}" style="fill: {fill_color}; fill-opacity:.8; stroke: {stroke_color}; stroke-width: 1px" />'
|
|
485
|
+
|
|
486
|
+
else:
|
|
487
|
+
return f'<circle cx="{radius}" cy="{radius}" r="{radius - c3}" style="fill: {fill_color}; fill-opacity:.8; stroke: {stroke_color}; stroke-width: 1px" />'
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def draw_aspect_grid(stroke_color: str, available_planets_list: list, aspects_list: list) -> str:
|
|
491
|
+
"""
|
|
492
|
+
Draws the aspect grid.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
- stroke_color (str): The color of the stroke.
|
|
496
|
+
- available_planets_list (list): List of all the planets, they will be actually filtered to so if they have
|
|
497
|
+
the "is_active" key set to True inside the function to have the correct list of just the active planets.
|
|
498
|
+
- aspects_list (list): List of aspects.
|
|
499
|
+
|
|
500
|
+
"""
|
|
501
|
+
|
|
502
|
+
out = ""
|
|
503
|
+
style = f"stroke:{stroke_color}; stroke-width: 1px; stroke-opacity:.6; fill:none"
|
|
504
|
+
xindent = 380
|
|
505
|
+
yindent = 468
|
|
506
|
+
box = 14
|
|
507
|
+
counter = 0
|
|
508
|
+
|
|
509
|
+
actual_planets = []
|
|
510
|
+
for planet in available_planets_list:
|
|
511
|
+
if planet.is_active:
|
|
512
|
+
actual_planets.append(planet)
|
|
513
|
+
|
|
514
|
+
first_iteration_revers_planets = actual_planets[::-1]
|
|
515
|
+
for index, a in enumerate(first_iteration_revers_planets):
|
|
516
|
+
counter += 1
|
|
517
|
+
out += f'<rect x="{xindent}" y="{yindent}" width="{box}" height="{box}" style="{style}"/>'
|
|
518
|
+
out += f'<use transform="scale(0.4)" x="{(xindent+2)*2.5}" y="{(yindent+1)*2.5}" xlink:href="#{a["name"]}" />'
|
|
519
|
+
|
|
520
|
+
xindent = xindent + box
|
|
521
|
+
yindent = yindent - box
|
|
522
|
+
|
|
523
|
+
xorb = xindent
|
|
524
|
+
yorb = yindent + box
|
|
525
|
+
|
|
526
|
+
second_iteration_revers_planets = first_iteration_revers_planets[index + 1 :]
|
|
527
|
+
for b in second_iteration_revers_planets:
|
|
528
|
+
out += f'<rect x="{xorb}" y="{yorb}" width="{box}" height="{box}" style="{style}"/>'
|
|
529
|
+
xorb = xorb + box
|
|
530
|
+
|
|
531
|
+
for aspect in aspects_list:
|
|
532
|
+
if (aspect["p1"] == a["id"] and aspect["p2"] == b["id"]) or (
|
|
533
|
+
aspect["p1"] == b["id"] and aspect["p2"] == a["id"]
|
|
534
|
+
):
|
|
535
|
+
out += f'<use x="{xorb-box+1}" y="{yorb+1}" xlink:href="#orb{aspect["aspect_degrees"]}" />'
|
|
536
|
+
|
|
537
|
+
return out
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
def draw_houses_cusps_and_text_number(
|
|
541
|
+
r: Union[int, float],
|
|
542
|
+
first_subject_houses_list_ut: list,
|
|
543
|
+
standard_house_cusp_color: str,
|
|
544
|
+
first_house_color: str,
|
|
545
|
+
tenth_house_color: str,
|
|
546
|
+
seventh_house_color: str,
|
|
547
|
+
fourth_house_color: str,
|
|
548
|
+
c1: Union[int, float],
|
|
549
|
+
c3: Union[int, float],
|
|
550
|
+
chart_type: ChartType,
|
|
551
|
+
second_subject_houses_list_ut: list = None,
|
|
552
|
+
transit_house_cusp_color: str = None,
|
|
553
|
+
) -> str:
|
|
554
|
+
"""
|
|
555
|
+
Draws the houses cusps and text numbers for a given chart type.
|
|
556
|
+
|
|
557
|
+
Parameters:
|
|
558
|
+
- r: Radius of the chart.
|
|
559
|
+
- first_subject_houses_list_ut: List of house cusps for the first subject.
|
|
560
|
+
- standard_house_cusp_color: Default color for house cusps.
|
|
561
|
+
- first_house_color: Color for the first house cusp.
|
|
562
|
+
- tenth_house_color: Color for the tenth house cusp.
|
|
563
|
+
- seventh_house_color: Color for the seventh house cusp.
|
|
564
|
+
- fourth_house_color: Color for the fourth house cusp.
|
|
565
|
+
- c1: Offset for the first subject.
|
|
566
|
+
- c3: Offset for the third subject.
|
|
567
|
+
- chart_type: Type of the chart (e.g., Transit, Synastry).
|
|
568
|
+
- second_subject_houses_list_ut: List of house cusps for the second subject (optional).
|
|
569
|
+
- transit_house_cusp_color: Color for transit house cusps (optional).
|
|
570
|
+
|
|
571
|
+
Returns:
|
|
572
|
+
- A string containing the SVG path for the houses cusps and text numbers.
|
|
573
|
+
"""
|
|
574
|
+
if chart_type in ["Transit", "Synastry"]:
|
|
575
|
+
if second_subject_houses_list_ut is None or transit_house_cusp_color is None:
|
|
576
|
+
raise KerykeionException("second_subject_houses_list_ut or transit_house_cusp_color is None")
|
|
577
|
+
|
|
578
|
+
path = ""
|
|
579
|
+
xr = 12
|
|
580
|
+
|
|
581
|
+
for i in range(xr):
|
|
582
|
+
# Determine offsets based on chart type
|
|
583
|
+
dropin, roff, t_roff = (160, 72, 36) if chart_type in ["Transit", "Synastry"] else (c3, c1, None)
|
|
584
|
+
|
|
585
|
+
# Calculate the offset for the current house cusp
|
|
586
|
+
offset = (int(first_subject_houses_list_ut[int(xr / 2)]) / -1) + int(first_subject_houses_list_ut[i])
|
|
587
|
+
|
|
588
|
+
# Calculate the coordinates for the house cusp lines
|
|
589
|
+
x1 = sliceToX(0, (r - dropin), offset) + dropin
|
|
590
|
+
y1 = sliceToY(0, (r - dropin), offset) + dropin
|
|
591
|
+
x2 = sliceToX(0, r - roff, offset) + roff
|
|
592
|
+
y2 = sliceToY(0, r - roff, offset) + roff
|
|
593
|
+
|
|
594
|
+
# Calculate the text offset for the house number
|
|
595
|
+
next_index = (i + 1) % xr
|
|
596
|
+
text_offset = offset + int(
|
|
597
|
+
degreeDiff(first_subject_houses_list_ut[next_index], first_subject_houses_list_ut[i]) / 2
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
# Determine the line color based on the house index
|
|
601
|
+
linecolor = {0: first_house_color, 9: tenth_house_color, 6: seventh_house_color, 3: fourth_house_color}.get(
|
|
602
|
+
i, standard_house_cusp_color
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
if chart_type in ["Transit", "Synastry"]:
|
|
606
|
+
# Calculate the offset for the second subject's house cusp
|
|
607
|
+
zeropoint = 360 - first_subject_houses_list_ut[6]
|
|
608
|
+
t_offset = (zeropoint + second_subject_houses_list_ut[i]) % 360
|
|
609
|
+
|
|
610
|
+
# Calculate the coordinates for the second subject's house cusp lines
|
|
611
|
+
t_x1 = sliceToX(0, (r - t_roff), t_offset) + t_roff
|
|
612
|
+
t_y1 = sliceToY(0, (r - t_roff), t_offset) + t_roff
|
|
613
|
+
t_x2 = sliceToX(0, r, t_offset)
|
|
614
|
+
t_y2 = sliceToY(0, r, t_offset)
|
|
615
|
+
|
|
616
|
+
# Calculate the text offset for the second subject's house number
|
|
617
|
+
t_text_offset = t_offset + int(
|
|
618
|
+
degreeDiff(second_subject_houses_list_ut[next_index], second_subject_houses_list_ut[i]) / 2
|
|
619
|
+
)
|
|
620
|
+
t_linecolor = linecolor if i in [0, 9, 6, 3] else transit_house_cusp_color
|
|
621
|
+
xtext = sliceToX(0, (r - 8), t_text_offset) + 8
|
|
622
|
+
ytext = sliceToY(0, (r - 8), t_text_offset) + 8
|
|
623
|
+
|
|
624
|
+
# Add the house number text for the second subject
|
|
625
|
+
fill_opacity = "0" if chart_type == "Transit" else ".4"
|
|
626
|
+
path += f'<g kr:node="HouseNumber">'
|
|
627
|
+
path += f'<text style="fill: #00f; fill-opacity: {fill_opacity}; font-size: 14px"><tspan x="{xtext - 3}" y="{ytext + 3}">{i + 1}</tspan></text>'
|
|
628
|
+
path += f"</g>"
|
|
629
|
+
|
|
630
|
+
# Add the house cusp line for the second subject
|
|
631
|
+
stroke_opacity = "0" if chart_type == "Transit" else ".3"
|
|
632
|
+
path += f'<g kr:node="Cusp">'
|
|
633
|
+
path += f"<line x1='{t_x1}' y1='{t_y1}' x2='{t_x2}' y2='{t_y2}' style='stroke: {t_linecolor}; stroke-width: 1px; stroke-opacity:{stroke_opacity};'/>"
|
|
634
|
+
path += f"</g>"
|
|
635
|
+
|
|
636
|
+
# Adjust dropin based on chart type
|
|
637
|
+
dropin = {"Transit": 84, "Synastry": 84, "ExternalNatal": 100}.get(chart_type, 48)
|
|
638
|
+
xtext = sliceToX(0, (r - dropin), text_offset) + dropin
|
|
639
|
+
ytext = sliceToY(0, (r - dropin), text_offset) + dropin
|
|
640
|
+
|
|
641
|
+
# Add the house cusp line for the first subject
|
|
642
|
+
path += f'<g kr:node="Cusp">'
|
|
643
|
+
path += f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="stroke: {linecolor}; stroke-width: 1px; stroke-dasharray:3,2; stroke-opacity:.4;"/>'
|
|
644
|
+
path += f"</g>"
|
|
645
|
+
|
|
646
|
+
# Add the house number text for the first subject
|
|
647
|
+
path += f'<g kr:node="HouseNumber">'
|
|
648
|
+
path += f'<text style="fill: #f00; fill-opacity: .6; font-size: 14px"><tspan x="{xtext - 3}" y="{ytext + 3}">{i + 1}</tspan></text>'
|
|
649
|
+
path += f"</g>"
|
|
650
|
+
|
|
651
|
+
return path
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
def draw_aspect_transit_grid(
|
|
655
|
+
grid_title: str,
|
|
656
|
+
aspects_list: Union[list[AspectModel], list[dict]],
|
|
657
|
+
celestial_point_language: KerykeionLanguageCelestialPointModel,
|
|
658
|
+
aspects_settings: KerykeionSettingsAspectModel,
|
|
659
|
+
) -> str:
|
|
660
|
+
"""
|
|
661
|
+
Generates the SVG output for the aspect transit grid.
|
|
662
|
+
|
|
663
|
+
Parameters:
|
|
664
|
+
- grid_title: Title of the grid.
|
|
665
|
+
- aspects_list: List of aspects.
|
|
666
|
+
- planets_labels: Dictionary containing the planet labels.
|
|
667
|
+
- aspects_settings: Dictionary containing the aspect settings.
|
|
668
|
+
|
|
669
|
+
Returns:
|
|
670
|
+
- A string containing the SVG path data for the aspect transit grid.
|
|
671
|
+
"""
|
|
672
|
+
|
|
673
|
+
# If not instance of AspectModel, convert to AspectModel
|
|
674
|
+
if isinstance(aspects_list[0], dict):
|
|
675
|
+
aspects_list = [AspectModel(**aspect) for aspect in aspects_list]
|
|
676
|
+
|
|
677
|
+
line = 0
|
|
678
|
+
nl = 0
|
|
679
|
+
inner_path = ""
|
|
680
|
+
scale = 1
|
|
681
|
+
for i, aspect in enumerate(aspects_list):
|
|
682
|
+
# Adjust the vertical position for every 12 aspects
|
|
683
|
+
if i == 12:
|
|
684
|
+
nl = 100
|
|
685
|
+
line = 0
|
|
686
|
+
|
|
687
|
+
elif i == 24:
|
|
688
|
+
nl = 200
|
|
689
|
+
line = 0
|
|
690
|
+
|
|
691
|
+
elif i == 36:
|
|
692
|
+
nl = 300
|
|
693
|
+
line = 0
|
|
694
|
+
|
|
695
|
+
elif i == 48:
|
|
696
|
+
nl = 400
|
|
697
|
+
# When there are more than 60 aspects, the text is moved up
|
|
698
|
+
if len(aspects_list) > 60:
|
|
699
|
+
line = -1 * (len(aspects_list) - 60) * 14
|
|
700
|
+
else:
|
|
701
|
+
line = 0
|
|
702
|
+
|
|
703
|
+
inner_path += f'<g transform="translate({nl},{line})">'
|
|
704
|
+
|
|
705
|
+
# first planet symbol
|
|
706
|
+
inner_path += f'<use transform="scale(0.4)" x="0" y="3" xlink:href="#{celestial_point_language[aspects_list[i]["p1"]]["name"]}" />'
|
|
707
|
+
|
|
708
|
+
# aspect symbol
|
|
709
|
+
inner_path += f'<use x="15" y="0" xlink:href="#orb{aspects_settings[aspects_list[i]["aid"]]["degree"]}" />'
|
|
710
|
+
|
|
711
|
+
# second planet symbol
|
|
712
|
+
inner_path += f'<g transform="translate(30,0)">'
|
|
713
|
+
inner_path += f'<use transform="scale(0.4)" x="0" y="3" xlink:href="#{celestial_point_language[aspects_list[i]["p2"]]["name"]}" />'
|
|
714
|
+
inner_path += f"</g>"
|
|
715
|
+
|
|
716
|
+
# difference in degrees
|
|
717
|
+
inner_path += f'<text y="8" x="45" style="fill:#000000; font-size: 10px;">{convert_decimal_to_degree_string(aspects_list[i]["orbit"])}</text>'
|
|
718
|
+
# line
|
|
719
|
+
inner_path += f"</g>"
|
|
720
|
+
line = line + 14
|
|
721
|
+
|
|
722
|
+
out = f'<g style="transform: translate(47%, 61%) scale({scale})">'
|
|
723
|
+
out += f'<text y="-15" x="0" style="fill:#000000; font-size: 14px;">{grid_title}:</text>'
|
|
724
|
+
out += inner_path
|
|
725
|
+
out += "</g>"
|
|
726
|
+
|
|
727
|
+
return out
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
def draw_moon_phase(
|
|
731
|
+
degrees_between_sun_and_moon: float,
|
|
732
|
+
latitude: float,
|
|
733
|
+
lunar_phase_outline_color: str = "#000000",
|
|
734
|
+
dark_color: str = "#000000",
|
|
735
|
+
light_color: str = "#ffffff",
|
|
736
|
+
) -> str:
|
|
737
|
+
"""
|
|
738
|
+
Draws the moon phase based on the degrees between the sun and the moon.
|
|
739
|
+
|
|
740
|
+
Parameters:
|
|
741
|
+
- degrees_between_sun_and_moon (float): The degrees between the sun and the moon.
|
|
742
|
+
- latitude (float): The latitude for rotation calculation.
|
|
743
|
+
- lunar_phase_outline_color (str): The color for the lunar phase outline.
|
|
744
|
+
- dark_color (str): The color for the dark part of the moon.
|
|
745
|
+
- light_color (str): The color for the light part of the moon.
|
|
746
|
+
|
|
747
|
+
Returns:
|
|
748
|
+
- str: The SVG element as a string.
|
|
749
|
+
"""
|
|
750
|
+
deg = degrees_between_sun_and_moon
|
|
751
|
+
|
|
752
|
+
# Initialize variables for lunar phase properties
|
|
753
|
+
fill_color_foreground = None
|
|
754
|
+
fill_color_background = None
|
|
755
|
+
circle_center_x = None
|
|
756
|
+
circle_radius = None
|
|
757
|
+
|
|
758
|
+
# Determine lunar phase properties based on the degree
|
|
759
|
+
if deg < 90.0:
|
|
760
|
+
max_radius = deg
|
|
761
|
+
if deg > 80.0:
|
|
762
|
+
max_radius = max_radius * max_radius
|
|
763
|
+
circle_center_x = 20.0 + (deg / 90.0) * (max_radius + 10.0)
|
|
764
|
+
circle_radius = 10.0 + (deg / 90.0) * max_radius
|
|
765
|
+
fill_color_foreground = dark_color
|
|
766
|
+
fill_color_background = light_color
|
|
767
|
+
|
|
768
|
+
elif deg < 180.0:
|
|
769
|
+
max_radius = 180.0 - deg
|
|
770
|
+
if deg < 100.0:
|
|
771
|
+
max_radius = max_radius * max_radius
|
|
772
|
+
circle_center_x = 20.0 + ((deg - 90.0) / 90.0 * (max_radius + 10.0)) - (max_radius + 10.0)
|
|
773
|
+
circle_radius = 10.0 + max_radius - ((deg - 90.0) / 90.0 * max_radius)
|
|
774
|
+
fill_color_foreground = light_color
|
|
775
|
+
fill_color_background = dark_color
|
|
776
|
+
|
|
777
|
+
elif deg < 270.0:
|
|
778
|
+
max_radius = deg - 180.0
|
|
779
|
+
if deg > 260.0:
|
|
780
|
+
max_radius = max_radius * max_radius
|
|
781
|
+
circle_center_x = 20.0 + ((deg - 180.0) / 90.0 * (max_radius + 10.0))
|
|
782
|
+
circle_radius = 10.0 + ((deg - 180.0) / 90.0 * max_radius)
|
|
783
|
+
fill_color_foreground = light_color
|
|
784
|
+
fill_color_background = dark_color
|
|
785
|
+
|
|
786
|
+
elif deg < 361.0:
|
|
787
|
+
max_radius = 360.0 - deg
|
|
788
|
+
if deg < 280.0:
|
|
789
|
+
max_radius = max_radius * max_radius
|
|
790
|
+
circle_center_x = 20.0 + ((deg - 270.0) / 90.0 * (max_radius + 10.0)) - (max_radius + 10.0)
|
|
791
|
+
circle_radius = 10.0 + max_radius - ((deg - 270.0) / 90.0 * max_radius)
|
|
792
|
+
fill_color_foreground = dark_color
|
|
793
|
+
fill_color_background = light_color
|
|
794
|
+
|
|
795
|
+
else:
|
|
796
|
+
raise KerykeionException(f"Invalid degree value: {deg}")
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
# Calculate rotation based on latitude
|
|
800
|
+
lunar_phase_rotate = -90.0 - latitude
|
|
801
|
+
|
|
802
|
+
# Return the SVG element as a string
|
|
803
|
+
return (
|
|
804
|
+
f'<g transform="rotate({lunar_phase_rotate} 20 10)">'
|
|
805
|
+
f' <circle cx="20" cy="10" r="10" style="fill: {fill_color_background}" />'
|
|
806
|
+
f' <circle cx="{circle_center_x}" cy="10" r="{circle_radius}" style="fill: {fill_color_foreground}" clip-path="url(#moonPhaseCutOffCircle)" />'
|
|
807
|
+
f' <circle cx="20" cy="10" r="10" style="fill: none; stroke: {lunar_phase_outline_color}; stroke-width: 0.5px; stroke-opacity: 0.5" />'
|
|
808
|
+
f"</g>"
|
|
809
|
+
)
|