<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Fun With SAS ODS Graphics: New Year's Eve Newton's Cradle Ball Drop in Graphics Programming</title>
    <link>https://communities.sas.com/t5/Graphics-Programming/Fun-With-SAS-ODS-Graphics-New-Year-s-Eve-Newton-s-Cradle-Ball/m-p/955231#M25227</link>
    <description>So clever! Thanks for sharing this.</description>
    <pubDate>Mon, 06 Jan 2025 18:52:42 GMT</pubDate>
    <dc:creator>ChrisHemedinger</dc:creator>
    <dc:date>2025-01-06T18:52:42Z</dc:date>
    <item>
      <title>Fun With SAS ODS Graphics: New Year's Eve Newton's Cradle Ball Drop</title>
      <link>https://communities.sas.com/t5/Graphics-Programming/Fun-With-SAS-ODS-Graphics-New-Year-s-Eve-Newton-s-Cradle-Ball/m-p/954737#M25206</link>
      <description>&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="nye2025.gif" style="width: 768px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/103400i48563A01625FE8E2/image-size/large?v=v2&amp;amp;px=999" role="button" title="nye2025.gif" alt="nye2025.gif" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's a &lt;A href="https://en.wikipedia.org/wiki/Newton%27s_cradle" target="_self"&gt;Newton's Cradle&lt;/A&gt;-inspired animated GIF &lt;A href="https://en.wikipedia.org/wiki/List_of_objects_dropped_on_New_Year%27s_Eve" target="_self"&gt;ball drop&lt;/A&gt; to roll out the old year - Happy New Year, all!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* Fun With SAS ODS Graphics: New Year's Eve Newton's Cradle Ball Drop
  Info on Newton's Cradle at en.wikipedia.org/wiki/Newton%27s_cradle;

data balls;                                      * Generate x/y points for 4 balls in Newton's Cradle;
r=7.45; y0=8; pi=constant("pi");                 * End balls swing through 30 degree arcs, middle balls stay contant;
do outerframe=0 to 11;                           * 12 time periods - beginning, 10-to-0 seconds countdown, end ending;            
if outerframe=11 then do; mtext='HAPPY NEW YEAR!'; mX=0; mY=8.3; end; * 11th frame displays Happy New Year!; 
ball=1; text='2'; x0=-1.5;                       * Ball one ('2') swings through 30 degree arc;         
frame=0;
do a=90 to 120 by 6, 120 to 96 by -6;
  radians=2*pi*a/360;
  x=x0+r*cos(radians);
  y=y0-r*sin(radians);
  angle=-(a-90);                                 * Ball only swings on alternate time periods;
  if outerframe in (0, 11) or mod(outerframe,2)=0 then do; angle=0; x=x0; y=y0-r; end; 
  frame+1;
  output;
end;                                             * Balls two ('0') and three ('2') are fixed and do not swing;
ball=2; text='0'; x=-.5; x0=-.5; y=y0-r; angle=0; do frame=1 to 11; output; end;
ball=3; text='2'; x=.5; x0=.5; y=y0-r; angle=0; do frame=1 to 11; output; end;
ball=4; text='4'; x0=1.5;
frame=0;
do a=-270 to -300 by -6, -300 to -276 by 6;      * Ball four ('4' or '5') swings through 30 degree arc;
  radians=2*pi*a/360;
  x=x0+r*cos(radians);
  y=y0-r*sin(radians);
  angle=-(a+270);                                * Ball only swings on alternate time periods;
  if outerframe in (0, 11) or ^mod(outerframe,2)=0 then do; angle=0; x=x0; y=y0-r; end; 
  frame+1;
  output;
end;
end;

proc sql;                                        * No arcs for first/last loops, flip year from 2024 --&amp;gt; 2025 on last swing return;
delete from balls where outerframe in (0,11) and frame&amp;gt;1;
update balls set text='5' where ball=4 and (outerframe=11 or (outerframe&amp;gt;=10 and frame&amp;gt;=8));

