%%%% sphrmd00.lmc %%%% Created by Laurence D. Finston (LDF) Sun Aug 5 18:53:10 CEST 2012 %%%% $Id: sphrmd00.lmc,v 1.8 2022/12/16 14:05:14 lfinsto1 Exp $ %% * (1) Copyright and License. %%%% This file is part of GNU 3DLDF, a package for three-dimensional drawing. %%%% Copyright (C) 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 %% Created: August 5, 2012 %% Last Updated: August 6, 2012 %% *** (1) Macros %% *** (3) Macros %% ** (2) crosshair %% Non-typed arguments: %% vv: picture %% ctr: >= 0: subscript for vv, < 0: vv is not an array. %% %% LDF 2012.06.05. macro crosshair; def crosshair (V) {point aa, numeric offset, point bb, point cc} = pen thin_pen; thin_pen := pencircle scaled (.25mm, .25mm, .25mm); transform tt; point A[]; A0 := aa shifted (0, 0, 1); A1 := (offset * unit_vector(cc - bb)) shifted by aa; A2 := A1 rotated_around (aa, A0) 90; A3 := A1 rotated_around (aa, A0) 180; A4 := A1 rotated_around (aa, A0) 270; if is_picture V: draw A1 -- A3 with_pen pencircle scaled (.25mm, .25mm, .25mm) with_pen thin_pen on_picture V; draw A2 -- A4 with_pen pencircle scaled (.25mm, .25mm, .25mm) with_pen thin_pen on_picture V; else: draw A1 -- A3 with_pen pencircle scaled (.25mm, .25mm, .25mm) with_pen thin_pen; draw A2 -- A4 with_pen pencircle scaled (.25mm, .25mm, .25mm) with_pen thin_pen; fi; enddef; macro old_crosshair; def old_crosshair {point aa, numeric offset} = draw aa -- (aa shifted (offset, 0)) with_pen pencircle scaled (.25mm, .25mm, .25mm); draw aa -- (aa shifted (-offset, 0)) with_pen pencircle scaled (.25mm, .25mm, .25mm); draw aa -- (aa shifted (0, offset)) with_pen pencircle scaled (.25mm, .25mm, .25mm); draw aa -- (aa shifted (0, -offset)) with_pen pencircle scaled (.25mm, .25mm, .25mm); enddef; %% Use negative length for tick mark on the left of aa, positive for one on the right. %% LDF 2010.06.02. def tick {point aa, numeric offset} = draw aa -- (aa shifted (offset, 0)) with_pen pencircle scaled (.25mm, .25mm, .25mm); enddef; %% ** (2) tab macro tab; % t: path (rectangle, circle, etc.) % VV: picture or ZERO % H_OFFSET: numeric variable % HEIGHT: numeric variable % j, k: Points on path % n: amount of mediation used to get offset from the points on the path % r: amount of mediation used to get offset % from the points on the path for the shorter edge. % u: Height of the tab (multiplied by a unit_vector derived from mag) % crosshair_ctr: Number of crosshairs. % mag : magnitude (1 or -1) def tab (t, VV, H_OFFSET, HEIGHT) {numeric j, numeric k, numeric n, numeric r, numeric u, numeric crosshair_ctr, numeric mag} := %% *** (3) % message "In tab:"; % if is_picture VV: % message "VV is a picture."; % else: % message "VV is not a picture."; % fi; boolean do_labels; do_labels := false; % true picture W; point P[]; pen thin_pen; thin_pen := pencircle scaled (.25mm, .25mm, .25mm); P21 := get_point (j) t; P22 := get_point (k) t; P0 := mediate(get_point (j) t, get_point (k) t, n); P1 := mediate(get_point (k) t, get_point (j) t, n); H_OFFSET := magnitude (P21 - P22) - magnitude (P0 - P1); P3 := mediate(P0, P1); P12 := P3 shifted (0, 0, 1); P13 := (unit_vector(P1 - P0) shifted P3) rotated_around (P3, P12) -90; P14 := (unit_vector(P1 - P0) shifted P3) rotated_around (P3, P12) 90; if mag > 0: P2 := P13; else: P2 := P14; fi; P4 := u * unit_vector(P2 - P3); shift P4 by P3; HEIGHT := magnitude (P4 - P3); P5 := mediate(get_point (j) t, get_point (k) t, r) shifted by (P4 - P3); P6 := mediate(get_point (k) t, get_point (j) t, r) shifted by (P4 - P3); %draw P0 -- P1 with_pen pencircle scaled (.5mm, .5mm, .5mm) with_color red on_picture W; P7 := mediate(P3, P4); P9 := (P7 - P3) shifted P0; P15 := mediate (P0, P5, 5); P16 := mediate (P5, P0, 5); P17 := mediate (P7, P9, 5); P18 := mediate (P9, P7, 5); %% LDF 2012.06.05. Intersection_point fails here, if drawn in x-z plane. %% There's a note in the definition of Point::intersection_point (or possibly %% Point::intersection_points). P10 := (P15 -- P16) intersection_point (P17 -- P18); P19 := mediate (P1, P6, 5); P20 := mediate (P6, P1, 5); P11 := (P18 -- P17) intersection_point (P19 -- P20); draw P0 -- P5 -- P6 -- P1 -- cycle with_color dark_gray with_pen thin_pen on_picture W; draw P10 -- P11 with_color dark_gray with_pen thin_pen on_picture W; draw P3 -- P4 with_color dark_gray with_pen thin_pen on_picture W; %draw P15 -- P16 withcolor red on_picture W; %draw P17 -- P18 withcolor blue on_picture W; %% *** (3) if crosshair_ctr > 0: for i = 1 upto crosshair_ctr: crosshair (W) {mediate(P10, P11, i/(crosshair_ctr + 1)), .1cm, P10, P11}; endfor; fi; % message "unit_vector(P10 - P11):"; % show unit_vector(P10 - P11); % message "unit_vector(P0 - P1):"; % show unit_vector(P0 - P1); pickup pencircle scaled (.25mm, .25mm, .25mm); if do_labels: %dotlabel.rt("$P_0$", P0) W; %dotlabel.llft("$P_1$", P1) W; %dotlabel.top("$P_2$", P2) W; dotlabel.bot("$P_3$", P3) W; dotlabel.top("$P_4$", P4) W; %dotlabel.urt("$P_5$", P5) W; %dotlabel.ulft("$P_6$", P6) W; % dotlabel.rt("$P_7$", P7) W; % dotlabel.top("$P_9$", P9) W; % dotlabel.top("$P_{10}$", P10) W; % dotlabel.top("$P_{11}$", P11) W; % dotlabel.top("$P_{15}$", P15) W; % dotlabel.top("$P_{16}$", P16) W; % dotlabel.top("$P_{17}$", P17) W; % dotlabel.top("$P_{18}$", P18) W; % dotlabel.top("$P_{19}$", P19) W; % dotlabel.top("$P_{20}$", P20) W; % dotlabel.bot("$P_{11}$", P11) W; fi; if is_picture VV: temp_ctr := 0; %% BUG! If this command is removed, a syntax error occurs. %% I don't know why. !! TODO: Do something about this. %% LDF 2012.06.17. VV += W; else: current_picture += W; fi; %% *** (3) enddef; %% ** (2) macro pyramid %% LOG %% LDF 2012.08.06. %% Added this macro definition. I've copied it from `bldelem3.lmc'. %% ENDLOG macro pyramid; def pyramid (U, V, W, ttext_picture, ddbl_tab_picture, ddiameter_two, T, rr) {numeric ssides, numeric ddiameter, numeric hheight_a, numeric hheight_b, numeric hheight_c, numeric ccross_a, numeric ccross_b, boolean do_guidelines, boolean do_labels} = string s; reg_polygon r[]; point p[]; p0 := (0, hheight_a); pen normal_pen; normal_pen := pencircle scaled (.5mm, .5mm, .5mm); set r0 with_sides ssides with_diameter ddiameter; draw r0 on_picture U with_pen normal_pen; % message "size r0:"; % show size r0; for i = 1 upto ssides: p[i] := get_point (i - 1) r0; draw p[i] -- p0 on_picture U with_pen normal_pen; endfor; % message "magnitude (p1 - p2):"; % show magnitude (p1 - p2); point S[]; S0 := mediate(p1, p2); numeric curr_mag; curr_mag := magnitude (p0 - S0); % message "curr_mag:"; % show curr_mag; S1 := S0 shifted (0, 1); S2 := p1 rotated_around (S0, S1) 90; S3 := (curr_mag * unit_vector (S2 - S0)) shifted by S0; triangle t[]; set t0 with_points (p1, S3, p2); numeric rot_val; rot_val := 360 / ssides; if do_labels: dotlabel.top("$p_0$", p0) U; dotlabel.bot("$p_1$", p1) U; dotlabel.bot("$p_2$", p2) U; dotlabel.bot("$p_3$", p3) U; dotlabel.bot("$p_4$", p4) U; dotlabel.bot("$p_5$", p5) U; dotlabel.bot("$s_0$", S0) U; dotlabel.bot("$s_2$", S2) U; dotlabel.bot("$s_3$", S3) U; fi; %% **** (4) %% **** (4) rotate t[0] (90, 0); path temp_path; path save_path; numeric h_offset; numeric tab_height; numeric temp_mag; path Q[]; if (hheight_b <= 0) or (hheight_b >= hheight_a): message "hheight_b <= 0 or hheight_b >= hheight_a. Not truncating pyramid."; draw t0 rotated (-90, 0) on_picture U with_pen normal_pen; draw t0 on_picture V with_pen normal_pen; draw t0 on_picture W with_pen normal_pen; temp_path := get_point 0 t0 -- get_point 1 t0; tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; temp_mag := magnitude (get_point 0 t0 - get_point 1 t0); temp_path := origin -- (temp_mag, 0); save_path := temp_path; for i = 1 upto ssides: tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; shift temp_path ((temp_mag - h_offset + .5cm), 0); tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; shift temp_path ((temp_mag - h_offset + .5cm), 0); tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; shift save_path (0, -(2tab_height + .25cm)); temp_path := save_path; endfor; temp_path := get_point 2 t0 -- get_point 1 t0; tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; if do_labels: for i = 0 upto 2: s := "$0_" & decimal (i) & "$"; dotlabel.top(s, get_point (i) t0) V; endfor; fi; for i = 1 upto ssides - 1: t[i] := t0 rotated (0, 0, i * rot_val); draw t[i] rotated (-90, 0) on_picture U with_pen normal_pen; draw t[i] on_picture V with_pen normal_pen; draw t[i] on_picture W with_pen normal_pen; temp_path := get_point 0 t[i] -- get_point 1 t[i]; tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; temp_path := get_point 2 t[i] -- get_point 1 t[i]; tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; endfor; if (is_triangle T): T := t0; fi; else: message "hheight_b > 0 and hheight_b < hheight_a. Truncating pyramid."; S4 := (0, hheight_b); % message "S4:"; % show S4; curr_mag := magnitude (S4 - S0); % message "curr_mag:"; % show curr_mag; S5 := (curr_mag * unit_vector (S2 - S0)) shifted by S0; rotate S5 (90, 0); rotate S0 (90, 0); S6 := S5 shifted (0, 0, 1); S7 := S0 rotated_around (S5, S6) 90; S8 := (get_point 0 t0 -- get_point 1 t0) intersection_point (S5 -- S7); S9 := (get_point 1 t0 -- get_point 2 t0) intersection_point (S5 -- S7); S10 := get_point 0 t0; S11 := get_point 2 t0; temp_path := S10 -- S8; tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; temp_path := S9 -- S11; tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; drawdot S10 with_pen pencircle scaled (1mm, 1mm, 1mm) on_picture V; Q0 := get_point 0 t0 -- S8 -- S9 -- get_point 2 t0 -- cycle; % draw t0 on_picture V with_pen normal_pen with_color blue; % draw t0 on_picture W with_pen normal_pen with_color blue; draw Q0 rotated (-90, 0) on_picture U; draw Q0 on_picture V; draw Q0 on_picture W; curr_mag := magnitude (S8 - S9) / magnitude (get_point 0 t0 - get_point 2 t0); r1 := r0 scaled (curr_mag, 0, curr_mag) rotated (90, 0, 180); shift r1 by (S8 - get_point 1 r1); ddiameter_two := 2 * magnitude (get_center r1 - get_point 1 r1); if do_labels: dotlabel.top("$S_5$", S5) U; dotlabel.top("$S_5$", S5) V; dotlabel.top("$S_0$", S0) V; dotlabel.top("$S_7$", S7) V; dotlabel.rt("$S_8$", S8) V; dotlabel.llft("$S_9$", S9) V; label("$S_{10}$", S10 shifted (0, .333cm)) V; dotlabel.ulft("$S_{11}$", S11) V; fi; if false: % do_labels for i = 0 upto ssides - 1: s := "$" & decimal (i) & "$"; dotlabel.top(s, get_point (i) r1) V; endfor; fi; if (is_reg_polygon rr): rr := r1; fi; if hheight_c <= 0: draw r1 rotated (-90, 0) on_picture U; draw r1 on_picture V; draw r1 on_picture W; % else: % draw r1 rotated (-90, 0) with_color dark_gray dashed evenly on_picture U; % draw r1 with_color dark_gray dashed evenly on_picture V; fi; S12 := get_center r1; S13 := S12 shifted (0, 0, 1); for i = 1 upto ssides - 1: t[i] := t0 rotated (0, 0, i * rot_val); Q[i] := Q0 rotated (0, 0, i * rot_val); % draw t[i] rotated (-90, 0) on_picture U with_pen normal_pen with_color blue; % draw t[i] on_picture V with_pen normal_pen with_color blue; % draw t[i] on_picture W with_pen normal_pen with_color blue; draw Q[i] rotated (-90, 0) on_picture U with_pen normal_pen; draw Q[i] on_picture V with_pen normal_pen; draw Q[i] on_picture W with_pen normal_pen; if hheight_c <= 0: temp_path := (S8 -- S9) rotated_around (S12, S13) (i * rot_val); tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, -1}; temp_path := (S8 -- S9) rotated (0, 0, i * rot_val); tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, 1}; fi; temp_path := (S10 -- S8) rotated (0, 0, i * rot_val); tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; temp_path := (S9 -- S11) rotated (0, 0, i * rot_val); tab (temp_path, V, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; tab (temp_path, W, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; endfor; temp_mag := magnitude (S8 - S10); temp_path := origin -- (temp_mag, 0); save_path := temp_path; label("$A$", origin) ddbl_tab_picture; label.urt("$A$", mediate(S8, S10)) W; for i = 1 upto ssides: tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; shift temp_path ((temp_mag - h_offset + .5cm), 0); tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; shift temp_path ((temp_mag - h_offset + .5cm), 0); tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_a, -1}; shift save_path (0, -(2tab_height + .25cm)); temp_path := save_path; endfor; if hheight_c <= 0: temp_mag := magnitude (S8 - S9); temp_val := -ssides; temp_val *= (2tab_height + .25cm); temp_val -= .25cm; temp_path := (0, temp_val) -- (temp_mag, temp_val); save_path := temp_path; label.lft("$B$", (0, temp_val)) ddbl_tab_picture; label.urt("$B$", mediate(get_point 1 r1, get_point 2 r1)) W; for i = 1 upto ssides: tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, -1}; shift temp_path ((temp_mag - h_offset + .5cm), 0); tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, -1}; shift temp_path ((temp_mag - h_offset + .5cm), 0); tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, 1}; tab (temp_path, ddbl_tab_picture, h_offset, tab_height) {0, 1, .875, .75, .2, ccross_b, -1}; shift save_path (0, -(2tab_height + .25cm)); temp_path := save_path; endfor; fi; %% if hheight_c <= 0: fi; %% Truncating pyramid %% **** (4) s := "\vbox{\halign{#:\quad\hfil&\hfil#\cr " & "Sides&" & decimal ssides & "\cr " & "Base diameter&$" & decimal ddiameter & "\rm{cm}$\cr "; if (hheight_b <= 0) or (hheight_b >= hheight_a): s := s & "Height&$" & decimal hheight_a & "\rm{cm}$"; elseif hheight_c <= 0: s := s & "Height of non-truncated pyramid&$" & decimal hheight_a & "\rm{cm}$\cr " & "Height of truncated pyramid&$" & decimal hheight_b & "\rm{cm}$\cr " & "Diameter of upper polygon&$" & decimal ddiameter_two & "\rm{cm}$"; else: s := s & "Height of lower section&$" & decimal hheight_b & "\rm{cm}$\cr " & "Height of upper section&$" & decimal hheight_c & "\rm{cm}$\cr " & "Diameter of upper polygon&$" & decimal ddiameter_two & "\rm{cm}$"; fi; s := s & "\cr}}"; if is_picture ttext_picture: label(s, origin) ttext_picture; fi; enddef; %% ** (2) %% * (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: