omdl  v0.6.1
OpenSCAD Mechanical Design Library
units_coordinate.scad
Go to the documentation of this file.
1 //! Coordinate systems and conversions.
2 /***************************************************************************//**
3  \file units_coordinate.scad
4  \author Roy Allen Sutton
5  \date 2017
6 
7  \copyright
8 
9  This file is part of [omdl] (https://github.com/royasutton/omdl),
10  an OpenSCAD mechanical design library.
11 
12  The \em omdl is free software; you can redistribute it and/or modify
13  it under the terms of the [GNU Lesser General Public License]
14  (http://www.gnu.org/licenses/lgpl.html) as published by the Free
15  Software Foundation; either version 2.1 of the License, or (at
16  your option) any later version.
17 
18  The \em omdl is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with the \em omdl; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301, USA; or see <http://www.gnu.org/licenses/>.
27 
28  \details
29 
30  \ingroup units units_coordinate
31 *******************************************************************************/
32 
33 include <../constants.scad>;
34 
35 //----------------------------------------------------------------------------//
36 /***************************************************************************//**
37  \addtogroup units
38  @{
39 
40  \defgroup units_coordinate Coordinates
41  \brief Coordinate systems and conversions.
42 
43  \details
44 
45  These functions allow for geometric points in space to be specified
46  using multiple coordinate systems. Some geometric calculations are
47  specified more naturally in one or another coordinate system. These
48  conversion functions allow for the movement between the most
49  convenient for a particular application.
50 
51  For more information see Wikipedia on [coordinate system].
52 
53  The table below enumerates the supported coordinate systems.
54 
55  | system id | description | dimensions | point convention |
56  |:----------:|:--------------:|:-----------:|:-------------------:|
57  | c | [cartesian] | 2d or 3d | [x, y] or [x, y, z] |
58  | p | [polar] | 2d | [r, aa] |
59  | y | [cylindrical] | 3d | [r, aa, z] |
60  | s | [spherical] | 3d | [r, aa, pa] |
61 
62  The symbols used in the convention column are as follows:
63 
64  | symbol | description | units | reference |
65  |:-------:|:------------------------|:-------:|:-------------------:|
66  | x, y, z | coordinate distance | any | xyz-axis |
67  | r | radial distance | any | z-axis / xyz-origin |
68  | aa | [azimuthal] angle | degrees | positive x-axis |
69  | pa | polar / [zenith] angle | degrees | positive z-axis |
70 
71  \note The [azimuthal] angle is a measure of the radial vector orthogonal
72  projection onto the xy-plane measured from the positive x-axis.
73  \note The polar angle is measured from the z-axis ([zenith]) to the
74  radial vector.
75 
76  \b Example
77 
78  \dontinclude units_coordinate_example.scad
79  \skip include
80  \until to="c");
81 
82  \b Result (base_coordinates = \b c): \include units_coordinate_example_c.log
83  \b Result (base_coordinates = \b p): \include units_coordinate_example_p.log
84  \b Result (base_coordinates = \b y): \include units_coordinate_example_y.log
85  \b Result (base_coordinates = \b s): \include units_coordinate_example_s.log
86 
87  [coordinate system]: https://en.wikipedia.org/wiki/Coordinate_system
88  [cartesian]: https://en.wikipedia.org/wiki/Cartesian_coordinate_system
89  [polar]: https://en.wikipedia.org/wiki/Polar_coordinate_system
90  [cylindrical]: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
91  [spherical]: https://en.wikipedia.org/wiki/Spherical_coordinate_system
92  [azimuthal]: https://en.wikipedia.org/wiki/Azimuth
93  [zenith]: https://en.wikipedia.org/wiki/Zenith
94 
95  @{
96 *******************************************************************************/
97 //----------------------------------------------------------------------------//
98 
99 //! <string> The base coordinate system.
101 
102 //! <boolean> When converting to angular measures add 360 to negative angles.
104 
105 //! Return the name of the given coordinate system identifier.
106 /***************************************************************************//**
107  \param s <string> A coordinate system identifier.
108 
109  \returns <string> The system name for the given identifier.
110  Returns \b undef for identifiers that are not defined.
111 *******************************************************************************/
112 function coordinates_name
113 (
114  s = base_coordinates
115 ) = (s == "c") ? "cartesian"
116  : (s == "p") ? "polar"
117  : (s == "y") ? "cylindrical"
118  : (s == "s") ? "spherical"
119  : undef;
120 
121 //! Convert a point from Cartesian to other coordinate systems.
122 /***************************************************************************//**
123  \param c <point> A point to convert.
124  \param to <string> The coordinate system identifier to which the point
125  should be converted.
126 
127  \returns <point> The converted result.
128  Returns \b undef for identifiers that are not defined.
129 
130  \private
131 *******************************************************************************/
132 function coordinate_c_to
133 (
134  c,
135  to
136 ) = (to == "c") ? ( c )
137  : (to == "p") ?
138  (
139  let
140  (
141  r = sqrt(pow(c.x,2) + pow(c.y,2)),
142  aa = atan2(c.y, c.x),
143  aap = ((aa<0) && (coordinates_positive_angles==true)) ? aa+360 : aa
144  )
145  [r, aap]
146  )
147  : (to == "y") ?
148  (
149  let
150  (
151  r = sqrt(pow(c.x,2) + pow(c.y,2)),
152  aa = atan2(c.y, c.x),
153  aap = ((aa<0) && (coordinates_positive_angles==true)) ? aa+360 : aa,
154  z = (c.z !=undef) ? c.z : 0
155  )
156  [r, aap, z]
157  )
158  : (to == "s") ?
159  (
160  let
161  (
162  r = sqrt(pow(c.x,2) + pow(c.y,2) + pow(c.z,2)),
163  aa = atan2(c.y, c.x),
164  aap = ((aa<0) && (coordinates_positive_angles==true)) ? aa+360 : aa,
165  pa = acos(c.z / r)
166  )
167  [r, aap, pa]
168  )
169  : undef;
170 
171 //! Convert a point from some coordinate system to the Cartesian coordinate system.
172 /***************************************************************************//**
173  \param c <point> A point to convert.
174  \param from <string> The coordinate system identifier of the point
175  to be converted.
176 
177  \returns <point> The converted result.
178  Returns \b undef for identifiers that are not defined.
179 
180  \private
181 *******************************************************************************/
182 function coordinate_to_c
183 (
184  c,
185  from
186 ) = (from == "c") ? ( c )
187  : (from == "p") ?
188  (
189  let
190  (
191  x = c[0]*cos(c[1]),
192  y = c[0]*sin(c[1])
193  )
194  [x, y]
195  )
196  : (from == "y") ?
197  (
198  let
199  (
200  x = c[0]*cos(c[1]),
201  y = c[0]*sin(c[1]),
202  z = (c[2] != undef) ? c[2] : 0
203  )
204  [x, y, z]
205  )
206  : (from == "s") ?
207  (
208  let
209  (
210  x = c[0]*sin(c[2])*cos(c[1]),
211  y = c[0]*sin(c[2])*sin(c[1]),
212  z = c[0]*cos(c[2])
213  )
214  [x, y, z]
215  )
216  : undef;
217 
218 //! Convert point from one coordinate system to another.
219 /***************************************************************************//**
220  \param c <point> A point to convert.
221  \param from <string> The coordinate system identifier of the point
222  to be converted.
223  \param to <string> The coordinate system identifier to which the point
224  should be converted.
225 
226  \returns <point> The converted result.
227  Returns \b undef for identifiers that are not defined.
228 *******************************************************************************/
229 function convert_coordinate
230 (
231  c,
232  from = base_coordinates,
233  to = base_coordinates
234 ) = coordinate_c_to( coordinate_to_c( c, from ), to );
235 
236 //! Radially scale a list of 2d cartesian coordinates.
237 /***************************************************************************//**
238  \param c <coords-2d> A list of cartesian coordinates [[x, y], ...].
239  \param r <decimal> A polar radius.
240  \param t <boolean> Translate or scale radius.
241 
242  \returns <coords-2d> A list of scaled cartesian coordinates.
243 
244  \details
245 
246  When \p t is \b true, all coordinates will terminate on a circle of
247  radius \p r. When \p t is \b false, the radius of each coordinate
248  is scaled by \p r.
249 *******************************************************************************/
250 function coordinates_cpc
251 (
252  c,
253  r,
254  t = false
255 ) =
256  [
257  for (i = c)
258  let (p = convert_coordinate(i, from="c", to="p"))
259  convert_coordinate([(t == true) ? r : r*p[0], p[1]], from="p", to="c")
260  ];
261 
262 //! Radially scale and convert a list of 2d polar coordinates to cartesian.
263 /***************************************************************************//**
264  \param c <coords-2d> A list of polar coordinates [[r, aa], ...].
265  \param r <decimal> A polar radius.
266  \param t <boolean> Translate or scale radius.
267 
268  \returns <coords-2d> A list of scaled cartesian coordinates.
269 
270  \details
271 
272  When \p t is \b true, all coordinates will terminate on a circle of
273  radius \p r. When \p t is \b false, the radius of each coordinate
274  is scaled by \p r.
275 *******************************************************************************/
276 function coordinates_pc
277 (
278  p,
279  r,
280  t = false
281 ) =
282  [
283  for (i = p)
284  convert_coordinate([(t == true) ? r : r*i[0], i[1]], from="p", to="c")
285  ];
286 
287 //! Radially scale a list of 3d cartesian coordinates.
288 /***************************************************************************//**
289  \param c <coords-3d> A list of cartesian coordinates [[x, y, z], ...].
290  \param r <decimal> A spherical radius.
291  \param t <boolean> Translate or scale radius.
292 
293  \returns <coords-3d> A list of scaled cartesian coordinates.
294 
295  \details
296 
297  When \p t is \b true, all coordinates will terminate on a sphere of
298  radius \p r. When \p t is \b false, the radius of each coordinate
299  is scaled by \p r.
300 *******************************************************************************/
301 function coordinates_csc
302 (
303  c,
304  r,
305  t = false
306 ) =
307  [
308  for (i = c)
309  let (s = convert_coordinate(i, from="c", to="s"))
310  convert_coordinate([(t == true) ? r : r*s[0], s[1], s[2]], from="s", to="c")
311  ];
312 
313 //! Radially scale and convert a list of 3d spherical coordinates to cartesian.
314 /***************************************************************************//**
315  \param c <coords-3d> A list of spherical coordinates [[r, aa, pa], ...].
316  \param r <decimal> A spherical radius.
317  \param t <boolean> Translate or scale radius.
318 
319  \returns <coords-3d> A list of scaled cartesian coordinates.
320 
321  \details
322 
323  When \p t is \b true, all coordinates will terminate on a sphere of
324  radius \p r. When \p t is \b false, the radius of each coordinate
325  is scaled by \p r.
326 *******************************************************************************/
327 function coordinates_sc
328 (
329  s,
330  r,
331  t = false
332 ) =
333  [
334  for (i = s)
335  convert_coordinate([(t == true) ? r : r*i[0], i[1], i[2]], from="s", to="c")
336  ];
337 
338 //! @}
339 //! @}
340 
341 //----------------------------------------------------------------------------//
342 // openscad-amu auxiliary scripts
343 //----------------------------------------------------------------------------//
344 
345 /*
346 BEGIN_SCOPE example;
347  BEGIN_OPENSCAD;
348  include <units/units_coordinate.scad>;
349 
350  base_coordinates = "c";
351 
352  // get the base coordinate system name
353  cs = coordinates_name();
354 
355  // absolute coordinates in a specified coordinate system.
356  c1 = convert_coordinate([1, 1, 1], "c");
357  c2 = convert_coordinate([1, 180], "p");
358  c3 = convert_coordinate([1, 90, -1], "y");
359  c4 = convert_coordinate([1, 5, 50], "s");
360 
361  // convert between system.
362  c5 = convert_coordinate([10*sqrt(2), 45, 45], from="s", to="y");
363  c6 = convert_coordinate([sqrt(2), 45], from="p", to="c");
364 
365  echo( cs=cs );
366  echo( c1=c1 );
367  echo( c2=c2 );
368  echo( c3=c3 );
369  echo( c4=c4 );
370  echo( c5=c5 );
371  echo( c6=c6 );
372  END_OPENSCAD;
373 
374  BEGIN_MFSCRIPT;
375  include --path "${INCLUDE_PATH}" {config_base,config_csg}.mfs;
376 
377  defines name "system" define "base_coordinates" strings "c p y s";
378  variables add_opts_combine "system";
379 
380  include --path "${INCLUDE_PATH}" script_std.mfs;
381  END_MFSCRIPT;
382 END_SCOPE;
383 */
384 
385 //----------------------------------------------------------------------------//
386 // end of file
387 //----------------------------------------------------------------------------//
coordinates_positive_angles
When converting to angular measures add 360 to negative angles.
function coordinates_pc(p, r, t=false)
Radially scale and convert a list of 2d polar coordinates to cartesian.
function coordinates_csc(c, r, t=false)
Radially scale a list of 3d cartesian coordinates.
function convert_coordinate(c, from=base_coordinates, to=base_coordinates)
Convert point from one coordinate system to another.
function coordinates_name(s=base_coordinates)
Return the name of the given coordinate system identifier.
base_coordinates
The base coordinate system.
function coordinates_cpc(c, r, t=false)
Radially scale a list of 2d cartesian coordinates.
function coordinates_sc(s, r, t=false)
Radially scale and convert a list of 3d spherical coordinates to cartesian.