proc sort data=balls; by outerframe frame;       * Order to allow BY statement to be used in plots;

ods graphics / reset height=8in width=8in noborder;  * Create animated GIF from generated images;
options nobyline papersize=('8 in', '8 in') animduration=2 animloop=yes printerpath=gif animation=start nodate nonumber;
ods printer file='~/nye/nye2025.gif';            * Animated GIF filename;

%macro genplots;                                 /* Use macros to produce 12 sets of frames */
%macro genplot(n);                               /* Each set of frames takes about 1 second (countdown) with pauses before and after */
%if       &amp;amp;n=0  %then options animduration=1.5 %str(; run;); /* Opening frame */ 
%else %if &amp;amp;n=11 %then options animduration=2   %str(; run;); /* Countdown frames */
%else                 options animduration=.1  %str(; run;); /* Final frame (2025) */
                                                 /* Plot the Newton's Cradle (Vector+Ellipse+Text plots) */
proc sgplot data=balls(where=(outerframe=&amp;amp;n)) nowall noautolegend nowall noborder noautolegend;
by outerframe frame;                             /* Use BY statement to create multiple plots for animation */
styleattrs backcolor=black;                      /* Black background */
vector x=x y=y / noarrowheads xorigin=x0 yorigin=y0 lineattrs=(color=cxa9acb6 thickness=2.5pt); /* Strings */
ellipseparm semimajor=.5 semiminor=.5 / xorigin=x yorigin=y nooutline lineattrs=(color=cxa9acb6) fill fillattrs=(color=cxa9acb6); /* Balls */
text x=x y=y text=text / rotate=angle strip textattrs=(color=black size=36pt weight=bold) contributeoffsets=none; /* Year digits */
refline 8.3 / axis=y lineattrs=(thickness=28pt color=cxa9acb6); /* Newton's cradle bar */
text x=mX y=mY text=mText / strip textattrs=(color=black size=20pt weight=bold) contributeoffsets=none; /* Happy New Year! message */
xaxis display=none values=(-5 5) offsetmin=0 offsetmax=0; /* Suppress axis info, limit bounds */
yaxis display=none values=(-1 9) offsetmin=0 offsetmax=0; /* Suppress axis info, limit bounds */
inset %if &amp;amp;n=0 %then "0:10"; %else %if &amp;amp;n=11 %then "0:00"; %else "0:%sysfunc(putn(%eval(10-&amp;amp;n+1),z2.))"; / position=bottom noborder textattrs=(color=cxa9acb6 size=24pt); /* Countdown timer */
run;   
%mend;
%do n=0 %to 11; %genplot(&amp;amp;n); %end;              /* 12 sets of frames */
%mend;
%genplots;
                   
options printerpath=gif animation=stop;          * Stop recording images;
ods printer close;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 30 Dec 2024 00:26:04 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Graphics-Programming/Fun-With-SAS-ODS-Graphics-New-Year-s-Eve-Newton-s-Cradle-Ball/m-p/954737#M25206</guid>
      <dc:creator>tc</dc:creator>
      <dc:date>2024-12-30T00:26:04Z</dc:date>
    </item>
    <item>
      <title>Re: Fun With SAS ODS Graphics: New Year's Eve Newton's Cradle Ball Drop</title>
      <link>https://communities.sas.com/t5/Graphics-Programming/Fun-With-SAS-ODS-Graphics-New-Year-s-Eve-Newton-s-Cradle-Ball/m-p/955231#M25227</link>
      <description>So clever! Thanks for sharing this.</description>
      <pubDate>Mon, 06 Jan 2025 18:52:42 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Graphics-Programming/Fun-With-SAS-ODS-Graphics-New-Year-s-Eve-Newton-s-Cradle-Ball/m-p/955231#M25227</guid>
      <dc:creator>ChrisHemedinger</dc:creator>
      <dc:date>2025-01-06T18:52:42Z</dc:date>
    </item>
  </channel>
</rss>

