/*

  <TheGHOUL/ReadMe.txt>

  Hank J. van Leuvensteijn Jr. 2019
  theghoul@hankjr.ca

  This work is licensed under the Unlicense. Do with it as you please, it's not guaranteed to be good for or at anything, actually, it comes with a strict 'Un-Guarantee', declaring it to be fit for nothing at all. Use it at your peril. See License.txt in this directory. Go to <http://unlicense.org/> for more information.

  Since we cannot know all that there is to be known about anything, we ought to know a little about everything.
  [Blaise Pascal]

  Perfection is the enemy of good.
  [Voltaire]

  Or, as I like to put it:

  Finished imperfection beats unfinished perfection.

*/

/*

  This directory contains 'The GHOUL', a.k.a. The Great Helpful OpenSCAD Unified Library.

  It, and it's most excellent documentation live in the wild at this address:

  http://hankjr.ca/theghoul/

*/

/*

  Go to the link below to learn how to install libraries in OpenSCAD:

  https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Libraries

  If you're too lazy to go there, here's a little help if you're running Gnu-Linux:

  The library directory is something like:

  /home/yourusername/.local/share/OpenSCAD/libraries/

  Extract TheGHOUL.zip there, this creates a directory

  /home/yourusername/.local/share/OpenSCAD/libraries/TheGHOUL/

  then put this:

  include<TheGHOUL/Config.scad>

  at the beginning of your somethingorother.scad file and away you go.

*/

/* ================================= IMPORTANT =================================

  All modules and functions are under the './Lib' folder, grouped in folders by similar functionality; let's call them 'families'.

  The './Lib' folder contains OpenSCAD 'family collections', grouped in files, all named 'Lib_SomeFamilyName.scad'. They are files that include<> all modules and functions of a family. The './Lib' folder also contains 'Lib_All.scad' which include<>s all the family collections in './Lib'.

  In turn, './Config.scad' in this directory include<>s './Lib/Lib_All.scad'. './Config.scad' also sets a number of parameters that some of The GHOUL's functions and modules need to work properly, so:

  If you simply include<TheGHOUL/Config.scad>, you have access to all the modules and functions of The GHOUL.

  What, load the WHOLE library? Yes. Why not? Is a little over 500 kB too much for your computation device? Are you running this on a ZX Spectrum?

  If that's too much for you or your system (I guess there's still the odd 286 out there) you can always include<> the separate functions and modules, but you will have to resolve their dependencies manually as well, and then there's the definitions and constants used by The GHOUL, and... It won't be fun. You have been warned.

*/

