It is currently March 28th, 2024, 8:54 pm

Atan2 math function

Changes made during the Rainmeter 3.2 beta cycle.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Atan2 math function

Post by jsmorley »

Thanks to dgrace for the code to add the Atan2(y,x) function to the math formulas.

Atan2(y,x) Returns the radians of arc tangent between points Y and X in the Cartesian plane. The sign of the elements determines the quadrant.

This can be useful for a lot of things, but one way to demonstrate how you might use it is to "draw an angled line between two points" in your skin.

If you have two points (meters) on your skin, a red one and a blue one in this instance:
1.png
You might want to draw a line between them;
2.png
To do this with a Roundline meter, you basically need to take these steps:

1) Get the X and Y positions of the two points.
2) Get the width and height of the triangle this creates. This gives you two of the sides of the "triangle", you just need the
third side. That will be the "line".
3) Use a formula to calculate the length (LineLength) of the third side of the triangle.
4) Use a formula to calculate the "arc angle" (RotationAngle) in radians between the two points.

So if we start with this code:

Code: Select all

[MeterPointA]
Meter=Image
X=0
Y=136
W=6
H=6
SolidColor=255,0,0,255

[MeterPointB]
Meter=Image
X=283
Y=0
W=6
H=6
SolidColor=191,235,255,255
That creates our red and blue points as in the first image.

Now we can create our Roundline meter, using the new Atan2 function to get our RotationAngle value.

Code: Select all

[MeterLineAtoB]
Meter=Roundline
X=([MeterPointA:X]+([MeterPointA:W]/2))
Y=([MeterPointA:Y]+([MeterPointA:H]/2))
LineColor=255,255,255,255
LineWidth=2
LineLength=(Sqrt((([MeterPointA:X]-[MeterPointB:X])**2)+(([MeterPointA:Y]-[MeterPointB:Y])**2)))
StartAngle=Rad(360)
RotationAngle=(Atan2([MeterPointB:Y]-[MeterPointA:Y], [MeterPointB:X]-[MeterPointA:X]))
AntiAlias=1
DynamicVariables=1
That draws our line in the second image, and that's all there is to it.

We can add some "dynamic" values for the positions of A and B, and see it in action:

Code: Select all

[Rainmeter]
Update=1000
BackgroundMode=2
SolidColor=20,30,40,255

[MeasureCounterX]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=100
HighBound=300

[MeasureCounterY]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=50
HighBound=150

[MeterPointA]
Meter=Image
X=0
Y=[MeasureCounterY]
W=6
H=6
SolidColor=255,0,0,255
DynamicVariables=1

[MeterPointB]
Meter=Image
X=[MeasureCounterX]
Y=0
W=6
H=6
SolidColor=191,235,255,255
DynamicVariables=1

[MeterLineAtoB]
Meter=Roundline
X=([MeterPointA:X]+([MeterPointA:W]/2))
Y=([MeterPointA:Y]+([MeterPointA:H]/2))
LineColor=255,255,255,255
LineWidth=2
LineLength=(Sqrt((([MeterPointA:X]-[MeterPointB:X])**2)+(([MeterPointA:Y]-[MeterPointB:Y])**2)))
StartAngle=Rad(360)
RotationAngle=(Atan2([MeterPointB:Y]-[MeterPointA:Y], [MeterPointB:X]-[MeterPointA:X]))
AntiAlias=1
DynamicVariables=1
test.gif
You do not have the required permissions to view the files attached to this post.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5382
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Atan2 math function

Post by eclectic-tech »

Pythagoras is :D about now

This will come in handy in my 'perspective' grid project :o

Thanks Dev Team! :thumbup:
Last edited by eclectic-tech on February 4th, 2015, 4:07 pm, edited 1 time in total.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Atan2 math function

Post by jsmorley »

Image
User avatar
WyzzyMoon
Posts: 10
Joined: February 9th, 2016, 8:34 pm

Re: Atan2 math function

Post by WyzzyMoon »

