Make it possible to generate an SVG image
This commit is contained in:
parent
7d15bd1956
commit
95d7d89470
@ -81,3 +81,12 @@ It can theoretically make it easier to synchronize events across multiple time
|
||||
zones without actually knowing the time difference; just tell the other
|
||||
attending parties that you eat your lunch during Ladybug hour, or that your
|
||||
event is taking place between Gourd and Soup hours.
|
||||
|
||||
Generated SVG
|
||||
=============
|
||||
|
||||
With the ``poetry run print_svg`` command, you will get an image similar to this:
|
||||
|
||||
.. image:: example-output.svg
|
||||
:width: 700
|
||||
:alt: An image rendered by this software
|
||||
|
681
example-output.svg
Normal file
681
example-output.svg
Normal file
@ -0,0 +1,681 @@
|
||||
<svg width="700" height="700" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<style>
|
||||
.hour path {stroke: rgb(0, 0, 0); stroke-width: 2px;}
|
||||
.hour text {stroke: none; fill: rgb(238, 187, 85);}
|
||||
.hour text.utc {stroke: none; fill: rgb(91, 68, 38);}
|
||||
.winter path {fill: rgb(70, 62, 108);}
|
||||
.spring path {fill: rgb(55, 87, 55);}
|
||||
.summer path {fill: rgb(113, 92, 43);}
|
||||
.autumn path {fill: rgb(108, 68, 44);}
|
||||
.local-hour {stroke: none; fill: rgb(238, 187, 85);}
|
||||
.night-time {stroke: none; fill: rgb(19, 17, 30);}
|
||||
.blue-hour {stroke: none; fill: rgb(9, 1, 119);}
|
||||
.golden-hour {stroke: none; fill: rgb(170, 132, 44);}
|
||||
.day-time {stroke: none; fill: rgb(125, 197, 240);}
|
||||
.marker {stroke: rgb(19, 17, 30); stroke-width: 2px; fill: none;}
|
||||
.moon-background {stroke: rgb(170, 170, 170); stroke-width: 2px; fill: rgb(19, 17, 30);}
|
||||
.moon {stroke: none; fill: rgb(170, 170, 170);}
|
||||
.sun {stroke: none; fill: rgb(238, 187, 85);}
|
||||
.dial {stroke-width: 2px; stroke: rgb(238, 187, 85);}
|
||||
</style>
|
||||
<defs>
|
||||
<path id="hour-name-path" d="M 312.1730467792776 62.6757645018362 a 289.803545 289.803545 15 0 1 75.65390644144473 0"></path>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="700" height="700" style="stroke: none; fill: rgb(19, 17, 30);"></rect>
|
||||
<g id="local-clock">
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(0, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">Midnight</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(15, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">1</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(30, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">2</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(45, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">3</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(60, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">4</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(75, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">5</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(90, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">6</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(105, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">7</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(120, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">8</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(135, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">9</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(150, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">10</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(165, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">11</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(180, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">Noon</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(195, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">13</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(210, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">14</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(225, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">15</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(240, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">16</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(255, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">17</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(270, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">18</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(285, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">19</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(300, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">20</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(315, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">21</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(330, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">22</text>
|
||||
<text
|
||||
transform="rotate(180, 350.0, 350.0) rotate(345, 350.0, 350.0)"
|
||||
class="local-hour"
|
||||
x="350.0"
|
||||
y="31.88096999999999"
|
||||
text-anchor="middle"
|
||||
font-size="16.5">23</text>
|
||||
</g>
|
||||
<g id="seasonal-clock" transform="rotate(30.0, 350.0, 350.0)">
|
||||
<g class="hour winter" transform="rotate(-172.5, 350.0, 350.0) rotate(0, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Candle</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 00</text>
|
||||
</g>
|
||||
<g class="hour winter" transform="rotate(-172.5, 350.0, 350.0) rotate(15, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Ice</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 01</text>
|
||||
</g>
|
||||
<g class="hour winter" transform="rotate(-172.5, 350.0, 350.0) rotate(30, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Comet</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 02</text>
|
||||
</g>
|
||||
<g class="hour winter" transform="rotate(-172.5, 350.0, 350.0) rotate(45, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Thimble</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 03</text>
|
||||
</g>
|
||||
<g class="hour winter" transform="rotate(-172.5, 350.0, 350.0) rotate(60, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Root</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 04</text>
|
||||
</g>
|
||||
<g class="hour winter" transform="rotate(-172.5, 350.0, 350.0) rotate(75, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Mist</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 05</text>
|
||||
</g>
|
||||
<g class="hour spring" transform="rotate(-172.5, 350.0, 350.0) rotate(90, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Sprout</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 06</text>
|
||||
</g>
|
||||
<g class="hour spring" transform="rotate(-172.5, 350.0, 350.0) rotate(105, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Rainbow</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 07</text>
|
||||
</g>
|
||||
<g class="hour spring" transform="rotate(-172.5, 350.0, 350.0) rotate(120, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Worm</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 08</text>
|
||||
</g>
|
||||
<g class="hour spring" transform="rotate(-172.5, 350.0, 350.0) rotate(135, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Bud</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 09</text>
|
||||
</g>
|
||||
<g class="hour spring" transform="rotate(-172.5, 350.0, 350.0) rotate(150, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Blossom</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 10</text>
|
||||
</g>
|
||||
<g class="hour spring" transform="rotate(-172.5, 350.0, 350.0) rotate(165, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Ladybug</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 11</text>
|
||||
</g>
|
||||
<g class="hour summer" transform="rotate(-172.5, 350.0, 350.0) rotate(180, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Geese</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 12</text>
|
||||
</g>
|
||||
<g class="hour summer" transform="rotate(-172.5, 350.0, 350.0) rotate(195, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Dust</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 13</text>
|
||||
</g>
|
||||
<g class="hour summer" transform="rotate(-172.5, 350.0, 350.0) rotate(210, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Peach</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 14</text>
|
||||
</g>
|
||||
<g class="hour summer" transform="rotate(-172.5, 350.0, 350.0) rotate(225, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Fog</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 15</text>
|
||||
</g>
|
||||
<g class="hour summer" transform="rotate(-172.5, 350.0, 350.0) rotate(240, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Acorn</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 16</text>
|
||||
</g>
|
||||
<g class="hour summer" transform="rotate(-172.5, 350.0, 350.0) rotate(255, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Gourd</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 17</text>
|
||||
</g>
|
||||
<g class="hour autumn" transform="rotate(-172.5, 350.0, 350.0) rotate(270, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Soup</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 18</text>
|
||||
</g>
|
||||
<g class="hour autumn" transform="rotate(-172.5, 350.0, 350.0) rotate(285, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Crow</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 19</text>
|
||||
</g>
|
||||
<g class="hour autumn" transform="rotate(-172.5, 350.0, 350.0) rotate(300, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Mushroom</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 20</text>
|
||||
</g>
|
||||
<g class="hour autumn" transform="rotate(-172.5, 350.0, 350.0) rotate(315, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Thunder</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 21</text>
|
||||
</g>
|
||||
<g class="hour autumn" transform="rotate(-172.5, 350.0, 350.0) rotate(330, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Frost</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 22</text>
|
||||
</g>
|
||||
<g class="hour autumn" transform="rotate(-172.5, 350.0, 350.0) rotate(345, 350.0, 350.0)">
|
||||
<path
|
||||
d="M 309.55397542717907 42.7819425076129 a 309.86903 309.86903 15 0 1 80.89204914564186 0 l -5.238142704197123 39.78764398844654 a 269.73806 269.73806 15 0 0 -70.41576373724762 0 z"></path>
|
||||
<text
|
||||
x="350.0"
|
||||
y="63.54070249999999"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="13.37699"><textPath xlink:href="#hour-name-path" startOffset="50%">Lantern</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, 350.0, 350.0)"
|
||||
class="utc"
|
||||
x="350.0"
|
||||
y="95.28533999999998"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="15.0234">U 23</text>
|
||||
</g>
|
||||
<circle cx="350.0" cy="350.0" r="239.69126000000003" class="day-time"></circle>
|
||||
<path
|
||||
class="golden-hour"
|
||||
d="M 350.0 350.0
|
||||
L 116.05469504530768 402.16794427657305
|
||||
A 239.69126000000003 239.69126000000003 169.29166666666669 1 0 570.178029285408 255.27125283008513
|
||||
z"></path>
|
||||
<circle cx="350.0" cy="514.934515" r="10" class="sun" transform="rotate(208.61666666666667, 350.0, 350.0)"></circle>
|
||||
<path
|
||||
class="blue-hour"
|
||||
d="M 350.0 350.0
|
||||
L 137.1262622524969 460.16656433689354
|
||||
A 239.69126000000003 239.69126000000003 198.91666666666669 0 0 587.0918462571672 314.795503713937
|
||||
z"></path>
|
||||
<path
|
||||
class="night-time"
|
||||
d="M 350.0 350.0
|
||||
L 143.12202233852076 471.0512390646379
|
||||
A 239.69126000000003 239.69126000000003 204.86666666666665 0 0 588.60109398448 327.1654194302391
|
||||
z"></path>
|
||||
<circle cx="350.0" cy="350.0" r="239.69126000000003" class="marker"></circle>
|
||||
</g>
|
||||
<g>
|
||||
<circle cx="350.0" cy="350.0" r="50" class="moon-background"></circle>
|
||||
<path
|
||||
class="moon"
|
||||
d="M 350.0 300.0
|
||||
C 283.0 306.0, 283.0 394.0, 350.0 400.0
|
||||
C 318.4132222222222 394.0, 318.4132222222222 306.0, 350.0 300.0"></path>
|
||||
</g>
|
||||
<line
|
||||
style="stroke: red;"
|
||||
transform="rotate(341.90416666666664, 350.0, 350.0)"
|
||||
x1="350.0"
|
||||
y1="579.69126"
|
||||
x2="350.0"
|
||||
y2="589.69126"></line>
|
||||
<line
|
||||
style="stroke: red;"
|
||||
transform="rotate(162.00833333333333, 350.0, 350.0)"
|
||||
x1="350.0"
|
||||
y1="579.69126"
|
||||
x2="350.0"
|
||||
y2="589.69126"></line>
|
||||
<line
|
||||
id="dial"
|
||||
transform="rotate(238.61666666666667, 350.0, 350.0)"
|
||||
class="dial"
|
||||
x1="350.0"
|
||||
y1="504.93451500000003"
|
||||
x2="350.0"
|
||||
y2="633.11505"></line>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 31 KiB |
@ -23,6 +23,7 @@ types-pytz = "^2021.3.6"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
print_data = "seasonal_clock:main"
|
||||
print_svg = "seasonal_clock.svg:print_svg"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
441
seasonal_clock/svg.py
Normal file
441
seasonal_clock/svg.py
Normal file
@ -0,0 +1,441 @@
|
||||
from datetime import datetime, time
|
||||
from math import ceil, cos, pi, radians, sin
|
||||
from typing import Union
|
||||
|
||||
from astral import LocationInfo, moon
|
||||
from pytz import UTC, timezone
|
||||
|
||||
from .config import load_config
|
||||
from .times import collect_day_parts
|
||||
|
||||
HOURS_AMPM = (
|
||||
'Midnight',
|
||||
'1a',
|
||||
'2a',
|
||||
'3a',
|
||||
'4a',
|
||||
'5a',
|
||||
'6a',
|
||||
'7a',
|
||||
'8a',
|
||||
'9a',
|
||||
'10a',
|
||||
'11a',
|
||||
'Noon',
|
||||
'1p',
|
||||
'2p',
|
||||
'3p',
|
||||
'4p',
|
||||
'5p',
|
||||
'6p',
|
||||
'7p',
|
||||
'8p',
|
||||
'9p',
|
||||
'10p',
|
||||
'11p',
|
||||
)
|
||||
HOURS_24 = (
|
||||
'Midnight',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'Noon',
|
||||
'13',
|
||||
'14',
|
||||
'15',
|
||||
'16',
|
||||
'17',
|
||||
'18',
|
||||
'19',
|
||||
'20',
|
||||
'21',
|
||||
'22',
|
||||
'23',
|
||||
)
|
||||
HOUR_NAMES = (
|
||||
'Candle',
|
||||
'Ice',
|
||||
'Comet',
|
||||
'Thimble',
|
||||
'Root',
|
||||
'Mist',
|
||||
'Sprout',
|
||||
'Rainbow',
|
||||
'Worm',
|
||||
'Bud',
|
||||
'Blossom',
|
||||
'Ladybug',
|
||||
'Geese',
|
||||
'Dust',
|
||||
'Peach',
|
||||
'Fog',
|
||||
'Acorn',
|
||||
'Gourd',
|
||||
'Soup',
|
||||
'Crow',
|
||||
'Mushroom',
|
||||
'Thunder',
|
||||
'Frost',
|
||||
'Lantern',
|
||||
)
|
||||
SEASONS = ('winter', 'spring', 'summer', 'autumn')
|
||||
|
||||
|
||||
def hex_to_rgb(hex_color: str) -> str:
|
||||
r = int(hex_color[1:3], 16)
|
||||
g = int(hex_color[3:5], 16)
|
||||
b = int(hex_color[5:7], 16)
|
||||
|
||||
return f'rgb({r}, {g}, {b})'
|
||||
|
||||
|
||||
def get_utc_offset(utc_time: datetime, local_time: datetime):
|
||||
assert utc_time.tzinfo
|
||||
assert local_time.tzinfo
|
||||
|
||||
utc = utc_time.replace(tzinfo=None)
|
||||
local = utc_time.replace(tzinfo=None)
|
||||
|
||||
return (utc - local).total_seconds()
|
||||
|
||||
|
||||
def seconds_to_degrees(seconds: float) -> float:
|
||||
one_second = 360 / 86400
|
||||
|
||||
return seconds * one_second
|
||||
|
||||
|
||||
def indent_lines(string: str, indentation: int = 8) -> str:
|
||||
return '\n'.join((' ' * indentation) + line for line in string.split('\n')) + '\n'
|
||||
|
||||
|
||||
def time_to_degrees(timestamp: Union[datetime, time]) -> float:
|
||||
return seconds_to_degrees(
|
||||
timestamp.hour * 3600 + timestamp.minute * 60 + timestamp.second
|
||||
)
|
||||
|
||||
|
||||
def hour_name_path(image_width: int, outer_r: float, ring_width: float) -> str:
|
||||
radius = outer_r - ring_width / 2
|
||||
delta_x = radius * sin(radians(15) / 2)
|
||||
delta_y = radius * (1 - cos(radians(15) / 2))
|
||||
x1 = image_width / 2 - delta_x
|
||||
y1 = (image_width / 2 - radius) + delta_y
|
||||
|
||||
return f'''<path id="hour-name-path" d="M {x1} {y1} a {radius} {radius} 15 0 1 {2 * delta_x} 0"></path>'''
|
||||
|
||||
|
||||
def hour_marker(
|
||||
hour: int,
|
||||
hour_name: str,
|
||||
image_width: int,
|
||||
outer_r: float,
|
||||
ring_width: float,
|
||||
hour_name_font_size: float,
|
||||
utc_font_size: float,
|
||||
indent: int = 8,
|
||||
) -> str:
|
||||
season = SEASONS[ceil((hour + 1) / 6) - 1]
|
||||
rotation = hour * 15
|
||||
|
||||
delta_x = outer_r * sin(radians(15) / 2)
|
||||
delta_y = outer_r * (1 - cos(radians(15) / 2))
|
||||
|
||||
s_delta_x = 0 - ring_width * sin(radians(15) / 2)
|
||||
s_delta_y = ring_width * cos(radians(15) / 2)
|
||||
|
||||
i_delta_x = -2 * (outer_r - ring_width) * sin(radians(15) / 2)
|
||||
|
||||
x1 = image_width / 2 - delta_x
|
||||
y1 = (image_width / 2 - outer_r) + delta_y
|
||||
|
||||
hour_name_y = image_width / 2 - outer_r + ring_width / 2 + hour_name_font_size / 4
|
||||
utc_hour_y = image_width / 2 - outer_r + ring_width + utc_font_size
|
||||
|
||||
ret = f'''<g class="hour {season}" transform="rotate(-172.5, {image_width / 2}, {image_width / 2}) rotate({rotation}, {image_width / 2}, {image_width / 2})">
|
||||
<path
|
||||
d="M {x1} {y1} a {outer_r} {outer_r} 15 0 1 {2 * delta_x} 0 l {s_delta_x} {s_delta_y} a {outer_r - ring_width} {outer_r - ring_width} 15 0 0 {i_delta_x} 0 z"></path>
|
||||
<text
|
||||
x="{image_width / 2}"
|
||||
y="{hour_name_y}"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="{hour_name_font_size}"><textPath xlink:href="#hour-name-path" startOffset="50%">{hour_name}</textPath></text>
|
||||
<text
|
||||
transform="rotate(-7.5, {image_width / 2}, {image_width / 2})"
|
||||
class="utc"
|
||||
x="{image_width / 2}"
|
||||
y="{utc_hour_y}"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="mathematical"
|
||||
font-size="{utc_font_size}">U {hour:02d}</text>
|
||||
</g>'''
|
||||
|
||||
return indent_lines(ret, indent)
|
||||
|
||||
|
||||
def local_hour(
|
||||
image_width: int,
|
||||
outer_r: float,
|
||||
hour_num: int,
|
||||
hour: str,
|
||||
font_size: float,
|
||||
indent: int = 8,
|
||||
) -> str:
|
||||
rotation = hour_num * 15
|
||||
|
||||
return indent_lines(
|
||||
f'''<text
|
||||
transform="rotate(180, {image_width / 2}, {image_width / 2}) rotate({rotation}, {image_width / 2}, {image_width / 2})"
|
||||
class="local-hour"
|
||||
x="{image_width / 2}"
|
||||
y="{image_width / 2 - outer_r - font_size / 2}"
|
||||
text-anchor="middle"
|
||||
font-size="{font_size}">{hour}</text>''',
|
||||
indent,
|
||||
)
|
||||
|
||||
|
||||
def get_range_path(
|
||||
image_width: int,
|
||||
radius: float,
|
||||
range_name: str,
|
||||
start_time: time,
|
||||
end_time: time,
|
||||
outer: bool = True,
|
||||
indent: int = 8,
|
||||
) -> str:
|
||||
start_deg = time_to_degrees(start_time)
|
||||
end_deg = time_to_degrees(end_time)
|
||||
|
||||
start_delta_x = radius * sin(radians(start_deg))
|
||||
start_delta_y = radius * (1 - cos(radians(start_deg)))
|
||||
end_delta_x = radius * sin(radians(end_deg))
|
||||
end_delta_y = radius * (1 - cos(radians(end_deg)))
|
||||
|
||||
deg_diff = end_deg - start_deg
|
||||
|
||||
large_arc_flag = 0 if abs(deg_diff) >= 180 else 1
|
||||
|
||||
return indent_lines(
|
||||
f'''<path
|
||||
class="{range_name}"
|
||||
d="M {image_width / 2} {image_width / 2}
|
||||
L {image_width / 2 - start_delta_x} {image_width / 2 + radius - start_delta_y}
|
||||
A {radius} {radius} {end_deg - start_deg} {large_arc_flag} 0 {image_width / 2 - end_delta_x} {image_width / 2 + radius - end_delta_y}
|
||||
z"></path>''',
|
||||
indent,
|
||||
)
|
||||
|
||||
|
||||
def get_moon_path(image_width: int, radius: float, moon_phase: float, indent: int = 8):
|
||||
handle_x_pos = radius * 1.34
|
||||
handle_y_pos = radius * 0.88
|
||||
min_x = image_width / 2 - handle_x_pos
|
||||
max_x = min_x + 2 * handle_x_pos
|
||||
top_y = image_width / 2 - handle_y_pos
|
||||
bottom_y = image_width / 2 + handle_y_pos
|
||||
|
||||
if moon_phase < 14:
|
||||
h1_x = min_x + 2 * handle_x_pos * (1 - moon_phase / 14)
|
||||
h2_x = max_x
|
||||
else:
|
||||
h1_x = min_x
|
||||
h2_x = max_x + 2 * handle_x_pos * (1 - moon_phase / 14)
|
||||
|
||||
ret = f'''<path
|
||||
class="moon"
|
||||
d="M {image_width / 2} {image_width / 2 - radius}
|
||||
C {h1_x} {top_y}, {h1_x} {bottom_y}, {image_width / 2} {image_width / 2 + radius}
|
||||
C {h2_x} {bottom_y}, {h2_x} {top_y}, {image_width / 2} {image_width / 2 - radius}"></path>'''
|
||||
|
||||
return indent_lines(ret, indent)
|
||||
|
||||
|
||||
def get_svg_data(
|
||||
local_time: datetime,
|
||||
image_width: int = 700,
|
||||
line_width: str = '2px',
|
||||
line_color: str = '#eebb55',
|
||||
utc_color: str = '#5b4426',
|
||||
hname_stroke_color: str = '#000000',
|
||||
winter_color: str = '#463e6c',
|
||||
spring_color: str = '#375737',
|
||||
summer_color: str = '#715c2b',
|
||||
autumn_color: str = '#6c442c',
|
||||
night_color: str = '#13111e',
|
||||
blue_color: str = '#090177',
|
||||
golden_color: str = '#aa842c',
|
||||
day_color: str = '#7dc5f0',
|
||||
moon_color: str = '#aaaaaa',
|
||||
local_hour_font_size: float = 16.5,
|
||||
hour_name_font_size: float = 13.37699,
|
||||
utc_hour_font_size: float = 15.0234,
|
||||
hour_24: bool = True,
|
||||
) -> str:
|
||||
line_rgb = hex_to_rgb(line_color)
|
||||
hname_stroke_rgb = hex_to_rgb(hname_stroke_color)
|
||||
utc_rgb = hex_to_rgb(utc_color)
|
||||
winter_rgb = hex_to_rgb(winter_color)
|
||||
spring_rgb = hex_to_rgb(spring_color)
|
||||
summer_rgb = hex_to_rgb(summer_color)
|
||||
autumn_rgb = hex_to_rgb(autumn_color)
|
||||
night_rgb = hex_to_rgb(night_color)
|
||||
blue_rgb = hex_to_rgb(blue_color)
|
||||
golden_rgb = hex_to_rgb(golden_color)
|
||||
day_rgb = hex_to_rgb(day_color)
|
||||
moon_rgb = hex_to_rgb(moon_color)
|
||||
hours = HOURS_24 if hour_24 else HOURS_AMPM
|
||||
outer_r = image_width / 2 - 3 * hour_name_font_size
|
||||
ring_width = hour_name_font_size * 3
|
||||
|
||||
utc_time = local_time.astimezone(UTC)
|
||||
utc_naive = utc_time.replace(tzinfo=None)
|
||||
local_naive = local_time.replace(tzinfo=None)
|
||||
offset = (local_naive - utc_naive).total_seconds()
|
||||
|
||||
config = load_config()
|
||||
|
||||
location = LocationInfo(
|
||||
config['city'],
|
||||
config['country'],
|
||||
config['timezone'],
|
||||
config['latitude'],
|
||||
config['longitude'],
|
||||
)
|
||||
local_tz = location.tzinfo
|
||||
day_parts = collect_day_parts(location.observer, local_time)
|
||||
day_parts_dict = dict(part[0:2] for part in day_parts)
|
||||
morning_blue_start = day_parts_dict.pop('morning_blue_start')
|
||||
morning_blue_end = day_parts_dict.pop('morning_golden_start')
|
||||
morning_golden_end = day_parts_dict.pop('morning_golden_end')
|
||||
evening_golden_start = day_parts_dict.pop('evening_golden_start')
|
||||
evening_blue_start = day_parts_dict.pop('evening_blue_start')
|
||||
evening_blue_end = day_parts_dict.pop('evening_blue_end')
|
||||
moon_phase = moon.phase(local_time)
|
||||
|
||||
noon = day_parts_dict.pop('noon')
|
||||
midnight = day_parts_dict.pop('midnight')
|
||||
|
||||
ret = f'''<svg width="{image_width}" height="{image_width}" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<style>
|
||||
.hour path {{stroke: {hname_stroke_rgb}; stroke-width: {line_width};}}
|
||||
.hour text {{stroke: none; fill: {line_rgb};}}
|
||||
.hour text.utc {{stroke: none; fill: {utc_rgb};}}
|
||||
.winter path {{fill: {winter_rgb};}}
|
||||
.spring path {{fill: {spring_rgb};}}
|
||||
.summer path {{fill: {summer_rgb};}}
|
||||
.autumn path {{fill: {autumn_rgb};}}
|
||||
.local-hour {{stroke: none; fill: {line_rgb};}}
|
||||
.night-time {{stroke: none; fill: {night_rgb};}}
|
||||
.blue-hour {{stroke: none; fill: {blue_rgb};}}
|
||||
.golden-hour {{stroke: none; fill: {golden_rgb};}}
|
||||
.day-time {{stroke: none; fill: {day_rgb};}}
|
||||
.marker {{stroke: {night_rgb}; stroke-width: 2px; fill: none;}}
|
||||
.moon-background {{stroke: {moon_rgb}; stroke-width: 2px; fill: {night_rgb};}}
|
||||
.moon {{stroke: none; fill: {moon_rgb};}}
|
||||
.sun {{stroke: none; fill: {line_rgb};}}
|
||||
.dial {{stroke-width: 2px; stroke: {line_rgb};}}
|
||||
</style>
|
||||
<defs>
|
||||
{hour_name_path(image_width, outer_r, ring_width)}
|
||||
</defs>
|
||||
<rect x="0" y="0" width="{image_width}" height="{image_width}" style="stroke: none; fill: {night_rgb};"></rect>
|
||||
<g id="local-clock">\n'''
|
||||
|
||||
for hour in range(24):
|
||||
ret += local_hour(
|
||||
image_width, outer_r, hour, hours[hour], local_hour_font_size, indent=8
|
||||
)
|
||||
|
||||
ret += f''' </g>
|
||||
<g id="seasonal-clock" transform="rotate({seconds_to_degrees(offset)}, {image_width / 2}, {image_width / 2})">
|
||||
'''
|
||||
for hour in range(24):
|
||||
ret += hour_marker(
|
||||
hour,
|
||||
HOUR_NAMES[hour],
|
||||
image_width,
|
||||
outer_r,
|
||||
ring_width,
|
||||
hour_name_font_size,
|
||||
utc_hour_font_size,
|
||||
indent=8,
|
||||
)
|
||||
|
||||
marker_radius = outer_r - ring_width - 2 * utc_hour_font_size
|
||||
ret += f''' <circle cx="{image_width / 2}" cy="{image_width / 2}" r="{marker_radius}" class="day-time"></circle>\n'''
|
||||
ret += get_range_path(
|
||||
image_width,
|
||||
marker_radius,
|
||||
'golden-hour',
|
||||
morning_golden_end.time(),
|
||||
evening_golden_start.time(),
|
||||
)
|
||||
sun_radius = 10
|
||||
ret += f''' <circle cx="{image_width / 2}" cy="{image_width / 2 + outer_r / 2 + sun_radius}" r="{sun_radius}" class="sun" transform="rotate({time_to_degrees(local_time.astimezone(UTC))}, {image_width / 2}, {image_width / 2})"></circle>\n'''
|
||||
ret += get_range_path(
|
||||
image_width,
|
||||
marker_radius,
|
||||
'blue-hour',
|
||||
morning_blue_end.time(),
|
||||
evening_blue_start.time(),
|
||||
)
|
||||
ret += get_range_path(
|
||||
image_width,
|
||||
marker_radius,
|
||||
'night-time',
|
||||
morning_blue_start.time(),
|
||||
evening_blue_end.time(),
|
||||
)
|
||||
|
||||
ret += f''' <circle cx="{image_width / 2}" cy="{image_width / 2}" r="{marker_radius}" class="marker"></circle>
|
||||
</g>
|
||||
<g>\n'''
|
||||
|
||||
moon_radius = 50
|
||||
ret += f''' <circle cx="{image_width / 2}" cy="{image_width / 2}" r="{moon_radius}" class="moon-background"></circle>\n'''
|
||||
|
||||
ret += get_moon_path(image_width, moon_radius, moon_phase, indent=8)
|
||||
ret += f''' </g>
|
||||
<line
|
||||
style="stroke: red;"
|
||||
transform="rotate({time_to_degrees(midnight.astimezone(local_tz))}, {image_width / 2}, {image_width / 2})"
|
||||
x1="{image_width / 2}"
|
||||
y1="{image_width / 2 + marker_radius - sun_radius}"
|
||||
x2="{image_width / 2}"
|
||||
y2="{image_width / 2 + marker_radius}"></line>
|
||||
<line
|
||||
style="stroke: red;"
|
||||
transform="rotate({time_to_degrees(noon.astimezone(local_tz))}, {image_width / 2}, {image_width / 2})"
|
||||
x1="{image_width / 2}"
|
||||
y1="{image_width / 2 + marker_radius - sun_radius}"
|
||||
x2="{image_width / 2}"
|
||||
y2="{image_width / 2 + marker_radius}"></line>
|
||||
<line
|
||||
id="dial"
|
||||
transform="rotate({time_to_degrees(local_time)}, {image_width / 2}, {image_width / 2})"
|
||||
class="dial"
|
||||
x1="{image_width / 2}"
|
||||
y1="{image_width / 2 + outer_r * 0.5}"
|
||||
x2="{image_width / 2}"
|
||||
y2="{image_width / 2 + outer_r - ring_width + hour_name_font_size}"></line>
|
||||
</svg>
|
||||
'''
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def print_svg():
|
||||
utc_now = datetime.utcnow().replace(tzinfo=UTC)
|
||||
local_now = utc_now.astimezone(timezone('Europe/Budapest'))
|
||||
|
||||
print(get_svg_data(local_now))
|
Loading…
Reference in New Issue
Block a user