/* ========================= CONVENTIONS========================================

  Consistency is the mother of clarity, and her, we like a lot. Throughout The GHOUL, the following conventions are adhered to (mostly):


  ## Directions and Angles.

  The following naming convention for angles and directions is (or may be) used in The GHOUL's comments and documentation:


  ### Directions

  |Name                |Meaning                                             |
  |:-------------------|:---------------------------------------------------|
  |East or 3 o'clock:  |Positive X-axis, 0 degrees.                         |
  |North or 12 o'clock:|Positive Y-axis, 90 degrees.                        |
  |West or 9 o'clock:  |Negative X-axis, 180 degrees.                       |
  |South or 6 o'clock: |Negative Y-axis, 270 degrees.                       |
  |Up:                 |Positive Z-axis.                                    |
  |Down:               |Negative Z-axis.                                    |
  |Azimuth:            |Angle in the Z=0 plane, CCW from the positive X-axis|
  |Inclination:        |Angle with the positive Z-axis.                     |
  |Width:              |X-dimension.                                        |
  |Length:             |Y-dimension.                                        |
  |Height:             |Z-dimension.                                        |


  ### Angles

  Angles in the X=0 or 'Y-Z' plane are expressed CCW looking from the positive X side with the positive Z-axis being 0 degrees.

  Angles in the Y=0 or 'X-Z' plane are expressed CCW looking from the positive Y side with the positive Z-axis being 0 degrees.

  Angles in the Z=0 or 'X-Y' plane are expressed CCW looking from the positive Z side with the positive X-axis being 0 degrees.


  ### Object orientation.

  3D Objects with a directional character such as arrows or triangles are created pointing along the positive Z-axis.

  2D shapes with a directional character such as arrows or triangles point along the positive X-axis.


  ## Tuple, vector, array, matrix

  Whether referring to strings, tuples, arrays or matrices; every position reference is 0-indexed.

  Start and end positions are always inclusive.

  Negative position references mean 'drop X positions from the beginning / end', e.g., LeftStr(string, -3) returns the string minus the last 3 characters RightStr(string, -3) returns the string minus the first 3 characters (which is trivial but kept that way for consistency's sake).


  ## Naming.

  ### Variable naming

  Variable names are in CamelCaps.

  ### Function naming

  Function names are in CamelCaps.

  Functions that are defined inside modules or that are only ever called by other functions or modules, have names starting with an underscore:

  _NeverCalledDirectlyByUser()

  ### Module naming

  Module names are in CamelCaps.

  Modules that are defined inside modules or that are only ever called by other functions or modules, have names starting with an underscore.


  ## Structure.

  Formatting convention for nested 'function = boolean ? if_true : if_false'.

    ~~~ openscad
    function SomeFunction(SomeParameter) =
        test 1 --------------------------------------
        ?   if_true 1 test 1-1 ----                 |
            ?   if_true 1-1       | test 1-1 range  | test 1 range
            :   if_false 1-1 ------                 |
        :   if_false 1 test 2 ---------------------------------------------
            ?   if_true 2 test 2-1 ----------------------                 |
                ?   if_true 2-1 test 2-2 --  test       |                 | test
                    ?   if_true 2-2       |  2-2        | test 2-1 range  | 2
                    :   if_false 2-2 ------  range      |                 | range
                :   if_false 2-1 ------------------------                 |
            :   if_false 2 ------------------------------------------------
        test 3 ..... &c.
        |   |   |   |- fourth (third nested) level - test 2-2
        |   |   |----- third (second nested) level - test 2-1
        |   |--------- second (first nested) level - test 1-1 and 2
        |------------- first level - test 1 and 3
    ;
    ~~~


  ## Recursion.

  Recursive functions usually need a counter and a result storage parameter so each call can hand these parameters to their successor.

  Recursive functions often have to initialise parameters depending on the call conditions. In single part recursive functions, much time is wasted by running 'If this is the first call do this' checks, initialisations and error checks on the recursive calls.

    ~~~ openscad
    SingleRecursiveFunction(SomeInput,SomeSettings,Result)=
        Do: trap errors.
        Test: Is this the initial call?
        Then: SingleRecursiveFunction(SomeInput,SomeSettings,Result)
        Else: Is this the last element?
            Then: Result
            Else: is this condition HighOccurence?
                Then: SingleRecursiveFunction(SomeInput,SomeSettings,HighOccurrenceResult)
                Else: SingleRecursiveFunction(SomeInput,SomeSettings,LowOccurenceResult)
    ;
    ~~~

  This can be greatly improved by splitting the 'error trap and initialisor' and the 'recursor' part. The initial call is made to the 'error trap and initialisor' which hands over to the 'recursor' for all recursive calls.

    ~~~ openscad
    RecursiveFirstCall(SomeInput)=
        Do: trap errors.
        Do: RecursiveMain(SomeInput,SomeSettings)
    ;

    RecursiveMain(SomeInput,SomeSettings,Result)=
        Test: Is this the last element?
        Then: Result
        Else: is this condition HighOccurence?
            Then: RecursiveMain(SomeInput,SomeSettings,HighOccurrenceResult)
            Else: RecursiveMain(SomeInput,SomeSettings,LowOccurenceResult)
    ;
    ~~~

  The time ratio between single and split functions can easily be 4:3, just because error checks and initialising only happen once. Will it matter? It does when processing large arrays of vertices &c. To get a real world idea, I clocked a routine checking for identical values in an array. It took 13 seconds for the single version and 10 seconds for the split version on 1e6 operations.

  As an aside; keep your recursive functions _tail_recursive. If that's latin to you, you should learn about that stuff: your CPU will love you for it.

  ## Other oddities

  I usually prefer the original to a copy or derivative, that's why I prefer my English the way the English intended it to be. OpenSCAD was written using the 'Americanised' spelling of the English language. Therefore--with great reluctance--when I refer to a colour, I will use the spelling 'color' to make things a little less confusing for those living between CAN and MEX. The same goes for centre and centred, I will--despite the significant aggravation of my OCD--conform to the OpenSCAD convention and spell them 'center' and 'centered'. There may be other examples, but none come to mind at this moment.


  ## Something about Geany

  I use [Geany](https://www.geany.org/), if you do as well, life gets a WHOLE lot better if you use some of the excellent possibilities to customise Geany for OpenSCAD source-code.

  Add new commands (functions, modules and special variables [$Foo]) to:

  (. is your home directory)

  - .config/geany/tags/scad.scad.tags - for (tag) auto-completion.
  - .config/geany/snippets.conf - for parameter block completion.
  - .config/geany/filedefs/filetypes.OpenSCAD.conf - for highlighting.

  The .config/geany/ directory can be found in your home directory. Files and directories starting with a '.' are normally hidden; type `<CTRL>h` to make them visible in your file organiser [Linux].

  If you're still one of those who use Microsoft or Apple products, I'm afraid I can't be of much help here; maybe you should check [Linux](https://en.wikipedia.org/wiki/Linux) out, it's stable, secure and free, that's why the majority of smart-phones, embedded operating systems, web-servers, universities and governments around the world use it... I bet you won't regret it. I favour [Debian](https://debian.org) but you may prefer one of it's descendants like [Ubuntu](https://ubuntu.com/about); there are a myriad of [flavours](https://en.wikipedia.org/wiki/List_of_Linux_distributions) to choose from.

  >Linux: Without walls or fences, who needs Windows or Gates?

*/