Thanks so much for the explanation, now I understand Atan2, I however noticed that you're calculation for line length didn't work correctly, at least for my senario.
I build a clock with it where the points are connected ( http://wyzzymoon.deviantart.com/art/Clockstellation-586438351 )
And sometimes the lines would suddenly be longer or shorter at weird moments.
Using just Pythagorean Theorem for the length calculation fixed it for me.
So that would make
LineLength=(Sqrt((([MeterPointB:X]-[MeterPointB:X])*([MeterPointB:X]-[MeterPointB:X]))+(([MeterPointB:Y]-[MeterPointB:Y])*([MeterPointB:Y]-[MeterPointB:Y]))))

Than you remove Atan2 and Cos from the Distance calculation and that makes it ( for me at least ) a lot more reliable.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5382
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Atan2 math function

Post by eclectic-tech »

WyzzyMoon wrote:Thanks so much for the explanation, now I understand Atan2, I however noticed that you're calculation for line length didn't work correctly, at least for my senario.
...
WyzzyMoon did find a repeatable issue with the built-in function.

When the X values are equal, you will get incorrect values, either too large or too small, depending on the quadrants the line are drawn. Lines drawn from quandrant I to quadrant IV are too long when X is equal. From quadrant II to quadrant III are too short.

Try his skin to see the action. Hope this helps find the issue...
Edit: Not sure where the change is needed, in the skin code or in the atan2 function... :???:
Last edited by eclectic-tech on February 9th, 2016, 11:44 pm, edited 1 time in total.
User avatar
dgrace
Developer
Posts: 265
Joined: June 28th, 2014, 8:32 am
Location: Tokyo, Japan

Re: Atan2 math function

Post by dgrace »

Good point - length is always better calculated off the cartesian coords, rather than using reverse trig. (It's also more efficient)

dave
User avatar
WyzzyMoon
Posts: 10
Joined: February 9th, 2016, 8:34 pm

Re: Atan2 math function

Post by WyzzyMoon »

eclectic-tech wrote:WyzzyMoon did find a repeatable issue with the built-in function.

When the X values are equal, you will get incorrect values, either too large or too small, depending on the quadrants the line are drawn. Lines drawn from quandrant I to quadrant IV are too long when X is equal. From quadrant II to quadrant III are too short.

Try his skin to see the action. Hope this helps find the issue...
Edit: Not sure where the change is needed, in the skin code or in the atan2 function... :???:
interesting, you actually figured out what the issue was, I didn't get any further than "weird".
The newest version on my Deviantart ( V1.4 ) fixed the issue by not using ATAN for the length calculation as I explained before but in the attachments I'll inlcude the old V1.3 with the issue and new V1.4 without so someone can see the issue in action now that 1.3 is no longer available form deviantart.
You do not have the required permissions to view the files attached to this post.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5382
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Atan2 math function

Post by eclectic-tech »

I am returning to this to see if there is a solution.

As mentioned by wzzymoon, there is an issue when using this example.

Here is a slightly modified version (points changed, but not the formulas), that can show the issue.
This skin draws a center red point and draws lines to random secondary points every 3 seconds
To see the issue, set the lowbound and high bound of [MeasureCounterX1] (normally a random point) equal to [MeasureCounterX] (the center fixed point)
The skin does not draw the connecting line vertically to the random Y points ???

This causes strange results when used in skins.

Can this can be investigated? Thanks!
(Edited code: Correction suggested by balala fixes this issue)

Code: Select all

; This skin draws a center red point and draws lines to random secondary points every 3 seconds
; Corrected to use different formula for LineLength and eliminate drawing error
[Rainmeter]
Update=3000
BackgroundMode=2
SkinWidth=312
SkinHeight=180
SolidColor=20,30,40,255

[MeasureCounterX]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=156
HighBound=156

[MeasureCounterY]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=90
HighBound=90

[MeasureCounterX1]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=0
HighBound=300

[MeasureCounterY1]
Measure=Calc
Formula=Random
UpdateRandom=1
LowBound=20
HighBound=170

[MeterPointA]
Meter=Image
X=[MeasureCounterX]
Y=[MeasureCounterY]
W=6
H=6
SolidColor=255,0,0,255
DynamicVariables=1

[MeterPointB]
Meter=Image
X=[MeasureCounterX1]
Y=[MeasureCounterY1]
W=6
H=6
SolidColor=191,235,255,255
DynamicVariables=1

[MeterLineAtoB]
Meter=Roundline
X=([MeterPointA:X]+([MeterPointA:W]/2))
Y=([MeterPointA:Y]+([MeterPointA:H]/2))
LineColor=255,255,255,255
LineWidth=2
LineLength=(Sqrt((([MeterPointA:X]-[MeterPointB:X])**2)+(([MeterPointA:Y]-[MeterPointB:Y])**2)))
StartAngle=Rad(360)
RotationAngle=(Atan2([MeterPointB:Y]-[MeterPointA:Y], [MeterPointB:X]-[MeterPointA:X]))
AntiAlias=1
DynamicVariables=1

[MeterLabel]
Meter=String
MeasureName=MeasureCounterX1
MeasureName2=MeasureCounterY1
FontColor=255,255,255
Text=PointB: ( %1, %2 )
Edit: Modified the code for LineLength formula to use the Pythagorean formula versus the original example. Now the example draws lines properly.
Thanks FreeRaider & balala for your help!
Last edited by eclectic-tech on October 1st, 2016, 4:46 pm, edited 1 time in total.
User avatar
FreeRaider
Posts: 826
Joined: November 20th, 2012, 11:58 pm

Re: Atan2 math function

Post by FreeRaider »

I am not a mathematician, but when I set the low bound and high bound of [MeasureCounterX1] equal to [MeasureCounterX], I have [PointB:X] = [PointA:X].

If I am right, this LineLength=(([MeterPointB:X]-[MeterPointA:X])/Cos(Atan2([MeterPointB:Y]-[MeterPointA:Y], [MeterPointB:X]-[MeterPointA:X]))) is equal to zero, thus no LineAtoB is drawn.

Am I right?
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5382
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Atan2 math function

Post by eclectic-tech »

FreeRaider wrote:I am not a mathematician, but when I set the low bound and high bound of [MeasureCounterX1] equal to [MeasureCounterX], I have [PointB:X] = [PointA:X].

If I am right, this LineLength=(([MeterPointB:X]-[MeterPointA:X])/Cos(Atan2([MeterPointB:Y]-[MeterPointA:Y], [MeterPointB:X]-[MeterPointA:X]))) is equal to zero, thus no LineAtoB is drawn.

Am I right?
I am not a mathematician either, you are right, that does result in zero length.

So I am asking sharper minds than mine, what might need to change when the X points are equal :???: