Re: [NTG-context] atan2 function
On Fri, 14 Oct 2022 16:09:41 -0700 Thangalin wrote: > Would making the conditional part of the API be useful to others? Of course, $\tan^{-1}(\pm 1)$ is undefined (mathematically). Alan ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
That's certainly tighter, thank you, Alan. Would making the conditional part of the API be useful to others? Cheers! On Fri, Oct 14, 2022 at 3:42 PM Alan Braslau wrote: > > On Fri, 14 Oct 2022 11:59:49 -0700 > Thangalin wrote: > > > I don't think an atantwo is needed. I *thought* I had read somewhere > > that atan( y, x ) was equivalent to calling atan2 in Lua. Ensuring > > there's no breakage when x == y would be nice, though. It was a little > > surprising to see angle return degrees rather than radians, but it > > does simplify my code: > > > > dc := vbc - vac; > > dr := vbr - var; > > vi := 0; > > > > if not( dc == dr ): > > vi := round( angle( dc, dr ) / 60 ); > > fi; > > > > % Compute the direction towards the first segment (to vertex of > > an edge). vangle := vi * 60 * pi / 180; > > > > Even simpler would be: > > > > dc := vbc - vac; > > dr := vbr - var; > > vi := round( angle( dc, dr ) / 60 ); % returns 0 when dc == dr > > > > % Compute the direction towards the first segment (to vertex of > > an edge). vangle := vi * 60 * pi / 180; > > > > Or accepting a third argument as the return value in the special case: > > > > vi := round( angle( dc, dr, 0 ) / 60 ); % returns 0 when dc == > > dr > > > > Cheers! > > vi := if (dc = dr) : 0 else : round (angle(dc,dr)/60) fi ; > > Alan ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
On Fri, 14 Oct 2022 11:59:49 -0700 Thangalin wrote: > I don't think an atantwo is needed. I *thought* I had read somewhere > that atan( y, x ) was equivalent to calling atan2 in Lua. Ensuring > there's no breakage when x == y would be nice, though. It was a little > surprising to see angle return degrees rather than radians, but it > does simplify my code: > > dc := vbc - vac; > dr := vbr - var; > vi := 0; > > if not( dc == dr ): > vi := round( angle( dc, dr ) / 60 ); > fi; > > % Compute the direction towards the first segment (to vertex of > an edge). vangle := vi * 60 * pi / 180; > > Even simpler would be: > > dc := vbc - vac; > dr := vbr - var; > vi := round( angle( dc, dr ) / 60 ); % returns 0 when dc == dr > > % Compute the direction towards the first segment (to vertex of > an edge). vangle := vi * 60 * pi / 180; > > Or accepting a third argument as the return value in the special case: > > vi := round( angle( dc, dr, 0 ) / 60 ); % returns 0 when dc == > dr > > Cheers! vi := if (dc = dr) : 0 else : round (angle(dc,dr)/60) fi ; Alan ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
I don't think an atantwo is needed. I *thought* I had read somewhere that atan( y, x ) was equivalent to calling atan2 in Lua. Ensuring there's no breakage when x == y would be nice, though. It was a little surprising to see angle return degrees rather than radians, but it does simplify my code: dc := vbc - vac; dr := vbr - var; vi := 0; if not( dc == dr ): vi := round( angle( dc, dr ) / 60 ); fi; % Compute the direction towards the first segment (to vertex of an edge). vangle := vi * 60 * pi / 180; Even simpler would be: dc := vbc - vac; dr := vbr - var; vi := round( angle( dc, dr ) / 60 ); % returns 0 when dc == dr % Compute the direction towards the first segment (to vertex of an edge). vangle := vi * 60 * pi / 180; Or accepting a third argument as the return value in the special case: vi := round( angle( dc, dr, 0 ) / 60 ); % returns 0 when dc == dr Cheers! ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
On Fri, 14 Oct 2022 10:07:19 +0200 Hans Hagen via ntg-context wrote: > So you suggest to add atantwo? As side note, you can redure your > definition to: > > vardef atantwo(expr dy, dx) = > if dx == 0 : > if dy < 0 : - fi pi / 2 > else : > atan(dy/dx) if dx > 0 : if dy < 0 : - else : + fi pi fi > fi > enddef ; > > going further makes us end up in an one-line obscurity An absurdity, as further discussion on this thread has shown: atan is derived from angle, which is essentially atan2. There is no need to circle around. As a side point, I now use MP doubleprecision mode by default, although I do believe that it is still preferable to use classic scaled integer mode (and minifun) for text graphical embellishments. The only practical point to consider when using doubleprecision mode for me is the need to explicitly use format with "decimal i" to round the text rendering of numbers. Alan ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
On Fri, 14 Oct 2022 at 14:58, Taco Hoekwater via ntg-context < ntg-context@ntg.nl> wrote: > > > > On 14 Oct 2022, at 14:26, Alan Braslau via ntg-context < > ntg-context@ntg.nl> wrote: > > > > Are you using MP in scaled integer or in doubleprecision mode? > > > > I have not looked into the MP angle operator code, but my suspicion is > that it is based on some super-clever John Hobby scheme optimized for > scaled integer calculations. > > The scaled version of “angle” is a handwritten approximation in web, not > using > any math library. I really doubt that that code is faster than calling > atan2() > on a modern machine, but I’ve kept it in because using a lib might give > slightly > different results. > iirc, in metapost the whole scaled number system has no dependency from any external math library (I have not checked the lmtx source yet). ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
> On 14 Oct 2022, at 14:26, Alan Braslau via ntg-context > wrote: > > Are you using MP in scaled integer or in doubleprecision mode? > > I have not looked into the MP angle operator code, but my suspicion is that > it is based on some super-clever John Hobby scheme optimized for scaled > integer calculations. The scaled version of “angle” is a handwritten approximation in web, not using any math library. I really doubt that that code is faster than calling atan2() on a modern machine, but I’ve kept it in because using a lib might give slightly different results. The double version of “angle" uses atan2() internally already, so that the atantwo macro is just duplicating the internals for that case. The decimal version of “angle’ uses a dedicated decNumberAtan2() library call. > > Hans has integrated the entire math library (and more) into lmtx. > > On 13/10/22 13/10/22, 13:51, Thangalin via ntg-context wrote: >> Thank you, Max. >> The angle function doesn't appear to provide the same calculation as >> my atantwo in all cases. >> https://pdfhost.io/v/Oqj7XmibJ_scaled >> The shorter line segment should be directed towards the vertex closest >> to the longer line segment. I tried using both: >> theta := angle( dx, dy ); >> theta := angle( dy, dx ); >> Neither made a difference, in some cases the angle differs from what I'd >> expect. >> My implementation is based on the first version given here: >> https://en.wikipedia.org/wiki/Atan2#Definition_and_computation >> I have something that works, so this is more of a curiosity as to >> there being a difference between my implementation of atantwo and the >> angle function. >> Here's an example with many lines and the angle function: >> https://pdfhost.io/v/1T4jgBnxh_scaled >> On Wed, Oct 12, 2022 at 11:42 PM Max Chernoff wrote: >>> >>> Hi, >>> How is atan2 called? I rolled my own as follows: >>> Is atan with two parameters supposed to behave like atan2? >>> >>> At mp-math.mpxl:167 there is: >>> >>>vardef atan primary x = angle(1,x) enddef ; >>> >>> The MetaPost manual says: >>> >>>The angle operator takes a pair and computes the two-argument >>>arctangent; i.e., angle is the inverse of the dir operator >>> >>> So it looks like "angle" is the function that you want for "atan2". >>> >>> Thanks, >>> -- Max >> ___ >> If your question is of interest to others as well, please add an entry to >> the Wiki! >> maillist : ntg-context@ntg.nl / >> https://www.ntg.nl/mailman/listinfo/ntg-context >> webpage : https://www.pragma-ade.nl / http://context.aanhet.net >> archive : https://bitbucket.org/phg/context-mirror/commits/ >> wiki : https://contextgarden.net >> ___ > > \ > > ___ > If your question is of interest to others as well, please add an entry to the > Wiki! > > maillist : ntg-context@ntg.nl / > https://www.ntg.nl/mailman/listinfo/ntg-context > webpage : https://www.pragma-ade.nl / http://context.aanhet.net > archive : https://bitbucket.org/phg/context-mirror/commits/ > wiki : https://contextgarden.net > ___ — Taco Hoekwater E: t...@bittext.nl genderfluid (all pronouns) ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
Are you using MP in scaled integer or in doubleprecision mode? I have not looked into the MP angle operator code, but my suspicion is that it is based on some super-clever John Hobby scheme optimized for scaled integer calculations. Hans has integrated the entire math library (and more) into lmtx. On 13/10/22 13/10/22, 13:51, Thangalin via ntg-context wrote: Thank you, Max. The angle function doesn't appear to provide the same calculation as my atantwo in all cases. https://pdfhost.io/v/Oqj7XmibJ_scaled The shorter line segment should be directed towards the vertex closest to the longer line segment. I tried using both: theta := angle( dx, dy ); theta := angle( dy, dx ); Neither made a difference, in some cases the angle differs from what I'd expect. My implementation is based on the first version given here: https://en.wikipedia.org/wiki/Atan2#Definition_and_computation I have something that works, so this is more of a curiosity as to there being a difference between my implementation of atantwo and the angle function. Here's an example with many lines and the angle function: https://pdfhost.io/v/1T4jgBnxh_scaled On Wed, Oct 12, 2022 at 11:42 PM Max Chernoff wrote: Hi, How is atan2 called? I rolled my own as follows: Is atan with two parameters supposed to behave like atan2? At mp-math.mpxl:167 there is: vardef atan primary x = angle(1,x) enddef ; The MetaPost manual says: The angle operator takes a pair and computes the two-argument arctangent; i.e., angle is the inverse of the dir operator So it looks like "angle" is the function that you want for "atan2". Thanks, -- Max ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___ \ ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
On 10/14/2022 2:35 AM, Max Chernoff via ntg-context wrote: Hi, The angle function doesn't appear to provide the same calculation as my atantwo in all cases. They both give the same results, but "angle" gives a result in degrees while "atantwo" gives a result in radians. This demo: \startMPpage vardef atantwo( expr dy, dx ) = save theta; numeric theta; theta := 0; if (dx > 0): theta := atan( dy / dx ); elseif (dx < 0) and (dy >= 0): theta := atan( dy / dx ) + pi; elseif (dx < 0) and (dy < 0): theta := atan( dy / dx ) - pi; elseif (dx == 0) and (dy > 0): theta := pi / 2; elseif (dx == 0) and (dy < 0): theta := -pi / 2; fi; theta enddef; def showangles(expr dx, dy) = message "---" message "atantwo " & decimal atantwo(dy, dx) message "angle " & decimal (angle(dx, dy) * pi / 180) message "angle " & decimal angle(dx, dy) message "(" & decimal dx & ", " & decimal dy & ")" enddef; showangles(1, 0); showangles(1, 1); showangles(0, 1); showangles(-1, 1); showangles(-1, 0); showangles(-1, -1); showangles(0, -1); showangles(1, -1); \stopMPpage So you suggest to add atantwo? As side note, you can redure your definition to: vardef atantwo( expr dy, dx ) = if (dx > 0): atan( dy / dx ) elseif (dx < 0) and (dy >= 0): atan( dy / dx ) + pi elseif (dx < 0) and (dy < 0): atan( dy / dx ) - pi elseif (dx == 0) and (dy > 0): pi / 2 elseif (dx == 0) and (dy < 0): -pi / 2 else : 0 fi enddef ; and then vardef atantwo(expr dy, dx) = if dx == 0 : if dy < 0 : - fi pi / 2 else : atan(dy/dx) if dx > 0 : if dy < 0 : - else : + fi pi fi fi enddef ; going further makes us end up in an one-line obscurity Hans - Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl - ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
Hi, > The angle function doesn't appear to provide the same calculation as > my atantwo in all cases. They both give the same results, but "angle" gives a result in degrees while "atantwo" gives a result in radians. This demo: \startMPpage vardef atantwo( expr dy, dx ) = save theta; numeric theta; theta := 0; if (dx > 0): theta := atan( dy / dx ); elseif (dx < 0) and (dy >= 0): theta := atan( dy / dx ) + pi; elseif (dx < 0) and (dy < 0): theta := atan( dy / dx ) - pi; elseif (dx == 0) and (dy > 0): theta := pi / 2; elseif (dx == 0) and (dy < 0): theta := -pi / 2; fi; theta enddef; def showangles(expr dx, dy) = message "---" message "atantwo " & decimal atantwo(dy, dx) message "angle " & decimal (angle(dx, dy) * pi / 180) message "angle " & decimal angle(dx, dy) message "(" & decimal dx & ", " & decimal dy & ")" enddef; showangles(1, 0); showangles(1, 1); showangles(0, 1); showangles(-1, 1); showangles(-1, 0); showangles(-1, -1); showangles(0, -1); showangles(1, -1); \stopMPpage gives: (1, 0) angle 0 angle 0 atantwo 0 --- (1, 1) angle 45 angle 0.78539816339744828 atantwo 0.78539816339744828 --- (0, 1) angle 90 angle 1.5707963267948966 atantwo 1.5707963267948966 --- (-1, 1) angle 135 angle 2.3561944901923448 atantwo 2.3561944901923448 --- (-1, 0) angle 180 angle 3.1415926535897931 atantwo 3.1415926535897931 --- (-1, -1) angle -135 angle -2.3561944901923448 atantwo -2.3561944901923448 --- (0, -1) angle -90 angle -1.5707963267948966 atantwo -1.5707963267948966 --- (1, -1) angle -45 angle -0.78539816339744828 atantwo -0.78539816339744828 --- Thanks, -- Max ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
Thank you, Max. The angle function doesn't appear to provide the same calculation as my atantwo in all cases. https://pdfhost.io/v/Oqj7XmibJ_scaled The shorter line segment should be directed towards the vertex closest to the longer line segment. I tried using both: theta := angle( dx, dy ); theta := angle( dy, dx ); Neither made a difference, in some cases the angle differs from what I'd expect. My implementation is based on the first version given here: https://en.wikipedia.org/wiki/Atan2#Definition_and_computation I have something that works, so this is more of a curiosity as to there being a difference between my implementation of atantwo and the angle function. Here's an example with many lines and the angle function: https://pdfhost.io/v/1T4jgBnxh_scaled On Wed, Oct 12, 2022 at 11:42 PM Max Chernoff wrote: > > Hi, > > > How is atan2 called? I rolled my own as follows: > > > Is atan with two parameters supposed to behave like atan2? > > At mp-math.mpxl:167 there is: > >vardef atan primary x = angle(1,x) enddef ; > > The MetaPost manual says: > >The angle operator takes a pair and computes the two-argument >arctangent; i.e., angle is the inverse of the dir operator > > So it looks like "angle" is the function that you want for "atan2". > > Thanks, > -- Max ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___
Re: [NTG-context] atan2 function
Hi, > How is atan2 called? I rolled my own as follows: > Is atan with two parameters supposed to behave like atan2? At mp-math.mpxl:167 there is: vardef atan primary x = angle(1,x) enddef ; The MetaPost manual says: The angle operator takes a pair and computes the two-argument arctangent; i.e., angle is the inverse of the dir operator So it looks like "angle" is the function that you want for "atan2". Thanks, -- Max ___ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context webpage : https://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : https://contextgarden.net ___