%%%% sundl_01.ldf %%%% Created by Laurence D. Finston (LDF) Thu Sep 27 17:57:57 CEST 2007 %% $Id: sundl_01.ldf,v 1.5 2007/10/02 17:21:47 lfinsto1 Exp $ %% * (1) Copyright and License. %%%% This file is part of GNU 3DLDF, a package for three-dimensional drawing. %%%% Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 The Free Software Foundation, Inc. %%%% GNU 3DLDF is free software; you can redistribute it and/or modify %%%% it under the terms of the GNU General Public License as published by %%%% the Free Software Foundation; either version 3 of the License, or %%%% (at your option) any later version. %%%% GNU 3DLDF is distributed in the hope that it will be useful, %%%% but WITHOUT ANY WARRANTY; without even the implied warranty of %%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %%%% GNU General Public License for more details. %%%% You should have received a copy of the GNU General Public License %%%% along with GNU 3DLDF; if not, write to the Free Software %%%% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA %%%% GNU 3DLDF is a GNU package. %%%% It is part of the GNU Project of the %%%% Free Software Foundation %%%% and is published under the GNU General Public License. %%%% See the website http://www.gnu.org %%%% for more information. %%%% GNU 3DLDF is available for downloading from %%%% http://www.gnu.org/software/3dldf/LDF.html. %%%% Please send bug reports to Laurence.Finston@gmx.de %%%% The mailing list help-3dldf@gnu.org is available for people to %%%% ask other users for help. %%%% The mailing list info-3dldf@gnu.org is for sending %%%% announcements to users. To subscribe to these mailing lists, send an %%%% email with ``subscribe '' as the subject. %%%% The author can be contacted at: %%%% Laurence D. Finston %%%% c/o Free Software Foundation, Inc. %%%% 51 Franklin St, Fifth Floor %%%% Boston, MA 02110-1301 %%%% USA %%%% Laurence.Finston@gmx.de %% Run like this: %% 3dldf sundl_01.ldf %% mpost sundl_01.mp %% tex sundl_01.txt %% dvips -o sundl_01.ps sundl_01.dvi %% All on one line: if false: 3dldf sundl_01.ldf; mpost sundl_01.mp; tex sundl_01.txt; \ dvips -o sundl_01.ps sundl_01.dvi fi; %% View using Ghostview like this: %% gv sundl_01.ps & %% * (1) %% ** (2) Sundial 1 %% *** (3) focus f[]; set f0 with_position (0, 5, -12) with_direction (0, 5, 10) with_distance 10; %% **** (4) Parameters radius := 5; %% Goettingen: latitude: 51 deg 32' N, longitude: 9 deg 56' E latitude := 51.533; %% Goettingen %% **** (4) Declarations and Initializations point p[]; %% Points on the dial point g[]; %% Points on the gnomon circle c[]; %% c0 is the dial point q[]; path m[]; rectangle r[]; transform t[]; bool_point_vector bpv; string s; pen path_pen; path_pen := pencircle scaled (.75mm, .75mm); %% **** (4) set c0 with_diameter (2 * radius) with_point_count 32; r0 := out_rectangle c0; r1 := r0 scaled (1.3, 0, 1.3); t0 := identity rotated (90, 90); c0 *= r0 *= r1 *= t0; %% **** (4) Figure 1 pickup pencircle scaled (.575mm, .575mm); beginfig(1); dotlabel.lrt("$\rm{origin}$", origin); g0 := (3 * radius, 0) rotated (0, 0, -latitude); g1 := (-5 * radius, 0) rotated (0, 0, -latitude); drawdblarrow g0 -- g1; label.bot("$g_0$", g0); label.top("$g_1$", g1); p0 := (0, 0, radius); %% **** (4) Points on top of dial (vertical) for i = 15 step 15 until 180: p[i] := p[i - 15] rotated -15; endfor; for i = 0 step 15 until 180: rotate p[i] (0, 0, -latitude); if false: draw origin -- p[i]; fi; endfor; %% **** (4) Points on bottom of dial (horizontal) for i = -15 step -15 until -165: p[i] := p[i + 15] rotated 15; endfor; for i = -15 step -15 until -165: rotate p[i] (0, 0, -latitude); if false: draw origin -- p[i]; fi; endfor; draw p[75] -- p[-105]; %% **** (4) Rotate dial and surrounding rectangles. t2 := identity rotated (0, 0, -latitude); c0 *= r0 *= r1 *= t2; %% **** (4) Draw and label the rectangles surrounding the dial draw r0 with_color red; draw r1 with_color green; for i = 0 upto 3: q[28 + i] := get_point (i) r0; q[i] := get_point (i) r1; endfor; %% ***** (5) r0 dotlabel.bot("$q_{28}$", q28); dotlabel.ulft("$q_{29}$", q29); dotlabel.top("$q_{30}$", q30); dotlabel.rt("$q_{31}$", q31); label.lrt("$r_0$", mediate(q28, q31, .25)) with_text_color red; %% ***** (5) r1 dotlabel.bot("$q_0$", q0); dotlabel.ulft("$q_1$", q1); dotlabel.top("$q_2$", q2); dotlabel.rt("$q_3$", q3); label.lrt("$r_1$", mediate(q0, q3)) with_text_color green; %% **** (4) Get the rectangle perpendicular to r1, draw and label it (r4) q4 := unit_vector(q3 - q0) * 2 shifted q0 rotated_around(q0, q1) 90; q5 := unit_vector(q3 - q0) * 2 shifted q0 rotated_around(q0, q1) -90; dotlabel.lft("$q_4$", q4); dotlabel.lft("$q_5$", q5); q6 := unit_vector(q2 - q1) * 2 shifted q1 rotated_around(q0, q1) 90; q7 := unit_vector(q2 - q1) * 2 shifted q1 rotated_around(q0, q1) -90; dotlabel.urt("$q_6$", q6); dotlabel.lrt("$q_7$", q7); r4 := (q5, q4, q6, q7); draw r4 with_color cyan; label.llft("$r_4$", mediate(q4, q5, .25)) with_text_color cyan; %% **** (4) Find, draw and label the rectangle representing the vertical plane (r2) q8 := q4 shifted (0, 14); q9 := q6 shifted (0, 14); dotlabel.lft("$q_8$", q8); dotlabel.lft("$q_9$", q9); r2 := (q6, q4, q8, q9); draw r2 with_color red; label.lft("$r_2$", mediate(q4, q8)) with_text_color red; %% **** (4) bpv := r2 intersection_points (g0 -- g1); q10 := bpv0; dotlabel.rt("$q_{10}$", q10); q11 := mediate(q4, q6); dotlabel.llft("$q_{11}$", q11); draw q10 -- q11; q12 := mediate(q5, q7); dotlabel.lrt("$q_{12}$", q12); draw q11 -- q12; q13 := mediate(q0, q1); dotlabel.llft("$q_{13}$", q13); draw p90 -- q13 with_color blue; bpv := (p[-105] -- p75) intersection_points r1; q14 := bpv0; q15 := bpv1; dotlabel.top("$q_{14}$", q14) with_text_color magenta; dotlabel.top("$q_{15}$", q15) with_text_color magenta; draw q14 -- q15 dashed evenly; point n[]; n0 := (get_normal c0 * -1) shifted q14; bpv := (q14 -- n0) intersection_points r2; q16 := bpv0; draw q16 -- q10 dashed evenly; dotlabel.rt("$q_{16}$ $(75^\circ)$", q16); draw q14 -- q16 dashed evenly; t3 := identity rotated_around (q4, q8) 5; q17 := q6; r3 := r2; r3 *= q17 *= t3; dotlabel.llft("$q_{17}$", q17); rotate_around r3 (q4, q17) 5; %% **** (4) Find the points on r3 (the skew plane) for i = 0 upto 3: q[23 + i] := get_point (i) r3; endfor; q27 := mediate(q24, q25); %% Label the points on r3 (the skew plane) dotlabel.ulft("$q_{23}$", q23); dotlabel.rt("$q_{24}$", q24); dotlabel.top("$q_{25}$", q25); dotlabel.top("$q_{26}$", q26); %% **** (4) Label r3 (the skew plane) label.lft("$r_{3}$", q27) with_text_color magenta; draw r3 with_color magenta; bpv := r3 intersection_points (g0 -- g1); q18 := bpv0; dotlabel.rt("$q_{18}$", q18); q19 := mediate(q16, q10); dotlabel.lrt("$q_{19}$", q19); q20 := .5 * q10; dotlabel.rt("$q_{20}$", q20); bpv := r3 intersection_points (q20 -- q19); q21 := bpv0; drawarrow q20 -- q21 dashed evenly; label.llft("$q_{21}$", q21); bpv := r3 intersection_points (q18 -- q21); q22 := bpv0; dotlabel.lft("$q_{22}$", q22); draw q18 -- q22 dashed evenly with_color red; %% **** (4) Find the normal to r3 q32 := get_center r3; s := "\setbox0=\hbox{(center of $r_3$)}\vbox{\hbox to \wd0{\hfil $q_{32}$}\box0}"; dotlabel.lft(s, q32); q33 := get_normal r3 * -6 shifted q32; s := "\setbox0=\hbox{(normal to $r_3$)}\vbox{\hbox to \wd0{$q_{33}$\hfil}\box0}"; drawarrow q32 -- q33 dashed evenly with_color magenta; label.lrt(s, q33); t4 := align (q32 -- q33) with_axis y_axis; %% **** (4) Draw dial draw c0; label.urt("$c_0$", get_point(16) c0 * .875 shifted (.1, 0)); %% **** (4) Draw axes of dial draw p0 -- p180 with_color blue with_pen path_pen; draw p[-90] -- p90 with_color blue with_pen path_pen; %% **** (4) Labels for top of dial. (vertical) if false: dotlabel.lrt("\uppercase\expandafter{\romannumeral 6} $(180^\circ)$", p180); dotlabel.lrt("\uppercase\expandafter{\romannumeral 7} $(165^\circ)$", p165); dotlabel.lrt("\uppercase\expandafter{\romannumeral 8} $(150^\circ)$", p150); dotlabel.llft("\uppercase\expandafter{\romannumeral 9} $(135^\circ)$", p135); dotlabel.lft("\uppercase\expandafter{\romannumeral 10} $(120^\circ)$", p120); dotlabel.lft("\uppercase\expandafter{\romannumeral 11} $(105^\circ)$", p105); fi; dotlabel.lft("\uppercase\expandafter{\romannumeral 12} $(90^\circ)$", p90); dotlabel.lft("$p_{75} =$\uppercase\expandafter{\romannumeral 13} $(75^\circ)$", p75); if false: dotlabel.lft("\uppercase\expandafter{\romannumeral 14} $(60^\circ)$", p60); s := "\setbox0=\hbox{$(45^\circ)$}" & "\vbox{\hbox to \wd0{\hfil\uppercase\expandafter{\romannumeral 15}}" & "\box0}"; dotlabel.lft(s, p45); dotlabel.lft("\uppercase\expandafter{\romannumeral 16} $(30^\circ)$", p30); dotlabel.lft("\uppercase\expandafter{\romannumeral 17} $(15^\circ)$", p15); dotlabel.lft("\uppercase\expandafter{\romannumeral 18} $(0^\circ)$", p0); fi; %% **** (4) Labels for bottom of dial. (horizontal) if false: dotlabel.lrt("\uppercase\expandafter{\romannumeral 7} $(-165^\circ)$", p[-165]); dotlabel.rt("\uppercase\expandafter{\romannumeral 8} $(-150^\circ)$", p[-150]); dotlabel.rt("\uppercase\expandafter{\romannumeral 8} $(-150^\circ)$", p[-150]); dotlabel.rt("\uppercase\expandafter{\romannumeral 9} $(-135^\circ)$", p[-135]); dotlabel.rt("\uppercase\expandafter{\romannumeral 10} $(-120^\circ)$", p[-120]); fi; dotlabel.lrt("\uppercase\expandafter{\romannumeral 11} $(-105^\circ)$", p[-105]); dotlabel.urt("\uppercase\expandafter{\romannumeral 12} $(-90^\circ)$", p[-90]); if false: dotlabel.urt("\uppercase\expandafter{\romannumeral 13} $(-75^\circ)$", p[-75]); dotlabel.ulft("\uppercase\expandafter{\romannumeral 14} $(-60^\circ)$", p[-60]); dotlabel.lft("\uppercase\expandafter{\romannumeral 15} $(-45^\circ)$", p[-45]); dotlabel.lft("\uppercase\expandafter{\romannumeral 16} $(-30^\circ)$", p[-30]); dotlabel.lft("\uppercase\expandafter{\romannumeral 17} $(-15^\circ)$", p[-15]); fi; %% **** (4) End of figure 1 endfig with_focus f0 no_sort; %% *** (3) Figure 2. Parallel projection onto plane of dial. %% Since parallel projection onto an arbitrary plane currently isn't %% all of the objects that need to be displayed are transformed %% appropriately. %% LDF 2007.09.30. beginfig(2); t1 := identity rotated (0, 0, latitude); rotate t1 (180, 180); c0 *= r0 *= r1 *= r2 *= t1; for i = -165 step 15 until 180: p[i] *= t1; draw origin -- p[i]; endfor; for i = 0 upto 16: q[i] *= t1; endfor; dotlabel.top("$q_{14}$ $(75^\circ)$", q14); dotlabel.bot("$q_{15}$", q15); draw c0; draw r0 with_color red; draw r1 with_color green; draw p[-90] -- p90 with_color blue; draw p0 -- p180 with_color blue; draw q14 -- q15 dashed evenly; draw q14 -- q16 dashed evenly; %% **** (4) Labels for top of dial. (vertical) dotlabel.ulft("\uppercase\expandafter{\romannumeral 6} $(180^\circ)$", p180); dotlabel.ulft("\uppercase\expandafter{\romannumeral 7} $(165^\circ)$", p165); dotlabel.ulft("\uppercase\expandafter{\romannumeral 8} $(150^\circ)$", p150); dotlabel.lft("\uppercase\expandafter{\romannumeral 9} $(135^\circ)$", p135); dotlabel.lft("\uppercase\expandafter{\romannumeral 10} $(120^\circ)$", p120); dotlabel.lft("\uppercase\expandafter{\romannumeral 11} $(105^\circ)$", p105); dotlabel.top("\uppercase\expandafter{\romannumeral 12} $(90^\circ)$", p90); dotlabel.rt("\uppercase\expandafter{\romannumeral 13} $(75^\circ)$", p75); dotlabel.rt("\uppercase\expandafter{\romannumeral 14} $(60^\circ)$", p60); s := "\setbox0=\hbox{$(45^\circ)$}" & "\vbox{\hbox to \wd0{\hfil\uppercase\expandafter{\romannumeral 15}}" & "\box0}"; dotlabel.rt(s, p45); dotlabel.rt("\uppercase\expandafter{\romannumeral 16} $(30^\circ)$", p30); dotlabel.rt("\uppercase\expandafter{\romannumeral 17} $(15^\circ)$", p15); dotlabel.rt("\uppercase\expandafter{\romannumeral 18} $(0^\circ)$", p0); %% **** (4) Labels for bottom of dial. (horizontal) dotlabel.llft("\uppercase\expandafter{\romannumeral 7} $(-165^\circ)$", p[-165]); dotlabel.lft("\uppercase\expandafter{\romannumeral 8} $(-150^\circ)$", p[-150]); dotlabel.lft("\uppercase\expandafter{\romannumeral 8} $(-150^\circ)$", p[-150]); dotlabel.lft("\uppercase\expandafter{\romannumeral 9} $(-135^\circ)$", p[-135]); dotlabel.lft("\uppercase\expandafter{\romannumeral 10} $(-120^\circ)$", p[-120]); dotlabel.lft("\uppercase\expandafter{\romannumeral 11} $(-105^\circ)$", p[-105]); dotlabel.bot("\uppercase\expandafter{\romannumeral 12} $(-90^\circ)$", p[-90]); dotlabel.lrt("\uppercase\expandafter{\romannumeral 13} $(-75^\circ)$", p[-75]); dotlabel.urt("\uppercase\expandafter{\romannumeral 14} $(-60^\circ)$", p[-60]); dotlabel.rt("\uppercase\expandafter{\romannumeral 15} $(-45^\circ)$", p[-45]); dotlabel.rt("\uppercase\expandafter{\romannumeral 16} $(-30^\circ)$", p[-30]); dotlabel.rt("\uppercase\expandafter{\romannumeral 17} $(-15^\circ)$", p[-15]); %% **** (4) End of figure 2 endfig with_projection parallel_z_y with_factor 1.25 no_sort; %% *** (3) Figure 3. Parallel projection onto the skew plane r3 beginfig(3); %% **** (4) Transform objects such that r3 comes to lie on the x-z plane. rotate t4 (0, -90); q18 *= q22 *= q23 *= q24 *= q25 *= q26 *= r3 *= t4; %% **** (4) Draw and label r3 and its corner points. draw r3 with_color magenta; dotlabel.urt("$q_{23}$", q23); dotlabel.lrt("$q_{24}$", q24); dotlabel.llft("$q_{25}$", q25); dotlabel.ulft("$q_{26}$", q26); %% **** (4) Label q18, the intersection of the gnomon with r3 and q22, the %% **** (4) intersection of the hour line for 1:00 PM with the bottom edge %% **** (4) of r3. dotlabel.top("$q_{18}$", q18); dotlabel.bot("$q_{22}$", q22); draw q18 -- q22 dashed evenly with_color red; q34 := mediate(q23, q24); endfig with_projection parallel_x_z; % *** (3) End of 3DLDF code. verbatim_metapost "end;"; end; %% ** (2) %% * (1) Emacs-Lisp code for use in indirect buffers when using the %% GNU Emacs editor. The local variable list is not evaluated when an %% indirect buffer is visited, so it's necessary to evaluate the %% following s-expression in order to use the facilities normally %% accessed via the local variables list. %% \initials{LDF 2004.02.12}. %% (progn (metafont-mode) (outline-minor-mode t) (setq fill-column 80)) %% * (1) Local variables for Emacs. %% Local Variables: %% mode:Metafont %% eval:(outline-minor-mode t) %% eval:(read-abbrev-file abbrev-file-name) %% outline-regexp:"%% [*\f]+" %% End: