It is currently April 19th, 2024, 3:23 pm

[Solved][Lots of Math] Moon Icon Rotation on a Sky Dial

Get help with creating, editing & fixing problems with skins
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by raiguard »

balala wrote: December 31st, 2018, 9:17 pm You've posted the content of a .lua file, that's why I asked to upload it. How does the latest code look like? If you've changed the lastly posted code, please post / upload it.
I only posted the SunCalc LUA code because GTI.H wanted to know the equation I'm using to get the moon phase value, among other things. It doesn't have anything to do with my issue right now.

Here is the code I am working with, as of the latest revision. Instead of using the LUA script, I changed the code to use variables that I can manually adjust to help with debugging:

AstroDial.ini:

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Variables]
; =========================
; DEBUG TESTING VARIABLES

; Sun / Moon Angles on the Dial (degrees)
sunDialAngle=-1
moonDialAngle=0
; Angle that the illuminated limb of the moon will face (degrees, starts North, counterclockwise)
rawMVA=0
; If set to 1, the moon will orient based on the value above. If set to 0, waxing will display on the right, and waning will display on the left.
showMoonAngle=1
; Moon phase value: 0.0 (new) -> 0.5 (full) -> 1.0 (new)
moonPhase=0.12

; =========================

; Colors
colorBg=15,15,15
colorDialArc=150,150,150
colorMoon=200,200,200
colorMoonBg=30,30,30
colorMoonBorder=70,70,70
colorSun=250,222,110
; Dial settings
dialRadius=250
dialStartX=3
dialArcThickness=6
dialObjectRadius=23
; Moon settings
moonBorderThickness=3
moonInnerRadius=(#dialObjectRadius# - #moonBorderThickness#)
moonArcStartX=(#dialStartX# - #dialObjectRadius#)
moonArcStartY=(#dialRadius# - #moonBorderThickness#)
moonViewAngle=((#rawMVA# + #moonDialAngle#) % 360)

; ==================================================
; MEASURES
; ==================================================

[MeasureSunDialVisibility]
Measure=Calc
Formula=#sunDialAngle#
IfCondition=(MeasureSunDialVisibility > 180) || (MeasureSunDialVisibility < 0)
IfTrueAction=[!SetVariable sunDialVisibility 0][!UpdateMeter MeterAstroDial][!Redraw]
IfFalseAction=[!SetVariable sunDialVisibility 255][!UpdateMeter MeterAstroDial][!Redraw]
DynamicVariables=1

[MeasureMoonDialVisibility]
Measure=Calc
Formula=#moonDialAngle#
IfCondition=(MeasureMoonDialVisibility > 180) || (MeasureMoonDialVisibility < 0)
IfTrueAction=[!SetVariable moonDialVisibility 0][!UpdateMeter MeterAstroDial][!Redraw]
IfFalseAction=[!SetVariable moonDialVisibility 255][!UpdateMeter MeterAstroDial][!Redraw]
DynamicVariables=1

; Converts the moon phase value into a radius value usable by the arc shape
[MeasureMoonShapePhaseCalc]
Measure=Calc
Formula=clamp(abs((#moonInnerRadius# * 4 * ((#moonPhase# > 0.5) ? (0.5 - (#moonPhase# - 0.5)) : #moonPhase#)) - #moonInnerRadius#),0,#moonInnerRadius#)
DynamicVariables=1
Group=MoonShape

; Adjusts the center of arc rotation for the moon limb shape in the X direction
[MeasureMoonLimbArcRotationXOffsetCalc]
Measure=Calc
DynamicVariables=1
Formula=(((#moonViewAngle# > 180) && (#moonViewAngle# < 360)) ? (#moonInnerRadius# * abs(cos(rad(#moonViewAngle#)))) : #moonInnerRadius#)
Group=MoonShape

; Adjusts the center of arc rotation for the moon limb shape in the Y direction
[MeasureMoonLimbArcRotationYOffsetCalc]
Measure=Calc
DynamicVariables=1
Formula=(((#moonViewAngle# <= 90) || (#moonViewAngle# >= 270)) ? #moonInnerRadius# : (#moonInnerRadius# * abs(sin(rad(#moonViewAngle#)))))
Group=MoonShape

; TEMPORARY DEBUG - rotates the moon's illuminated limb 360 degrees
[MeasureActionTimer]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat Increase, 16, 180
ActionList2=ResetMove | Repeat Move, 16, 180
ActionList3=ResetMove | Repeat Both, 16, 180
ActionList4=Repeat Increase, 16, 5
Increase=[!SetVariable rawMVA "(#rawMVA# + 2)"][!SetVariable moonViewAngle "((#rawMVA# + #moonDialAngle#) % 360)"][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
Move=[!SetVariable moonDialAngle "(#moonDialAngle# + 1)"][!SetVariable moonViewAngle "((#rawMVA# + #moonDialAngle#) % 360)"][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
Both=[!SetVariable rawMVA "(#rawMVA# + 2)"][!SetVariable moonDialAngle "(#moonDialAngle# + 1)"][!SetVariable moonViewAngle "((#rawMVA# + #moonDialAngle#) % 360)"][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
ResetMove=[!SetVariable moonDialAngle 0][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
DynamicVariables=1

; ==================================================
; METERS
; ==================================================

[MeterAstroDial]
Meter=Shape
; Arc
Shape=Arc #dialStartX#,#dialRadius#,(#dialRadius# * 2 + #dialStartX#),#dialRadius#,#dialRadius#,#dialRadius# | StrokeWidth #dialArcThickness# | Stroke Color #colorDialArc# | StrokeStartCap Round | StrokeEndCap Round
; Sun
Shape2=Ellipse #dialStartX#,#dialRadius#,#dialObjectRadius#,#dialObjectRadius# | StrokeWidth 0 | Fill Color #colorSun#,#sunDialVisibility# | Rotate #sunDialAngle#,(#dialRadius# + #dialObjectRadius#),(#dialObjectRadius#)
; Moon
Shape3=Ellipse #dialStartX#,#dialRadius#,#dialObjectRadius#,#dialObjectRadius# | StrokeWidth 0 | Fill Color #colorMoonBorder#,#moonDialVisibility# | Rotate #moonDialAngle#,(#dialRadius# + #dialObjectRadius#),(#dialObjectRadius#)
Shape4=Ellipse #dialStartX#,#dialRadius#,#moonInnerRadius#,#moonInnerRadius# | StrokeWidth 0 | Fill Color #colorMoonBg#,#moonDialVisibility# | Rotate #moonDialAngle#,(#dialRadius# + #moonInnerRadius#),(#moonInnerRadius#)
Shape5=Ellipse #dialStartX#,#dialRadius#,#moonInnerRadius#,#moonInnerRadius# | StrokeWidth 0 | Fill Color #colorMoon#,#moonDialVisibility#
Shape6=Path MoonArc | StrokeWidth 0 | Fill Color #colorMoon# | Rotate (((#showMoonAngle# = 1) ? (-#moonViewAngle#) : ((#moonPhase# > 0.5) ? -90 : 90))),#moonInnerRadius#,#moonInnerRadius# | Offset #moonBorderThickness#,#moonBorderThickness# | StrokeLineJoin Round
MoonArc=#moonArcStartX#,#moonArcStartY# | ArcTo (#moonArcStartX# + (#moonInnerRadius# * 2)),#moonArcStartY#,#moonInnerRadius#,[MeasureMoonShapePhaseCalc:],0,(((#moonPhase# > 0.25) && (#moonPhase# < 0.75)) ? 1 : 0) | ArcTo #moonArcStartX#,#moonArcStartY#,#moonInnerRadius#,#moonInnerRadius#,0,1

Shape7=Combine Shape5 | Intersect Shape6 | Rotate #moonDialAngle#,(#dialRadius# + [MeasureMoonLimbArcRotationXOffsetCalc:]),([MeasureMoonLimbArcRotationYOffsetCalc:])

Shape8=Ellipse #dialRadius#,#dialRadius#,5,5 | StrokeWidth 0 | Fill Color 0,150,0

Padding=30,30,30,30
SolidColor=#colorBg#
DynamicVariables=1

[MeterDebugLimbRotation]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Limb Rotation
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 1"]
Antialias=1

[MeterDebugDialRotation]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Dial Rotation
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 2"]
Antialias=1

[MeterDebugBoth]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Both Rotations
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 3"]
Antialias=1

[MeterDebugStepLimb]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Step Limb Rotation
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 4"]
Antialias=1
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
balala
Rainmeter Sage
Posts: 16144
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by balala »

Checking this last posted code, it looks alright. There still is something wrong with it?
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by raiguard »

balala wrote: December 31st, 2018, 9:29 pm Checking this last posted code, it looks alright. There still is something wrong with it?
Set the moon phase value to something between 0.25 and 0.75 and run the Dial or Both debug tests.
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
balala
Rainmeter Sage
Posts: 16144
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by balala »

raiguard wrote: December 31st, 2018, 9:30 pm Set the moon phase value to something between 0.25 and 0.75 and run the Dial or Both debug tests.
Right, I see now. I'll take a look to see if I can figure out something.
User avatar
GTI.H
Posts: 75
Joined: December 15th, 2018, 3:35 am

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by GTI.H »

raiguard wrote: December 31st, 2018, 9:30 pm Set the moon phase value to something between 0.25 and 0.75 and run the Dial or Both debug tests.
Thanks for the SUNCALC.LUA script, this may be useful someday even though I do not think I would need a Script just to calculate the phases of the moon, maybe I'm mistaken, but an equation would be enough.

I recently wrote a Skin similar to this one and I prefer to use on time updated realistic images like Astro photos.

I have not yet analyzed your code, but it does suggest that your Limb is with the center reference moving.


--
Regards
GTI
Last edited by GTI.H on December 31st, 2018, 10:51 pm, edited 1 time in total.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by raiguard »

GTI.H wrote: December 31st, 2018, 10:46 pm Thanks for the SUNCALC.LUA script, this may be useful someday even though I do not think I would need a Script just to calculate the phases of the moon, maybe I'm mistaken, but an equation would be enough.

I recently wrote a Skin similar to this one and I prefer to use on time updated realistic images like Astro photos.

I have not yet analyzed your code, but it does suggest that your limb is with the center reference moving.


--
Regards
GTI
Correct. I am currently working on an EXTREMELY thorough explanation so people know exactly what is going on. I'm about 70% done with it. Hopefully once it's done it will help immensely.
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
GTI.H
Posts: 75
Joined: December 15th, 2018, 3:35 am

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by GTI.H »

What I'm trying to say is that a good place to look for the error is in the center reference of your Limb.
raiguard wrote: December 31st, 2018, 10:49 pm Correct. I am currently working on an EXTREMELY thorough explanation so people know exactly what is going on. I'm about 70% done with it. Hopefully once it's done it will help immensely.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by raiguard »

GTI.H wrote: December 31st, 2018, 10:55 pm What I'm trying to say is that a good place to look for the error is in the center reference of your Limb.
Yes, it has to do with this. I actually already know the exact problem and what's causing it, I just have no idea how to fix it. As part of my detailed explanation I am describing the exact problem, what I've done to counteract it, and the part that I need help with. Sorry for the confusion, the explanation will be finished soon. :thumbup:
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by raiguard »

I apologize in advance. I am not good at explaining complex topics...

First, if you are not well-versed in Shape Meters, click here to view the documentation for them.

Second, several values I am going to be talking about are usually provided through a LUA script, called SunCalc. However, for debugging purposes, I have deleted all references to this script and converted those values into manually editable variables: #moonViewAngle#, #moonDialAngle, and #moonPhase#.

The Moon Icon

Before I can get to the actual issue, I need to explain how the moon icon itself works. Normally, there are three shapes involved: Border, Background, and Limb, which combine to make the icon:
2018-12-31 13_55_44-D__Settings_Caleb_Rainmeter_Skins_ModernGadgets_Settings_UnitTests_WeatherShapes.png
The border and background are simple circles, but the limb is a custom Path shape. Here is the standalone code for the moon icon, without all of the changes necessary to implement it into AstroDial:
astrodial-standalone-moon.gif
ShapeMoon.ini:

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Variables]
; Moon phase value: 0.0 (new) -> 0.5 (full) -> 1.0 (new)
moonPhase=0.0
; Angle that the illuminated limb of the moon will be displayed at (starting at north, going clockwise)
moonViewAngle=-131
; Set to 1 to use moonViewAngle, 0 to display horizontally
showMoonAngle=0
; Internal moon variables
moonRadius=60
moonBorderThickness=4
moonInnerRadius=(#moonRadius# - #moonBorderThickness#)
; Colors
colorBg=15,15,15
colorMoon=200,200,200
colorMoonBg=30,30,30
colorMoonBorder=70,70,70

; Converts the moon phase value into a radius value usable by the arc shape
[MeasureMoonShapePhaseCalc]
Measure=Calc
Formula=clamp(abs((#moonInnerRadius# * 4 * ((#moonPhase# > 0.5) ? (0.5 - (#moonPhase# - 0.5)) : #moonPhase#)) - #moonInnerRadius#),0,#moonInnerRadius#)
DynamicVariables=1

[MeterMoonShape]
Meter=Shape
Shape=Ellipse #moonRadius#,#moonRadius#,#moonRadius#,#moonRadius# | StrokeWidth 0 | Fill Color #colorMoonBorder#
Shape2=Ellipse #moonRadius#,#moonRadius#,#moonInnerRadius#,#moonInnerRadius# | StrokeWidth 0 | Fill Color #colorMoonBg#
Shape3=Path MoonArc | StrokeWidth 0 | Fill Color #colorMoon# | Rotate ((#showMoonAngle# = 1) ? (-#moonViewAngle#) : ((#moonPhase# > 0.5) ? -90 : 90)),#moonInnerRadius#,#moonInnerRadius# | Offset #moonBorderThickness#,#moonBorderThickness# | StrokeLineJoin Round
MoonArc=0,#moonInnerRadius# | ArcTo (#moonInnerRadius# * 2),#moonInnerRadius#,#moonInnerRadius#,[MeasureMoonShapePhaseCalc:],0,(((#moonPhase# > 0.25) && (#moonPhase# < 0.75)) ? 1 : 0) | ArcTo 0,#moonInnerRadius#,#moonInnerRadius#,#moonInnerRadius#,0,1
Padding=10,10,10,10
SolidColor=#colorBg#
DynamicVariables=1
LeftMouseUpAction=[!CommandMeasure MeasureMoonShapeActionTimer "Execute 1"]

; Temporary measure for debug purposes - animates between new moon and full moon, then back
[MeasureMoonShapeActionTimer]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat Increase, 16, 100 | Wait 1000 | Repeat Increase, 16, 100 | Reset
Increase=[!SetVariable moonPhase "(#moonPhase# + 0.005)"][!UpdateMeasure MeasureMoonShapePhaseCalc][!UpdateMeter MeterMoonShape][!UpdateMeasure MeasureMoonShapeActionTimer][!Redraw]
Reset=[!SetVariable moonPhase 0][!UpdateMeasure MeasureMoonShapePhaseCalc][!UpdateMeter MeterMoonShape][!UpdateMeasure MeasureMoonShapeActionTimer][!Redraw]
DynamicVariables=1
To create the limb, I use a Path to create a closed shape. The first segment is an arc shape that spans the width of the moon in the center (where the terminator line is in the example GIF above). This arc gets its Y radius from an equation that translates the SunCalc moon phase value (represented by the #moonPhase# variable) into said radius. Here is the equation:

Code: Select all

; Converts the moon phase value into a radius value usable by the arc shape
[MeasureMoonShapePhaseCalc]
Measure=Calc
Formula=clamp(abs((#moonInnerRadius# * 4 * ((#moonPhase# > 0.5) ? (0.5 - (#moonPhase# - 0.5)) : #moonPhase#)) - #moonInnerRadius#),0,#moonInnerRadius#)
DynamicVariables=1
Group=MoonShape
For the second segment, I simply use another arc that goes back to the starting point (the left side of the moon) in an arc that perfectly matches up with the intersection between the background border and the background itself.
2018-12-31 14_26_23-D__Settings_Caleb_Rainmeter_Skins_ModernGadgets_Settings_UnitTests_WeatherShapes.png
Now that I have the shape of the moon's illuminated limb correct, I need to rotate it to the correct angle. There are two options for this: If the #showMoonAngle# variable is set to 0, then the icon will default to displaying the moon from right to left, like so:
astrodial-standalone-showmoonangle-off.gif
It does this by checking the moon phase value. If it is between 0 and 0.5, that means that it is the first half of the moon cycle, so it rotates the limb 90 degrees clockwise. Once it passes full moon (#moonPhase# > 0.5), it rotates the limb to point the other way (from north, 90 degrees counterclockwise).

If #showMoonAngle# is set to 1, then the moon will rotate itself based on the #moonViewAngle# variable. This is another substitute SunCalc value that, when used with the actual script, defines the angle of the moon's illuminated limb from north, going counterclockwise, as it appears in real life. In other words, the limb will face the same direction as the actual moon is facing.

For example, if the moon's angle is 131 degrees, it will look like this:
astrodial-standalone-showmoonangle-on.gif
Alright, so now you know how the moon icon itself works. Let's move on to implementing it into AstroDial.

Implementing the Moon Icon into AstroDial

A (rather annoying) limitation of shape meters is that you can only perform one transformation of each type on a shape (see the Transformation Modifiers section of the Shape documentation). Therefore, since I already rotated the moon limb to get the correct angle, I cannot then go rotate it around the dial.

One way to circumvent this is to use the Combine shape. This shape will literally "combine" two or more shapes into a new shape. When the combining happens, all attribute modifiers are taken from the parent shape. Therefore, I cannot simply combine the border, background, and limb shapes into one, because then it looks like this:
astrodial-standalone-moon-combined-badly.png
Because of this, in order to use combine to be able to rotate the limb twice, I need to create another dummy background, and use the Intersect combine type to make it work:
astrodial-standalone-moon-combined-correctly.png
Since I didn't combine the border and background shapes, I will still need to rotate them separately from the limb shape. However, this is pretty easy, and works perfectly 100% of the time.

For all three shapes, I define the center of rotation for the dial, represented by the green dot:
astrodial-rotation-reference.png
To define the center of rotation, Rainmeter will start at the top-left of the shape's bounding box, and offset it by a certain number of pixels that you define. In this case, I offset it by the radius of the moon icon (#dialObjectRadius#), then add the dial radius to that. Then I go down by #dialObjectRadius#, so that it is located at the exact bottom-center of the dial arc.
astrodial-center of rotation reference-no limb rotation.png
Now that we have a center of rotation, all we need to do is tell it how many degrees to rotate. Do that, and you end up with this:
astrodial-rotation reference-130 degrees.png
Oh no! As you can see, when we rotate it around the dial, it adds that rotation to the limb as well. We can counter this simply by adding #moonDialAngle to #moonViewAngle#:
astrodial-center of rotation reference-limb rotation-broken.png
...And now we're to the original issue that I created this thread for.

Correcting for Bounding Box Movement

After much thought, and going back through and explaining to myself exactly how everything worked, I realized the problem:
astrodial-center of rotation reference-limb rotation.png
The issue lies with the limb rotation itself. As you can see in the above picture, when the limb is rotated, it changes the starting position of the limb shape's bounding box. This causes the defined center of dial rotation to be offset as well, which in turn, causes the dial rotation for the limb to become skewed. Thus, you end up with this (click to animate):
atrodial PROBLEMS.gif
So, how to fix it? I did come up with a partial solution. I realized that the sine of #moonViewAngle# would describe exactly how far away from the center of the icon that the top of the bounding box is, proportional to the full distance of #moonInnerRadius# (#dialObjectRadius# - #moonBorderThickness#). Same for cosine in the X direction:
astrodial-moonlimbbboffset-sinecosineexplain.png
Using this, I was able to counteract the offset and return the center of dial rotation back to where it is supposed to be:
astrodial-centerofrotationreference-limbrotation-withoffset.png
All appeared to be well in the world. I did some tests and it appeared to be fixed:
astrodial less-than-half fixed.gif
...That is, until I tried it with a moon phase that was greater than first quarter:
astrodial more-than-half broken.gif
The Current Problem

FINALLY, AT LAST, comes the problem that I haven't yet figured out how to solve. For phases greater than a quarter, taking the sine and cosine of #moonViewAngle# no longer accurately represents where the bounding box is:
astrodial-moonlimbbboffset-offsetnotright.png
The problem here is that the sine and cosine calculations depend on a straight line when referencing the angle (you can see this line by setting the phase to 0.25, or half moon). However, once you go greater than a half moon, this line is enveloped by the limb and can no longer be used as a reference point for the trigonometry. Thus, when it tries to calculate the values based on this "line", it doesn't work because the bounding box is no longer defined by that line.

This is where I am completely stuck. I hope the explanation made sense, and gives you a starting point to be able to help solve this problem. Thanks for reading my long-winded explanation, and thanks for having interest in helping me solve this. :D

AstroDial.ini:

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Variables]
; =========================
; DEBUG TESTING VARIABLES

; Sun / Moon Angles on the Dial (degrees)
sunDialAngle=-1
moonDialAngle=0
; Angle that the illuminated limb of the moon will face (degrees, starts North, counterclockwise)
rawMVA=220
; If set to 1, the moon will orient based on the value above. If set to 0, waxing will display on the right, and waning will display on the left.
showMoonAngle=1
; Moon phase value: 0.0 (new) -> 0.5 (full) -> 1.0 (new)
moonPhase=0.37

; =========================

; Colors
colorBg=15,15,15
colorDialArc=150,150,150
colorMoon=200,200,200
colorMoonBg=30,30,30
colorMoonBorder=70,70,70
colorSun=250,222,110
; Dial settings
dialRadius=250
dialStartX=3
dialArcThickness=6
dialObjectRadius=23
; Moon settings
moonBorderThickness=3
moonInnerRadius=(#dialObjectRadius# - #moonBorderThickness#)
moonArcStartX=(#dialStartX# - #dialObjectRadius#)
moonArcStartY=(#dialRadius# - #moonBorderThickness#)
moonViewAngle=((#rawMVA# + #moonDialAngle#) % 360)

; ==================================================
; MEASURES
; ==================================================

[MeasureSunDialVisibility]
Measure=Calc
Formula=#sunDialAngle#
IfCondition=(MeasureSunDialVisibility > 180) || (MeasureSunDialVisibility < 0)
IfTrueAction=[!SetVariable sunDialVisibility 0][!UpdateMeter MeterAstroDial][!Redraw]
IfFalseAction=[!SetVariable sunDialVisibility 255][!UpdateMeter MeterAstroDial][!Redraw]
DynamicVariables=1

[MeasureMoonDialVisibility]
Measure=Calc
Formula=#moonDialAngle#
IfCondition=(MeasureMoonDialVisibility > 180) || (MeasureMoonDialVisibility < 0)
IfTrueAction=[!SetVariable moonDialVisibility 0][!UpdateMeter MeterAstroDial][!Redraw]
IfFalseAction=[!SetVariable moonDialVisibility 255][!UpdateMeter MeterAstroDial][!Redraw]
DynamicVariables=1

; Converts the moon phase value into a radius value usable by the arc shape
[MeasureMoonShapePhaseCalc]
Measure=Calc
Formula=clamp(abs((#moonInnerRadius# * 4 * ((#moonPhase# > 0.5) ? (0.5 - (#moonPhase# - 0.5)) : #moonPhase#)) - #moonInnerRadius#),0,#moonInnerRadius#)
DynamicVariables=1
Group=MoonShape

; Adjusts the center of arc rotation for the moon limb shape in the X direction
[MeasureMoonLimbArcRotationXOffsetCalc]
Measure=Calc
DynamicVariables=1
Formula=(((#moonViewAngle# > 180) && (#moonViewAngle# < 360)) ? (#moonInnerRadius# * abs(cos(rad(#moonViewAngle#)))) : #moonInnerRadius#)
Group=MoonShape

; Adjusts the center of arc rotation for the moon limb shape in the Y direction
[MeasureMoonLimbArcRotationYOffsetCalc]
Measure=Calc
DynamicVariables=1
Formula=(((#moonViewAngle# <= 90) || (#moonViewAngle# >= 270)) ? #moonInnerRadius# : (#moonInnerRadius# * abs(sin(rad(#moonViewAngle#)))))
Group=MoonShape

; TEMPORARY DEBUG - rotates the moon's illuminated limb 360 degrees
[MeasureActionTimer]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat Increase, 16, 180
ActionList2=ResetMove | Repeat Move, 16, 180
ActionList3=ResetMove | Repeat Both, 16, 180
ActionList4=Repeat Increase, 16, 5
Increase=[!SetVariable rawMVA "(#rawMVA# + 2)"][!SetVariable moonViewAngle "((#rawMVA# + #moonDialAngle#) % 360)"][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
Move=[!SetVariable moonDialAngle "(#moonDialAngle# + 1)"][!SetVariable moonViewAngle "((#rawMVA# + #moonDialAngle#) % 360)"][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
Both=[!SetVariable rawMVA "(#rawMVA# + 2)"][!SetVariable moonDialAngle "(#moonDialAngle# + 1)"][!SetVariable moonViewAngle "((#rawMVA# + #moonDialAngle#) % 360)"][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
ResetMove=[!SetVariable moonDialAngle 0][!UpdateMeasureGroup MoonShape][!UpdateMeter MeterAstroDial][!UpdateMeasure MeasureActionTimer][!Redraw]
DynamicVariables=1

; ==================================================
; METERS
; ==================================================

[MeterAstroDial]
Meter=Shape
; Arc
Shape=Arc #dialStartX#,#dialRadius#,(#dialRadius# * 2 + #dialStartX#),#dialRadius#,#dialRadius#,#dialRadius# | StrokeWidth #dialArcThickness# | Stroke Color #colorDialArc# | StrokeStartCap Round | StrokeEndCap Round
; Sun
Shape2=Ellipse #dialStartX#,#dialRadius#,#dialObjectRadius#,#dialObjectRadius# | StrokeWidth 0 | Fill Color #colorSun#,#sunDialVisibility# | Rotate #sunDialAngle#,(#dialRadius# + #dialObjectRadius#),(#dialObjectRadius#)
; Moon
Shape3=Ellipse #dialStartX#,#dialRadius#,#dialObjectRadius#,#dialObjectRadius# | StrokeWidth 0 | Fill Color #colorMoonBorder#,#moonDialVisibility# | Rotate #moonDialAngle#,(#dialRadius# + #dialObjectRadius#),(#dialObjectRadius#)
Shape4=Ellipse #dialStartX#,#dialRadius#,#moonInnerRadius#,#moonInnerRadius# | StrokeWidth 0 | Fill Color #colorMoonBg#,#moonDialVisibility# | Rotate #moonDialAngle#,(#dialRadius# + #moonInnerRadius#),(#moonInnerRadius#)
Shape5=Ellipse #dialStartX#,#dialRadius#,#moonInnerRadius#,#moonInnerRadius# | StrokeWidth 0 | Fill Color #colorMoon#,#moonDialVisibility#
Shape6=Path MoonArc | StrokeWidth 0 | Fill Color #colorMoon# | Rotate (((#showMoonAngle# = 1) ? (-#moonViewAngle#) : ((#moonPhase# > 0.5) ? -90 : 90))),#moonInnerRadius#,#moonInnerRadius# | Offset #moonBorderThickness#,#moonBorderThickness# | StrokeLineJoin Round
MoonArc=#moonArcStartX#,#moonArcStartY# | ArcTo (#moonArcStartX# + (#moonInnerRadius# * 2)),#moonArcStartY#,#moonInnerRadius#,[MeasureMoonShapePhaseCalc:],0,(((#moonPhase# > 0.25) && (#moonPhase# < 0.75)) ? 1 : 0) | ArcTo #moonArcStartX#,#moonArcStartY#,#moonInnerRadius#,#moonInnerRadius#,0,1

Shape7=Combine Shape5 | Intersect Shape6 | Rotate #moonDialAngle#,(#dialRadius# + [MeasureMoonLimbArcRotationXOffsetCalc:]),([MeasureMoonLimbArcRotationYOffsetCalc:])

Shape8=Ellipse #dialRadius#,#dialRadius#,2 | StrokeWidth 0 | Fill Color 0,150,0

Padding=30,30,30,30
SolidColor=#colorBg#
DynamicVariables=1

[MeterDebugLimbRotation]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Limb Rotation
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 1"]
Antialias=1

[MeterDebugDialRotation]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Dial Rotation
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 2"]
Antialias=1

[MeterDebugBoth]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Both Rotations
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 3"]
Antialias=1

[MeterDebugStepLimb]
Meter=String
FontFace=Arial
FontSize=12
FontColor=230,230,230
Padding=5,5,5,5
SolidColor=#colorBg#
Y=R
Text=Debug Step Limb Rotation
LeftMouseUpAction=[!CommandMeasure MeasureActionTimer "Execute 4"]
Antialias=1
You do not have the required permissions to view the files attached to this post.
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
GTI.H
Posts: 75
Joined: December 15th, 2018, 3:35 am

Re: [Lots of Math] Moon Icon Rotation on a Sky Dial

Post by GTI.H »

Good work, good explanation.

I feel that a bigger issue is your approach to this issue. When we have a good approach, everything flows better.

Intuitively, without debugging your code I would bet on the following solution:

Based on this image (I had already felt the issue was here, the difficulty is to immerse and describe our thoughts):
Image

While we can not find a better solution, try to calculate the center of the Limb by the quadrant that is still integral (the fourth quadrant: the lower right in this image), as the Limb passes through the center, switch and consider the entire quadrant of the other arc (Black arc: In the second quadrant, Upper left).

Another attempt would be to replace the center of the Limb with the center of the border or Background that you have combined to make the moon icon, to relate the Limb with the Border or Background, perhaps a sum of the black and white arcs.


--
Regards
GTI