evolvotron/BUGS0000644000175100017510000000530111267025132013316 0ustar timdaytimdayKnown bugs: - Enlargements seem to need silly amount of memory. Where's it all going ? - Middle mouse drags sometimes don't seem to have any effect other than triggering redisplay. Thought to be fixed by MutatableImage serial numbers (was using pointer value as substitute for object identity before). - Build dependencies don't seem to be very good; crashes and bad linkage can sometimes be cleared by touching files or rebuild from clean. (precompiled headers something to do with this?) We're at the mercy of qmake here really. - Simplifying functions sometimes changes their appearance (implies "is_constant" probably buggy for some functions). Some random testing of functions before and after simplify would help. - When using -spheremap mode, middle mouse-button adjustments don't work as expected (this is because they're not compensated for the projection). Live with it. - Gradient type operators produce a real mess when applied to noise functions. High frequencies in the noise produce big derivatives. Enlarging up to 4096x4096 sometimes looks a bit more sensible. - Have yet to find a tool which can display anything other than the first frame of a Qt-generated MNG format. (Apparently Qt's MNG actually has nothing to do with the multi-frame PNG format). - Very rarely image calculations appear to arrive seriously out-of-order. May be a more of a problem on slower hardware ? If this is causing trouble, try using "-t 1" command-line option to fix it. - Example of "interesting" fullscreen bahaviour (Metacity on RedHat9): Run app fullscreen. Fire off a fullscreen "Big" display. Open the properties dialog for the "big" window. This results in metacity showing the task bar. Use the task bar to select the main app window into the foreground. Watch both fullscreen windows battle for supremacy! This sort of thing is unlikely to be fixed. - Resizing the evolvotron window queues up crazy numbers of tasks. This didn't matter too much in 2D mode, but with animations the memory reserved for each task's render target is considerably larger. - Undo doesn't always work how you'd expect. e.g respawn after undo doesn't respawn from what you'd expect. Undo of a reset or restart doesn't put the mutation parameters & function weightings back how they were. - Moire patterns & undersampling mean small images can show structures not actually present in larger resolution versions. - Once image colours become saturated there's not much which will cause them to scale back down to sensible ranges, unless you're lucky. - Recolour behaves strangely sometimes (?) (e.g spawns all-black images or subtly warped images) Not seen recently; may be fixed. evolvotron/BUILD0000755000175100017510000000010211055517066013421 0ustar timdaytimday#!/bin/sh PATH=$QTDIR/bin:$PATH export PATH ./configure && make evolvotron/LICENSE0000644000175100017510000004313111055517066013652 0ustar timdaytimday GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. evolvotron/NEWS0000644000175100017510000002612012100750300013321 0ustar timdaytimday[Most recent at top] From release 0.6.2: - Version to 0.6.3 - Files derived from USAGE (evolvotron.html and usage_text.h) are now under svn control and no longer need to be generated as part of the build of a fresh checkout. - Migrated to new SourceForge platform. Needed: svn switch --relocate https://evolvotron.svn.sourceforge.net/svnroot/evolvotron "svn+ssh://timday@svn.code.sf.net/p/evolvotron/code/" From release 0.6.1: - Version to 0.6.2 - CHANGES renamed to NEWS - License boilerplate managed using "headache" - Add some "tartan" inspired functions. - Add pixel/voxel/hex grid quantizing functions. - Port command line options to boost::program_options, rationalize commandline options. - Fix to evolvotron_mutate from Pedro Gimeno. - Update mkdeb script to work on squeeze - Functions to be loaded on startup can be specified on the commandline. - Add option to shuffle startup functions. From release 0.6.0: - Version to 0.6.1 - Fix bug in saved functions: quotes missing around version attribute From release 0.5.1: - Version to 0.6.0 - Switch to Qt4. - (Qt4 related) keyboard shortcuts rationalized many removed, ctrl-modifiers dropped - (Qt4 related) image displays now have a frame around them - (Qt4 related) Remove non-standard Qt animated PNG support - evolvotron_match removed - Platform specific code (e.g number of processors identification) isolated in libevolvotron/platform_specific.[h|cpp] and selected by PLATFORM_LINUX or PLATFORM_BSD (Fink Qt's __DARWIN_X11__ also detected and used to select PLATFORM_BSD). - Repository migrated to svn From release 0.5.0: - Version to 0.5.1 - Replace not often used frontside heating/cooling buttons with autocooling mechanism. - Separate tabs for info & license on "About" dialog. - Better formatting of function properties dialog, and also shows XML function tree. - Dialog with rendering controls - Multisampling (antialiasing) options - -a/-j/-s command line options for autocool/jitter/multisample - evolvotron_render adds -j/-s to control jitter & multisampling - Option (-E) of separate thread pool (with different nices: -n/-N) for enlargements. Task totals for each reported separately. - Enlargement and solo renderings are fragmented into multiple smaller jobs to better utilize multiprocessor systems. - Generally better use of ref-counted QImage and QPixmap. - Middle-mouse drag adjustments flicker less. From release 0.4.0: - Version to 0.5.0 - Lists of functions in alphabetic order. - New FunctionTop always at top level. - New functions: Frieze groups. - Constantness of functions more conservative (less overrides) and hopefully less buggy. - Final colour space transform range more constrained to keep colours sane. - More sensible mutation of top level spatial transform (less arbitrary shearing). - Note that above changes mean old saved functions will appear different. - New mutation parameter: probability of a function's parameters being reset. - Code clean up: - More std::auto_ptr, boost::shared_ptr, boost::ptr_vector. Code is now delete free. - Get rid of hacked static function registration; uses auto-generated register_all_functions. - Compute threads use QWaitCondition, not polling. - Default number of threads is number of processors. - Compute threads run at lower priority. - -n command line option to control compute thread priority. (NB assumes Linux NPTL's non-Posix compliant behaviour of threads NOT sharing a common nice value; see "man pthreads" on Linux.) - About dialog displays number of threads. - Use precompiled headers (build time 2m45s down to 1m45s). - code_review script - Set an icon on various dialogs and main frame. - Add -D (function debug) massively weighting in favour of FunctionNoiseOneChannel. Useful with -x/-X. - Believed to fix Debian bug #436231 and gentoo #144160 - MutatableImage has serial number (fix problems caused by pointer value being wrongly used as equivalent) From release 0.3.1: - Version to 0.4.0 - Lock state moved to mutatable image so is stored in undo history - Mandelbrot & Julia set only in x,y plane. Julia set uses fixed parameters. - Add Juliabrot. - Fix "Randomize" button on "All" functions tab. - "Favourite" function dialog provides access to -x/-X command-line functionality - Undo after reset works better - Fix broken FunctionGradient. Replace with GradientOfMagnitude, DivergenceOfMagnitude, Divergence, Curl - Migrate float->double via typedef real - Always builds with fullscreen option. From release 0.3.0: - Version to 0.3.1 - Fix for gcc 3.4 - ./configure made (slightly) more robust From release 0.2.3: - Version to 0.3.0 - Get rid of troublesome system call to ../VERSION in common.pro and pass settings from configure script instead - Add not-very-useful .qt-mng image file output format - Add function stats to Properties dialog - Add function simplification (more useful for debugging than anything) - Don't use True and False in doc-building python script (seems to be quite new thing, not in 2.1.x ?). Use 0 and 1 instead. - Internal changes - Add pkg/debian .deb builder script (still under development) - Fix buggy Y rotation matrix - Eliminate template-tastic Tuple and Matrix classes. Fix XYZ and Transform to not require them. - evolvotron_mutate - -g option more likely to generate insteresting functions - -linz and -spheremap options where appropriate - evolvotron_match utility. - New dialog for function weightings (not fully implemented) From release 0.2.2: - Version to 0.2.3 - Break out USAGE file from README - Add text_to_markup.py script to prettify USAGE file, used from configure - Add quick reference and user manual accessible from help menu From release 0.2.1: - Version to 0.2.2 - CPU type an option to ./configure (p3,p4,xp supported) - Build option for fullscreen & menu-hiding modes (from keyboard or command-line) - Fullscreen mode for "Big" image displays - Change default grid to 6x5 (would sooner have fat than thin images) From release 0.2.0: - Bump version to 0.2.1 - Display (not compute) priority to higher resolution images (saves time enlarging low res images unnecessarily) - Blank images on replacement (above change makes this more necessary) - Round-robin dispatch of done tasks to displays means redisplay more balanced. - -x and -X command line options to specify specifc top level function types. - FunctionKaleidoscope*, FunctionWindmill*, FunctionSeparateZ added. - More iterative functions also added: FunctionStreak Function*Ring - Added -f option to evolvotron_render - Internals: function framework changed (avoids FunctionNodeUsing::evaluate wrapper), speed improvement ? - Internals: Type of top-level node can mutate, MutatableImage more sane. - "Undo" keyboard accelerator works - Per-image display "Properties" dialog added (placeholder) From release 0.1.4: - Bump version to 0.2.0 - Filenames converted to/from QString using Qt's "local8Bit" codec. - -f option specifies number of frames (default 1, which is the non-animated behaviour of previous versions) - -r option specifies framerate of full-resolution animation (default 8, about the minimum to look smooth) - Animations save to multiple files From release 0.1.3: - Bump version to 0.1.4 - Function tree growth rate restored to pre-0.1.2 rates - Both multiscale noise types counted as iterative as originally intended. - "Substitute" mutation type added. From release 0.1.2: - Bump version to 0.1.3 - Build lib and separate executables. Use qmake "subdirs" at top level, move code into subdirs. - Add evolvotron_render executable. - Add evolvotron_mutate executable. - Better Args class. - Fix bug in FunctionAverageSamples - Add noise class - Add more functions. - Use better random number generator (MT) - Changes to initial setup probabilities, add chance of identity nodes front and back From release 0.1.1: - Bump version to 0.1.2. This is purely a bug-fix release. - Gentoo compile bug fix (Karl Robillard) - Disable implicit QString conversion (use explicit latin1() method). - Workround "C++ static initializer fiasco" by moving problem static members into instance-get methods. From release 0.1.0: - Bump version to 0.1.1 - Grid size now defaults to 7x5 - More functions! From release 0.0.5: - Bump version to 0.1.0 - Fix nasty bug in computers where a task could be delivered and deleted while the compute thread was still setting state in it (timing related so it never happened with ccmalloc and valgrind). - Massive internal changes necessary for file save/load (also makes adding functions easier) - Save/load individual functions to XML - configure checks QTDIR defined (biggest cause of build problems) From release 0.0.4 - Bump version to 0.0.5 - configure script #!/bin/* changed to sh from csh - Release tar files now unpack to a ./evolvotron directory - More "Big" size options - Big image can create big images - Big image's initial window size decided by Qt - Spawn warped offers more specific controls (zoom/pan/rotate) - Middle mouse button does stuff (pan/zoom/rotate/shear) - Undo menu entry describes type of action which will be undone - Closing a big image cleans up undo history appropriately - Bug with assumed EvolotronMain/MutableImageDisplay destructor order fixed. From release 0.0.3: - Bump version to 0.0.4 - More interesting start up functions - More functions (e.g rotation and spirals, geometric inverse, iterated fns, fractals...) - Controls to enable/disable expensive/ugly iterative and fractal functions (default off). - Fix dumb bug in xy range of image (makes everything generally behave a lot better; most noticeable with warp) - "Identity supression" control which helps eliminate/reduces obvious origin centering. - "Proportion constant" control (doesn't seem to have that much effect). - Separate reset/restart functionality (reset also resets mutation parameters). - Move Cool/Shield buttons to be adjacent (commonly used together). - "is_constant" query method used to eliminate boring constant images. - x&y co-ordinate alignment fixed (not something users would notice) - Spawn warped made less messy: just generates translate/scale/rotate... no shearing. - Reset clears locks / restart doesn't - Gratuitously templatized tuple/matrix class added to help geometric transforms. - Add "configure" script 'cos thats how lots of other apps do it. Apparently. From release 0.0.2: - Bump version to 0.0.3 - Add command line arg control of grid size and threads, don't override -geometry - GUI control of mutation parameters - "Respawn" regenerates a single display area using spawn/recolour/warp as appropriate. - "Cancel" in file save dialog obeyed. - "Insert" mutation type. - "Undo" functionality. From release 0.0.1: - Bump version to 0.0.2 - Switch to QMainWindow base in anticipation of toolbar. - Save as PPM or PNG - Scrollable fixed-size image "Big" windows. - Improvements to app response under load. From release 0.0.0: - Bump version to 0.0.1 - Add volatile to inter-thread communication flags - Added a few more image node function types - Add "spawn_recoloured" - Add "spawn_warped" evolvotron/README0000644000175100017510000002371112100750252013513 0ustar timdaytimdayNOTE ==== There is a ./configure script here, but it's NOT autoconf generated. evolvotron is built using the qmake utility which is part of Qt. However, most users should be able to ./configure ; make PROVIDED their environment is set up correctly. Page down to the BUILDING section for more info. INTRODUCTION ============ Evolvotron is interactive "generative art" software to evolve images/textures/patterns through an iterative process of random mutation and user-selection driven evolution. If you like lava-lamps, and still think the Mandelbrot set is cool, this could be the software for you. It uses C++ (and STL+Boost) & Qt (which is Trolltech's Qt GUI toolkit; it's ABSOLUTELY NOTHING TO DO WITH APPLE'S QUICKTIME!). It's multithreaded (using Qt's threading API). Home page: http://www.bottlenose.demon.co.uk/share/evolvotron Author: timday at timday dot com This file describes how to build evolvotron. See the USAGE file for details of what the built executable can do. If you manage to make practical use of evolvotron, especially if evolvotron derived imagery makes it into print or other mass media, I'd love to hear about it: please email! Have fun Tim LICENSE ======= This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. [The license should be in the LICENSE file in the same directory as this README] BUILDING ======== There's no reason it shouldn't work on any platform with a correctly set up qmake. [A simple python script is now also used to build the online documentation; I'm hoping this won't cause any problems] You do NOT need to be root (there is no install stage). In the top level directory, you can either do ./configure make or just have both done for you by doing ./BUILD [Note that the BUILD script also adds $QTDIR/bin to the path while it runs the commands, and is probably the easiest way to build if your PATH doesn't include a directory containing qmake and you like it that way.] Make will recurse into and build the libfunction & libevolvotron directories (which is 99% of the work) and some additional subdirectories with executables. Among other things, this will give you an "evolvotron" executable which you can run immediately with ./evolvotron/evolvotron and/or copy where you like (there are no shared libs or "resource files" needing additional attention). See the USAGE file (or in-app manual) for instructions. BUILD PROBLEMS ============== Short story ----------- 1. Check you have your QTDIR environment variable defined correctly. 2. Check your PATH will find qmake (i.e do "which qmake") (adding $QTDIR/bin to your path will fix this on many distros; note that the BUILD script does this when it runs). 3. If your system appears to have some qt libraries, but not qmake, you probably need to install a Qt development tools package of some sort before you can build evolvotron. The 0.6.0 code builds against Boost 1.35 Non-linux platform issues ------------------------- On the whole, Qt does an excellent job of insulating code from platform specific details. However, there is a little bit of linux-specific code in evolvotron. If you don't have a PLATFORM_... define set, you'll get some warnings about no default implementations of functions in platform_specific.cpp, but should still get a working evolvotron (although missing some functionality with regard to automatically choosing how many threads to run and controlling thread priority). All the platform specific code should live in libevolvtron/platform_specific.cpp and is selected by compile options -DPLATFORM_LINUX or -DPLATFORM_BSD (with more potentially addable for other platforms). Setting the appropriate build options is most easily set by editing an appropriate DEFINES+=PLATFORM_LINUX or DEFINES+=PLATFORM_BSD near the top of the common.pro file. Qt doesn't make a fine enough distinction between unix platforms to decide completely automatically, and the situation is further complicated by e.g Fink's Qt not considering itself to be a Qt 'macx' build. Long story ---------- [These days the author primarily develops on Debian stable or testing. The comments below re RedHat are based on experience with the now very old RH 8 & 9; they may or may not be applicable to Fedora.] QTDIR should point to your Qt installation. Your Qt installation should be a directory somewhere (it might be /usr/share/qt3, it might be /usr/lib/qt3-gcc3.2, who knows), containing some or all of the subdirectories bin, doc, etc, include, lib, mkspecs, plugins. NB you might have more than one qt installation (e.g on Debian testing there is/was both /usr/share/qt and /usr/share/qt3). You probably want qt3 if there's a choice. I've never tried Qt4. RedHat defines QTDIR for the normal user environment, Debian needs QTDIR setting explicitly. Additionally QMAKESPEC might possibly need setting (only a Mandrake user has reported having to do this explicitly so far). It will be something like "linux-g++" if you need to set it. Check the Qt docs for other architectures or perhaps look in your QT installation's mkspecs directory if you think you need this. Many build failures are simply because the necessary Qt build tools aren't in your path: which qmake which moc should both find something. RedHat makes life easy by putting these binaries in /usr/bin, but many distros leave them languishing in $QTDIR/bin, in which case you should either add this to your path or use the BUILD script provided here (which sets it for the commands it runs). If you have gcc/c++ compile problems problems: If you have to change anything, the chances are it should be changed in common.pro. Remember that any Makefiles you can see are generated by qmake from .pro files and therefore hacking on the Makefiles is generally a fruitless exercise. Some source releases have had problems with other versions of gcc than the ones I test on. A COMPLETE record of a failed build would be appreciated (including the initial display of the gcc version). If you can fix it, then patches would be even better! And the hackiest build yet: A Debian (3.0r1) user reported Debian's Qt package not including qmake. (Having since played with Debian myself I now know this is probably because they didn't install the various Qt -dev and/or -dev-tools packages too). They eventually got hold of a qmake from somewhere (builing Qt from source?). Attempting a regular evolvotron build they apparently (unsurprisingly) encountered a header/library version incompatibility (old headers, new library) which was solved by hand editing the qmake-generated Makefile and adding "-I- -I. " in front of the other -I paths. Yuk. BUILDING ON OTHER PLATFORMS =========================== [Very old information now!] Linc Davis reports: "I built it on a Mac with Qt installed via Fink (if you know what that is.) All I had to do is add '$(QTDIR)/include/qt' to the include path and then run make." Paolo Greppi built it on OSX like this: - get qt for osx http://www.trolltech.com/download/qt/mac.html - configure qt with -thread to compile threading support (takes a lot of time) - remember to: sudo ln -sf /usr/local/qt/lib/libqt-mt.3.dylib /usr/lib - and add this to .tcshrc in your home directory: setenv QTDIR /usr/local/qt setenv PATH $QTDIR/bin:$PATH setenv DYLD_LIBRARY_PATH $QTDIR/lib - modify the Makefile in evolvotron adding -lqt-mt at the end of LIBS - cd libevolvotron mv mutatable_image_computer_farm.c mutatable_image_computer_farm.cpp mv mutatable_image_computer_task.c mutatable_image_computer_task.cpp - make ... while compiling, it keeps saying c++: unrecognized option `-pthread' (but this doesn't seem to matter) INSTALL ======= The evolvotron sources don't try to provide an installer. The assumption is that packagers will have a better idea of where files should be copied to on their systems, and the tools to do it. Doing make install will recursively descend into the various build directories, but does nothing in each one. The things you're likely to want to install are (in order of interest): The main executable and man page: ./evolvotron/evolvotron ./man/man1/evolvotron.1 User documentation (standalone version of the builtin manual): USAGE An HTML version of the above: ./evolvotron.html Command-line driven tools and their man pages: ./evolvotron_render/evolvotron_render ./man/man1/evolvotron_render.1 ./evolvotron_mutate/evolvotron_mutate ./man/man1/evolvotron_mutate.1 An unsuccessful experiment: ./evolvotron_match/evolvotron_match There are NO extra supporting files built (e.g shared libraries, config files, "resource" files) which need to be in special places for the software to work. PACKAGING ========= There are a few things which might be useful to packagers: mkdeb - script to build .deb files (using the strangely unpopular "yada", and pbuilder). This is used to build the .debs put up on sourceforge, but the "official" Debian ones (and Ubuntu derivatives) are more conventionally packaged by Gurkan Sengun. Yada is obsoleted as of Debian's "Wheezy" release however. rpm/ - directory for contributed RPM related resources. BUILDING CODE DOCUMENTATION =========================== If you have doxygen (and graphviz too) and want to build the source code documentation, execute ./mkdoc at the top level. The code documentation then appears in ./doc/html/ This hasn't been tested in a long while now, although the doxygen commenting style has been kept up. evolvotron/TODO0000644000175100017510000003603612100750300013321 0ustar timdaytimdayProximity to one end or the other of this list does not necessarily imply it will be done sooner or later than other items! Infrastructure -------------- - Ditch yada; migrate to...? dh? (yada gone in Debian Wheezy and Ubuntu P.) Consequences of Qt4 port ------------------------ mutableimagedisplay actions need attention - hmmm shorcuts would need to be installed for the grid, then dispatched. Margins in display grid - add command line option to control size ? Why was DialogMutatableImageDisplay created with :QDialog(parent,0,TRUE) ? EvolvotronMain destructor called on close ? statusbar needs right justification ? New-style include files; move to common Lots of Qthingy* stuff needn't be declared in headers; clean up Conventional Mode ----------------- - Migrate to a stock threading/thread pool/futures lib. - Just make "fullscreen mode support" be the default (and remove text in USAGE). - Link on webpage to gallery http://gigrafx.110mb.com/evolvotron/index.html - ...also flickr stuff (xargs?) - Mouse manipulations: frame rate should be clamped to allow some time to produce a nice image - At least split out evolvotron_main_history.cpp, even if the class remains nested in .h - Smaller fragments for big enlargements; seeing unused processors. - More feedback on when enlargements are ready for saving (have split tasks count now... need more ? yes) - Triangles quantization mode (c.f hexes, pixels and voxels) - Linear and cubic interpolation for pixel and voxel mode quantizer - Enlargement menu: submenus for square, 4:3, 8:5, 16:9. 16x10. 5:4 SXGA 1024x1024 is a bit of an oddball. And name them, see http://en.wikipedia.org/wiki/Computer_display_standard - Friezegroups: Cut taken out for 0.5.0 release. Want cut and blend for those that support it. Blend should use two functions in some cases. Can't see how to blend cuts; needs something more like old warp approach. - Work out how to add warping/blending to the (frieze) symmetry groups so they dont look so "cut". Hop - Basic, Blend and Cut done. Cut needs attn to fit in with spinhop. Jump - Basic, Blend and Cut done. (Is just Hop with y=0 reflection). Cut needs attn to fit in with spinhop. Sidle - Basic. Can't be blended or cut as there are only reflection lines. (Could be blended, but doesn't hide much). Spinjump - Basic. No blend or cut as there are only reflection lines. (Is just Sidle with y=0 reflection). (Again, could blend but not much point). Spinhop - Basic. Blend done. Cut done. Spinsidle - todo Step - todo - Not entirely convinced by separate thread pool for enlargements. On the other hand, do need some mechanism to progress enlargements while working on main grid. - Add functions for the 17 "wallpaper" symmetry groups. ref: http://www.scienceu.com/geometry/articles/tiling/wallpaper.html Wikipedia http://en.wikipedia.org/wiki/Wallpaper_group is good. Presumably there are 3D versions too. See also http://www.mi.sanu.ac.yu/vismath/ana/ana5.htm - The function properties dialog could construct a QListView instead of just displaying the XML. But then you'd want full editing capabilities too (and why not?) - When mutating parameters, have a chance of a "special" reset to "interesting" values, and maybe even patterns of values. - Debian transitioning Apps to Applications (post Etch) see bug #361418 - GPLv3 ? Don't understand what else needs to be (e.g Qt3 etc) - Maybe icon setting could do with some more attention; probably there are more things which should set it (e.g respawn coloured) and loading could set a flag defering icon setting until that view is ready. - Boost post-1.33 changes usage of ptr_map, apparently. (Waiting for 1.34 to hit Debian Testing). - MutatableImageComputer::push_todo could handle defer a bit better. Actually, complete overhaul of queue/computer kill/defer/abort would be better. Computers should check priority on head of queue periodically and switch if there's something better to work on. - Move InstanceCounted out of useful.h (and #include with it) - Changing lock state triggers a redisplay. Lock state would be better associated with displays than MutatableImages, but the history archive doesn't support anything but changing images; needs additional abstraction of general notion of change of a display's state. Can live with this for now. - Use reStructuredText instead of own python txt->html converter. (Then use fracplanet htm->qml converter). - Mode (genesis mode?) which traverses grid, creating a new image every few seconds. First click stops mode. Useful for getting started. - Transform<->vector should output basis vectors first, translation last. - is_constant not enough to avoid boring images. Need to actually check amount of variation. - Get rid of heat/cool etc buttons cluttering up status bar and just have (new) autocool tick, and reheat button ? - Functions with similar names probably do much the same thing so reduce their weighting to avoid them dominating. - FriezeGroups should add an extra parameter for repeat length rather than using 1 all the time. Likewise for spheres. - Move LoadHandler out of mutatable image. - QFileDialog seems to support previewing; enable it for file contents previewing in file dialog. - Internationalization. Make it as easy as possible for contributors to submit new languages. - Ability to set animation mode from GUI (property of an image function ?) - Ability to set spheremap mode from GUI (property of an image function ?) - Keyboard shortcuts for all of reset/restart/remix - Display mutation parameters permanently on status bar. - Scripts entry on context menu; pipes XML to things in ~/.evolvotron/scripts directory - Make middle-mose-button adjustments work sensibly with -spheremap - Option for save function to also generate thumbnail at the same time ? (Maybe not with previewing) - Look into mime-type registration and auto-thumbnailing in nautilus, KDE etc (pipe through evolvotron_render) - Browse window to show thumbnails for all .xml files in a directory. - DialogFunctions and DialogMutationParameters don't notice when the other dialog modifies MutationParameters. Fortunately this doesn't matter because they (will) control completely disjoint aspects of it. Could do with proper model update propagation/validation if things get any more complex though.. - linz and -spheremap need rationalising before we add more projections - Ability to change linz and spheremap attributes on properties menu. - Supplement spheremaps with... what ? Cubemaps ? Volume output ? - Heat/Cool etc buttons in status bar not very interesting. Replace with autocool controls, or have them actually fire off a respawn from the last spawned image; would get more of an idea of how much effect there is then. - MutationParameters should be held by EvolvotronMain with pointers passed to dialogs. - Different projections for evolvotron_render, maybe main app (e.g spheremaps, cubemaps, volumes). - Display properties dialog should have small copy of image - "Evolvotron corpus"; publish mode & viewer app to see other users' creations How ? Jabber conference! (It's all XML). - Quick 'n easy way of pushing to Flickr ? - Proper dependency and generation by qmake of libevolvotron/usage_text.h - Rationalise configure options: fs/nofs (doc/nodoc?) - -h & --help option. Print version and functions supported. - man pages ? Knock off something simple. - Window ordering (and whether fullscreen) should be an input to compute priority. Need to be able to change priorities once tasks are in queue, and re-order queue. - Give some sort of control over pixel aspect ratio. A nice circular image in a square display on the screen is squished when rendered to a rectangular image. Best solution probably to offer cropped modes e.g "640x480 from 640x640". Alternative solution would be 4:3 mode for the whole app where the evaluation range is changed. Harder to explain though. - [Local] Clean up evolvotron_admin/evolvotron_gallery - Check qmake can be found by configure. Check $(QTDIR)/bin first... RH seem to be unusual in copying it to /usr/bin - evolvotron_render default output (or with filename "-") should be to stdout. (The problem is that Qt's image writing libs only support file output). Could create a /tmp file behind the scenes, or write something simple like PPM. - File save dialogs should remember which directory they were last accessing. (Maybe a Qt problem) - Replace FunctionNode::stub() with FunctionRegistry based code - Create registry of all function node types (done) - Use to bring up a panel for setting relative frequencies (check for exploding branching ratios) - Button to spawn images with a specific type of top level node (would be great for testing) - Allow iterative/allow fractal would then become convenience buttons for quick-setting a whole group of frequencies - Classification scheme for function types (basic, smooth, chooser, complex, expensive). - More types of mutation - Substitute a node for a different type, retaining it's settings (expand/cull as necessary) - Nodes near top level should have more chance of mutation ? - evolvotron_mutate standalone exe should provide more control (heat/cool/irradiate/shield options, recolour/warp options, animation options). - Combining/breeding image pairs. Use drag-and-drop Either: Create a new top level node with 2 or more args and add the parents to it. Create a new random stub and insert the parents at random points. Insert one image at a random point into the other. Concatenate (function compose) the 2 images (probably not v. interesting) Need to prune too to keep size under control. - Get rid of silly xyz and matrix dependence on general tuples and templates. (Can be well optimised, but only with heavyweight compile options.) - Profile & optimise. - Spawn recoloured could be linear, quadratic (or generalised?) versions. - Undo needs to save more state to work properly (e.g state for respawn) Make history know about "MutatableImageHolders" rather than Displays, and have last spawned be held in such an object too. - Have a function type which can suck in random images from directories of images (specified by environmental variable ?) Filename would need to be retained in node and XML for reproducibility. - Optimise drag: just recompute new area (needs image subregions for tasks). - Option (default on) to automatitcally respawn boring constant images as soon as they've been computed to a certain resolution. - Web front end to commandline tools: an evolvotron web-server. - Command line option for border around images... use space to indicate locked status. - Maybe add "view" menu: like warp but just applying to current image (like drag) (would need explicit control over amounts: maybe drag approach better ?). - Last method used should point to an object encapsulating the behaviour (so warp spawn method can encapsulate a transform factory). Needed for breeding behaviour (so can keep 2 last images). - Undo needs to restore _last_spawned too (but do above first and keep hisory of spawn methods). - Command line option to enable/disable fractal and iterative types. - "Unlock all" on edit menu - Reset & Restart: combine and bring up modal "are you sure" dialog box which can also contain check boxes for what to reset: mutation parameters function freqencies (when implemented) locked displays - Quit should bring up "are you sure" dialog. - Option to increase number of iterations of certain types of iterative node in an image (i.e "accuracy") (probably makes sense for Mandelbrot/Julia or a sampling blur where it just increases the detail, but less useful for repeated function mapping). - "Move all locked to start" on edit menu (or move them to a "safe area", or save them in reloadable form). - Save whole grid as a single image (from File menu). - Save whole grid to an XML file. - Context menu option to bring up info about an image (in particular number of nodes and max depth) - Reference counting for images (far too much deepcloning currently; e.g to tasks and history). But if it ain't broken don't fix it. - Use hourglass cursor over displays which haven't got final high resolution yet ? (Really need combined hourglass/pointer cursor but Qt doesn't have one built in). - Computing zero co-ordinate sometimes gives unusual output (black lines across images). Avoid by jittering co-ordinate (would break up jaggies), or just avoid exact zero ? - Why stop at screen resolution ? Antialiasing by supersampling. - Separate tool (?) to evolve images towards a given image. How close would it get and how quickly ? Would the process of getting there be interesting (e.g as an animation) ? - Compute farms on multiple remote machines. - Menu options to add/remove rows/columns from display grid - Autocool of mutation parameters (probably shouldn't be on by default; control from command line). - Heat/cool etc should act in proportion to current values (probably wanted for autocool). - Evolve other things e.g parameters of celluar automata/reaction diffusion equations/iterated function systems. - Rationalise MutatableImageNode::stub so more work is done by Node constructors (just pass in a MutationParameters). - Avoid misleading moire patterns by jittering samples - No low-res images option for when using remotely via X11 over slow link (they take longer to display than compute) (running over compressed ssh helps a lot though). - Evolvotron_mutate should support -x/-X options. - Think of more functions: Blending counterparts for switching/choosing functions. Streaking version of windmill functions. Generalised rotations Square "Bhuddist mandala" versions of kaleidascope Concentric rings Iterative function generating a list of point co-ordinates... then test for blobs or make paths (would be more efficient with a cached/precomputed element to functions). Animation --------- - Could avoid bitBlt when reassembling fragmentary animation renders by fragmenting on frame instead of by screen area. Don't think this is a big enough deal (saves a bit of copying in a little used feature) to be worth bothering with. - More warp types (rotate time into space etc) - More control over animation (frames & framerate) from edit/options menu (or on a display by display basis ? Then "big" images could have more frames and higher framerates) - Ability to degrade temporal resolution with spatial resolution at low-res render levels - Support animation in evolvotron_render - Sync animation to xmms beat somehow ? - Option to sweep z sinusoidally or linearly - Option to bounce or cycle z - Make frames, frame-rate, sine vs. linear, loop vs. bounce properties of the image. Extras ------ - evolvotron_match hasn't been seen to do much but converge towards general overall color of target. Try matching in edge-detected space or something ? Rejected -------- - Add #ifdef INSTANTIATE_FN (or move to .cpp) around evaluate methods implemented in .h ? Only really justifiable for fn .h included in multiple places (not that many of them; NB function registration doesn't see these). Not worth bothering with. evolvotron/USAGE0000644000175100017510000006471512013776726013454 0ustar timdaytimdayEVOLVOTRON USER MANUAL ====================== Evolvotron is interactive "generative art" software to evolve images/textures/patterns through an iterative process of random mutation and user-selection driven evolution. On starting the application, a grid of images is displayed. Resize or maximise the application if you like, but the more pixels have to be calculated, the slower it will be. (For the default 2D image mode, you will need a fast machine or patience. For the optional animation mode, you will need both.) Simply repeat the following until bored: - Click (singleclick) on an image you like to spawn the next generation of its mutant offspring. - Wait until variations on it are regenerated in sufficient detail that you can decide which one you like best again. IMPORTANT: Initially you should select images with some sort of variation. If you select a uniform image, you may get stuck in a degenerate zone with little to mutate and therefore little chance of escape to more interesting images. You can always reset/restart from the "File" menu (the difference is that "reset" also resets the mutation parameters to their default values). Selecting one of the "warp" options from a context menu (right-click on an image) can also help by introducing an additional opportunity for mutation on subsequent spawns. Note that various spirals, grids and tiles, although complex looking, are actually implemented by a single function node and may leave you stuck too. COMMAND LINE OPTIONS ==================== The following are equivalent: - evolvotron --grid 12x8 - evolvotron --grid=12x8 - evolvotron -g 12x8 GENERAL OPTIONS --------------- -a, --autocool Enable autocooling by default, and cause resets of mutation parameters to re-enable autocooling if it was disabled. -F, --fullscreen Start in "fullscreen" mode (NB for Qt on X11 this means a screen-filling borderless/undecorated window is used; it's not simply maximising the window, and it's not the sort of framebuffer hijacking used by SDL games). The Qt documentation claims some window managers may not be entirely cooperative with this (in which case sorry, you're on your own). evolvotron actions which bring up dialog boxes (e.g save) seem to generally behave fairly sensibly but child windows (e.g enlargements or dialogs) can show some "interesting" behaviour. Fullscreen mode can be toggled within the application using "F" key. The "Esc" key will also exit it. -g, --grid x Sets size of the grid of image display cells in the main application area (defaults to 5x6) -h, --help Print summary of command line options and exit. -j, --jitter Enable sample jittering. Samples will be made at a random position within a pixel instead of on a regular grid, providing some antialiasing. -m, --multisample Enables additional antialiasing passes. Specifing 2 or 3 will provide an additional pass with 2x2 or 3x3 samples per pixel. Specifiying 4 (of higher) will provide a 2x2 and a final 4x4 pass. Specifying 1 provides the default behaviour of one sample per pixel. For best rendering quality also specify -j. -M, --menuhide Start with menu and status bar hidden. Nice with --fullscreen. Hiding can be toggled within the application using ctrl-m. The Esc key will also bring them back. -p, --spheremap Images are produced by sampling the underlying 3D function on the latitude-longitude grid of a sphere. The resulting images should be usable as spheremaps/spherical environment maps. Animations vary the radius of the sphere. NB when in spheremap mode, middle mouse button adjustments do not yet behave like you'd expect. -S, --startup Specify a function filename (evolvotron's XML format) to load on startup (or reset). The option can be provided multiple times, and this is also the interpretation of any positional arguments. Startup functions are placed in the grid from left to right, top to bottom. -U, --shuffle Use in conjunction with -S / --startup options, to display the specified functions in random order, both on application startup and on each reset of the application. ANIMATION OPTIONS ----------------- -f, --frames Number of frames in animations (defaults to 1 i.e no animation) -l, --linear Vary z linearly with time rather than sinusoidally. Sinusoidal variation generally looks better when animations are "bounced" forwards and backwards, but this option is useful when generating slices to use as volumetric textures. -s, --fps Rate at which frames are displayed per second (integer). (Defaults to 8). POWER-USER & DEBUG OPTIONS -------------------------- Note that the usual Qt/X11 options (for example, -geometry x option to set on-screen size in pixels) are processed and removed before evolvotron options are checked. -D, --debug Puts the certain aspects of the app into a more debug oriented mode. Currently (ie this may change) it simply changes function weightings so virtually all function nodes are FunctionNoiseOneChannel. By itself this is a pretty pointless thing to do, but in conjunction with the -X options it's useful for examining the behaviour of specific functions. -E, --enlargement-threadpool Use a separate thread pool for computing enlargements. Using this option ensures computation of enlargements continue to make some progress even while the main grid is being actively worked on. However, this will be at the expense of main grid rendering performance. Without this option, enlargements' final high-resolution renderings are invariably lower priority than computation for images in the main grid. See also the -N option to control the priority of threads in this pool. -n, --nice Sets additional niceness (relative to the main application thread) of the compute (rendering) thread(s). It's useful to run compute threads at a slightly lower priority ("nice 4" is the default without this option) than the main (GUI) part of the program (but note that this means other normal/lowish priority tasks running on your machine may slow evolvotron down a bit more than expected). -N, --Nice Sets additional niceness (relative to the main application thread) of the compute thread(s) computing enlargements (default value is 8). Only effective in conjunction with -E option. -t, --threads Sets number of compute threads. If this is not specified, then as many compute threads are created as there are processors on the system (unless this cannot be discovered in which case only a single compute thread is created). Non-linux builds will likely not include code to determine processor count (suitable patches gratefully received). -u, --unwrapped Modifies -F behaviour so that the specified "favourite" function is NOT wrapped by space/colour transforms. NB For functions without leaf nodes or parameters (e.g FunctionSphericalToCartesian) this doesn't leave any scope for variation or future mutation. Function name recognition is case sensitive. Example: $ evolvotron -F FunctionKaleidoscope -u -v, --verbose Verbose mode, writes various things to application stderr. This is primarily intended to assist debugging. This option used to be useful for getting a list of supported function names for use with the -F option, but those can also be inspected via the Settings dialogs. -x, --favourite Force a specific "favourite" function type to be used at the top level of all function trees. The specified function is still wrapped by spatial and colour warping functions which may disguise it considerably. A list of all the function names understood by evolvotron is output during app startup when the -v option is specified. Function name recognition is case sensitive. Example: $ evolvotron -F FunctionSpiralLinear MOUSE CONTROL ============= LEFT-CLICK ---------- A left-click on an image in the main window spawns the mutant offspring of that image to all the other (non-locked) displays in the grid. RIGHT-CLICK CONTEXT MENU ------------------------ Right clicking on an image gets you a few more options: - "Respawn" regenerates just the current image from whatever it was spawned from (and using recolour or warp, if that's what was used to produce it). The main use of this is to make your grid of images look nice for screendumps, by regenerating any which aren't up to scratch. NB May not work as expected after an "undo". - "Spawn" is the same as clicking an image. It generates mutated images to all unlocked images in the grid. - "Recolour" to produce different coloured variants of the selected image - "Warp"'s sub-options produce variants of the image which have been zoomed/rotated/panned. - "Lock" to prevent an image from being overwritten by spawns from other images (select again to toggle). - "Enlarge" to produce a blow-up of the image in a single window. Submenu items select either a freely resizable window or a scrollable view of a fixed size image. If the application is running in fullscreen mode (NB this is NOT the same as a simply "maximised" window) then the enlarged image will also be fullscreen (the "Resizeable" mode is probably what you want in this case as the image will automatically be rendered at the correct resolution). - "Save image" to save the image in a file (.ppm or .png). You generally want to save an enlarged image: if you save a small image from the grid, the size you see on the screen is the size you get in the file. Save isn't allowed until the full resolution image has been generated; if you try to save too early a dialog box will be displayed telling you to try again later. - "Save function" to store the function to an XML file. - "Load function" to load a stored function from an XML file. NB if the file was saved from a different version numbered evolvotron, a warning message will be generated. Save/load of functions is an experimental feature and you should not count on future versions of evolvotron being able to load files saved from old versions, or producing the same image from a loaded function. Attempting to load functions from later versions into earlier versions is even less likely to succeed. - "Simplify" prunes the function tree of redundant branches where possible (the same action can be applied to all images from the main "Edit" menu). This doesn't change the appearance of the image, but may make it recompute faster. - "Properties" brings up a dialog box containing some information about the image (e.g the number of function nodes it contains). MIDDLE MOUSE BUTTON ------------------- [NB This feature will probably only be of practical use to those with high-end machines]. You can use the middle mouse button to drag-adjust individual images. This is useful for "final composition" type tweaks, e.g centering an image's most interesting feature, or just for satisfying your curiosity about what's off the edge of the image. It also works on enlarged images, although it's virtually unusable without a bit of practice on smaller, faster ones (just boldly make the adjustment you want, release the button... and wait). Changes made can be rolled-back on the main Edit/Undo menu item, one drag-action at a time. An unmodified middle-mouse drag pans the image around following the mouse motion. A SHIFT-middle drag zooms the image in and out with scaling proportional to the distance from the centre of the image. Beware of generating huge zooms by clicking too near the centre of the image. An ALT-SHIFT-middle drag is similar but anisotropic: the scaling may be different in X and Y. Warning: this technique is very sensitive and can be quite tricky to use! In particular, if you initially click near the centre axes of the image the zoom factor can be HUGE, so the best way to start using this is to click about halfway on a diagonal between the image centre and a corner and gently move in and out radially. Dragging from one side of the image to the other flips it over (the degenerate case of infinite zoom at the centre is handled cleanly I think). If it all goes horribly wrong, undo and try again. A CTRL-middle drag rotates the image about its centre. A CTRL-ALT-middle drag shears the image (the best way to see what this does is to click in the corner of an image and move the mouse horizontally or vertically). KEYBOARD CONTROL ================ There are some keyboard shortcuts. MAIN WINDOW ----------- - "r"/"t"/"x" perform various starts of reset/restart. - "q" quits the application. - "u" (and also Ctrl-z) does an undo. - "f": full-screen mode (on X11, Qt does this by asking the window manager for a screen-filling undecorated window, and the documentation contains some dire warnings about problems with broken window managers). See also "-F" command line option. Fullscreen mode propagates to enlarged image display windows. NB The application may completely disappear from the screen for a brief interval while switching mode. - "m" : hides status and menu-bar hiding, which can be nice when in full-screen or window-maximised mode. See also "-M" command line option. Also note that while the menu bar is hidden, most of these keyboard shortcuts won't function as they're tied to the menu system. - Esc : exits full-screen and/or menu-hiding mode, putting the application into its normal default state. ENLARGEMENT WINDOWS ------------------- The image display windows created by selecting "Enlarge" from a context menu also have a couple of keyboard operations: - "f" : [NB only available with fullscreen build option] toggles full-screen mode. When returning to normal mode, if the main app window was fullscreen then it will also drop back to normal mode. - Esc : [NB only available with fullscreen build option] completely closes a fullscreen-mode enlargement window. GUI ELEMENTS ============ MAIN MENU BAR ------------- - File menu: Items to restart, reset and quit the application. The difference between restart and reset is that reset sets the mutation parameters back the their default values. The "randomize function weights" version of restart scrambles the relative probability of the various function types (if you think evolvotron just keeps generating the same kinds of images give it a try). The "restart with specifc function" item duplicates the functionality of the "-x" and "-X" command-line options. - Edit menu: "Undo" lets you undo certain actions: e.g spawn, middle-button adjustment, simplification and lock/unlock. There is a large but limited number of levels of undo. "Simplify" is of curiosity value only: it prunes redundant branches from images ("junk DNA"); this may help them recompute faster but at the cost of there being less mutatable material. - Settings menu: "Mutations" brings up a dialog to modify the amount of change spawned images are subject to. (See "advanced usage" below.) "Functions" brings up a dialog to modify the relative probability of functions being used. By default all functions are equally likely except for iterative functions and fractals, which are almost but not completely supressed. But if you think there are too many spirals or grids (or not enough fractals) then this is the place to adjust the frequency with which they appear. If the software was built with the fullscreen option, that can also be controlled from this menu. "Favourite" brings up a dialog which allows you to select a specific function type to always be used as the root node of any new functions. The function can be wrapped by some other random stuff, or unwrapped. See also the -X and -x command line options. - Help menu: Items to bring up documentation, and the usual "About" box (which includes the license). STATUS BAR ---------- An area on the status bar shows how many compute "tasks" are outstanding (or "Ready" when there are none). When two task totals are reported, the first is for the main grid and the second for any enlargements being computed. Each "task" is the recomputation of an image at some resolution. Tasks are prioritised by their number of pixels (small image implies higher priority). This is why, if the main grid is still recomputing, recalculations of enlargements will appear to freeze after they have reached a certain resolution, at least until other lower resolution tasks have completed. The status bar also provides some control over the "autocool" mechanism which reduces mutation strength with time. See the advanced usage section below. TIPS ==== - Don't start a session with any preconceived ideas about the kind of image you want to get out of it. You will be disappointed. - I get the best results when I click the image which most immediately catches my eye as they start appearing. If you stop to think about it too much then things seem to go downhill. - If you seem to be just getting the same old spirals and grids all the time, stop clicking on spirals and grids! (The same goes for random mush). - Don't get too hung up on using the warp and middle-mouse drag adjustments every iteration... use those tools for final polishing of your masterpiece. - You can quickly cycle through a lot of initial images (until you find one with real potential) by bashing on Ctrl-r to repeatedly restart. - To add variety to an image's mutations, nudge it with a small middle-mouse drag. This introduces a top level transform, and therefore more parameters to be varied. - Enlargements take a long time to complete their final high-resolution rendering pass (especially with multisampling enabled). Most convenient practice seems to be to go away and leave them to complete, then come back and save them later. Continuing to click away on the main grid effectively starves them of CPU, unless the -E command-line option is used. ANIMATION ========= As of version 0.2.0 evolvotron contains some experimental support for generation of animations (although so far the results have been pretty disappointing IMHO, but it's still early days). NB THIS IS EVEN MORE COMPUTATIONALLY AND MEMORY INTENSIVE THAN THE STATIC IMAGE MODE. Simply supply a -f command line option and evolvotron will generate animated sequences with the specified number of frames. These will be displayed at the frame rate specified by the optional -s option (default 8). So "evolvotron -s 24" will generate 3 second long animations. Animations reverse direction at each end to avoid a sudden jump. If you save an animation as PPM or PNG, multiple files will be saved with .fnnnnnn (where nnnnnn is the zero-filled frame number) inserted in each filename before the filetype qualifier. For example, if you enter foo.ppm as the filename to save, files foo.f000000.ppm, foo.f000001.ppm... will be saved. If you have the ImageMagick tools you can convert these to an animated GIF playing at approx. 8 frames per second with: $ convert -delay 12 foo.f??????.ppm foo.gif ADVANCED USAGE ============== Evolvotron's idea of an image is a function which converts XYZ co-ordinates to an RGB colour (however we can only display a 2D plane for now so the input Z is fixed to zero, or varied with time when animating). The image functions are constructed from trees of function nodes. (In the mathematical expression 1+(2*x) the "+" and the "*" would be function nodes.) Evolvotron's functions tend to correspond to geometric or colour-space operations or anything else which can be applied to a 3D vector. By mutating the structure of the function tree (adding random branches, for example) and the values of the constant embedded within it, the image can be changed. The mutation parameters are under control from the dialogs accessible via the Settings menu, and the "autocool" mechanism exposed in the status bar also has some influence. There are two kinds of mutation: perturbations to the magnitude of constants, and structural mutations which rearrage the function tree of an image. Four types of structural mutations are currently implemented: - replacement of a function branch by a new random stub (a "Glitch" mutation). - a random shuffle of a node's sub-nodes - insertion of random nodes between a node and it's sub-nodes - the substitution of a node with one of a different type, with sub-nodes unaffected where possible). The probability (per function node) of these mutations is controlled from spinboxes on the "Mutation Parameters" dialog (expressed as chances-in-a-hundred), as is the size of perturbations to constants. It is useful to think of the perturbations to constant parameters as being a thermal effect (hence the "heat" and "cool" buttons), while structural alterations are more drastic and are caused by high energy gamma rays or something (hence "irradiate" and "shield" buttons to adjust the probability of structual mutations). So why would you want to change the mutation parameters from the initial defaults ? Basically, if you're getting too much variation in spawned images (this tends to happen after many generations of images, by which time the function trees have grown quite large and therefore are experiencing a lot of mutations) then cool and/or shield. If all the images look too similar, heat and/or irradiate. The "autocool" mechanism (enabled from the statusbar or mutation parameters dialog) automatically reduces the strength of mutations from the base values with successive generations. The cooling can be cancelled by disabling autocooling or pressing the "Reheat" button to zero the number of generations counted for cooling. The effect of the cooling is a compound halving of the mutation strength after some number of generations (this number is the "half-life" controllable from the mutation parameters dialog). Note that if autocooling is enabled then eventually, after a number of iterations more than many multiples of the half-life has passes, spawned images will differ very little from their parents (hence the need for "reheat"). There is also a dialog accessible from "Functions..." on the "Settings" menu. This allows control over the relative proportions in which functions occur. There is a tab showing the relative weighting of all functions (log-2 scale: each tick halves the probability of the function occurring), and additional tabs for various classifications of function for quicker access. The "Randomize" button on each tab assigns random weightings and helps increase the uniqueness of your session. The "Functions" dialog also has a "Dilution" tab which allows the average function-tree branching ratio to be controlled (by changing the proportion of trivial zero-branch functions added): note that using a high branching ratio results in very complex images which will take a long time to compute, while reducing the ratio results in simple, boring images. 3 types of function node are considered fundamental: constant nodes (which return a constant), identity nodes (which return their position argument) and transform nodes (which transform their positon argument by random parameters). On the "Dilution" tab of the "Functions" dialog there are two slider controls to affect things related to these: - "proportion constant" controls the proportion of diluting fundamental nodes which are constants. Changing this from its default value of 0.5 doesn't actually seem to have much effect. - "proportion transforms" sets the proportion of non-constant nodes diluting which are transforms (as opposed to identity nodes). The main effect of this is that images are less commonly obviously centred on the origin or aligned with the axes. I think this is a good thing, so the value is at 1.0 by default. OTHER EXECUTABLES ================= This release also builds some other command-line driven (non-GUI, non-interactive) utilities. Consult the man pages for full details. evolvotron_render reads a XML function description from its standard input and renders it to the file specified. evolvotron_mutate reads an XML function description from its standard input and outputs a mutated version. A command line option allows the "genesis" situation of creating a random function description with no input. EXAMPLES -------- Evolving and mutating on the command line: $ evolvotron_mutate -g | tee fn.xml | evolvotron_render /tmp/xxx.ppm ; display /tmp/xxx.ppm $ cat fn.xml | evolvotron_mutate | evolvotron_render -j -m 4 /tmp/xxx.ppm ; display /tmp/xxx.ppm Animating a function ani.xml saved from evolvotron in animation mode: $ cat ani.xml | evolvotron_render -f 100 -v -s 256 256 ani.ppm ; animate ani.f??????.ppm FUTURE DEVELOPMENTS =================== Please check the TODO file first before you send me suggestions! Please don't ask me to port evolvotron to proprietary platforms. You are of course Free under the terms of the GPL to do so yourself, but please read http://www.fefe.de/nowindows/ first. THANKS ====== To those who have contributed feedback, suggestions and patches: - Dmitry Kirsanov - Jonathan Melhuish - Karl Robillard - Linc Davis - Paolo Greppi - Marcin Wojtczuk - Michael Sterrett - Massimiliano Guastafierro - Goetz Waschk - Forrest Walter And to the anonymous Linspire reviewer who perhaps came up with the best summary of evolvotron yet: "Fascinating. Utterly pointless, but fascinating." The friezegroups wouldn't have been possible without http://michaelshepperd.tripod.com/resources/groups.html Thanks to www.di.fm, www.somafm.com and Trance4Ever for music to code to. Thanks especially to a SIGGRAPH conference panel many years ago (likely including Karl Sims, the pioneer in this area) who first got me interested in this stuff. WHY ? ===== I have always admired those who have the skill to wield a pen or paintbrush and fill a sheet of paper or a canvas with some striking image from their imagination. Unfortunately I lack the patience to learn such skills, and probably the necessary manual dexterity and imagination too. Evolvotron, and several predecessors developed on and off over a decade since I first came across the idea, are an attempt to compensate for this using the skills I do have i.e some mathematical sensibility and the ability to write working code (well, sometimes). If you like an image it produces, then as far as I'm concerned that's as satisfying a result as if you liked something I'd drawn myself. Tim Day evolvotron/VERSION0000755000175100017510000000041612100750252013703 0ustar timdaytimday#!/bin/bash # Script to echo the current version number. # THIS IS THE ONLY PLACE IN ALL THE EVOLVOTRON SOURCE A HARDWIRED VERSION NUMBER SHOULD APPEAR # NB If you edit this, "make distclean" and then rebuild (./BUILD) as there is no dependency checking echo "0.6.3" evolvotron/configure0000755000175100017510000000164612100750252014545 0ustar timdaytimday#!/bin/bash # QMAKESPEC is possibly also required on some systems # See Qt/qmake docs for your system and Evolvotron README if you have any problems. if [ -z "$QTDIR" ] ; then echo "QTDIR not defined" echo "You almost certainly need QTDIR defined and pointing at your QT installation" echo "If you know different, edit ./configure and remove this test." exit 1 fi # TODO?: Should perhaps test "which qmake" here. # If not found, add $(QTDIR)/bin to path. But the ./BUILD script does that. echo "Your qmake version is:" qmake-qt4 --version echo echo "Your gcc version is (unless qmake is set up to use a different one):" gcc --version echo CONFIG_OPTS="$@" VERSION_NUMBER=`./VERSION` echo echo "Running qmake-qt4 with CONFIG_OPTS=$CONFIG_OPTS VERSION_NUMBER=$VERSION_NUMBER..." qmake-qt4 "CONFIG_OPTS=$CONFIG_OPTS" "VERSION_NUMBER=$VERSION_NUMBER" main.pro echo "...configuration completed - ready to do 'make' now" evolvotron/doxygen.cfg0000644000175100017510000010757611055517066015021 0ustar timdaytimday# Doxyfile 1.2.14 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # General configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = evolvotron # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doc # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, # German, Greek, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, # Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish. OUTPUT_LANGUAGE = English # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these class will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. It is allowed to use relative paths in the argument list. STRIP_FROM_PATH = # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower case letters. If set to YES upper case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # users are adviced to set this option to NO. CASE_SENSE_NAMES = YES # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explict @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # reimplements. INHERIT_DOCS = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consist of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = libevolvotron/moc # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. INPUT_FILTER = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse. FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the Html help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, # or Internet explorer 4.0+). Note that for large projects the tree generation # can take a very long time. In such cases it is better to disable this feature. # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimised for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assigments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_XML = NO #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = "FUNCTION_BEGIN(FN,NP,NA,IT)=class FN : public FunctionBoilerplate{public:" \ "FUNCTION_END(FN)=};" # If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line and do not end with a semicolon. Such function macros are typically # used for boiler-plate code, and will confuse the parser if not removed. SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # Configuration::addtions related to external references #--------------------------------------------------------------------------- # The TAGFILES tag can be used to specify one or more tagfiles. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superceded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yield more powerful graphs. CLASS_DIAGRAMS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # changed from NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are gif, jpg, and png # If left blank gif will be used. DOT_IMAGE_FORMAT = gif # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermedate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::addtions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO # The CGI_NAME tag should be the name of the CGI script that # starts the search engine (doxysearch) with the correct parameters. # A script with this name will be generated by doxygen. CGI_NAME = search.cgi # The CGI_URL tag should be the absolute URL to the directory where the # cgi binaries are located. See the documentation of your http daemon for # details. CGI_URL = # The DOC_URL tag should be the absolute URL to the directory where the # documentation is located. If left blank the absolute path to the # documentation, with file:// prepended to it, will be used. DOC_URL = # The DOC_ABSPATH tag should be the absolute path to the directory where the # documentation is located. If left blank the directory on the local machine # will be used. DOC_ABSPATH = # The BIN_ABSPATH tag must point to the directory where the doxysearch binary # is installed. BIN_ABSPATH = /usr/local/bin/ # The EXT_DOC_PATHS tag can be used to specify one or more paths to # documentation generated for other projects. This allows doxysearch to search # the documentation for these projects as well. EXT_DOC_PATHS = evolvotron/evolvotron.html0000644000175100017510000007344112100750300015735 0ustar timdaytimday Evolvotron User Manual

Evolvotron User Manual

Evolvotron is interactive "generative art" software to evolve images/textures/patterns through an iterative process of random mutation and user-selection driven evolution.

On starting the application, a grid of images is displayed. Resize or maximise the application if you like, but the more pixels have to be calculated, the slower it will be. (For the default 2D image mode, you will need a fast machine or patience. For the optional animation mode, you will need both.)

Simply repeat the following until bored:

  • Click (singleclick) on an image you like to spawn the next generation of its mutant offspring.
  • Wait until variations on it are regenerated in sufficient detail that you can decide which one you like best again.

IMPORTANT: Initially you should select images with some sort of variation. If you select a uniform image, you may get stuck in a degenerate zone with little to mutate and therefore little chance of escape to more interesting images. You can always reset/restart from the "File" menu (the difference is that "reset" also resets the mutation parameters to their default values). Selecting one of the "warp" options from a context menu (right-click on an image) can also help by introducing an additional opportunity for mutation on subsequent spawns.

Note that various spirals, grids and tiles, although complex looking, are actually implemented by a single function node and may leave you stuck too.

Command Line Options

The following are equivalent:

  • evolvotron --grid 12x8
  • evolvotron --grid=12x8
  • evolvotron -g 12x8

General Options

  • -a, --autocool
    Enable autocooling by default, and cause resets of mutation parameters to re-enable autocooling if it was disabled.

  • -F, --fullscreen
    Start in "fullscreen" mode (NB for Qt on X11 this means a screen-filling borderless/undecorated window is used; it's not simply maximising the window, and it's not the sort of framebuffer hijacking used by SDL games). The Qt documentation claims some window managers may not be entirely cooperative with this (in which case sorry, you're on your own). evolvotron actions which bring up dialog boxes (e.g save) seem to generally behave fairly sensibly but child windows (e.g enlargements or dialogs) can show some "interesting" behaviour. Fullscreen mode can be toggled within the application using "F" key. The "Esc" key will also exit it.

  • -g, --grid colsxrows
    Sets size of the grid of image display cells in the main application area (defaults to 5x6)

  • -h, --help
    Print summary of command line options and exit.

  • -j, --jitter
    Enable sample jittering. Samples will be made at a random position within a pixel instead of on a regular grid, providing some antialiasing.

  • -m, --multisample multisample grid
    Enables additional antialiasing passes. Specifing 2 or 3 will provide an additional pass with 2x2 or 3x3 samples per pixel. Specifiying 4 (of higher) will provide a 2x2 and a final 4x4 pass. Specifying 1 provides the default behaviour of one sample per pixel. For best rendering quality also specify -j.

  • -M, --menuhide
    Start with menu and status bar hidden. Nice with --fullscreen. Hiding can be toggled within the application using ctrl-m. The Esc key will also bring them back.

  • -p, --spheremap
    Images are produced by sampling the underlying 3D function on the latitude-longitude grid of a sphere. The resulting images should be usable as spheremaps/spherical environment maps. Animations vary the radius of the sphere. NB when in spheremap mode, middle mouse button adjustments do not yet behave like you'd expect.

  • -S, --startup function_filename
    Specify a function filename (evolvotron's XML format) to load on startup (or reset). The option can be provided multiple times, and this is also the interpretation of any positional arguments. Startup functions are placed in the grid from left to right, top to bottom.

  • -U, --shuffle
    Use in conjunction with -S / --startup options, to display the specified functions in random order, both on application startup and on each reset of the application.

Animation Options

  • -f, --frames frames
    Number of frames in animations (defaults to 1 i.e no animation)

  • -l, --linear
    Vary z linearly with time rather than sinusoidally. Sinusoidal variation generally looks better when animations are "bounced" forwards and backwards, but this option is useful when generating slices to use as volumetric textures.

  • -s, --fps framerate
    Rate at which frames are displayed per second (integer). (Defaults to 8).

Power-user & Debug Options

Note that the usual Qt/X11 options (for example, -geometry widthxheight option to set on-screen size in pixels) are processed and removed before evolvotron options are checked.

  • -D, --debug
    Puts the certain aspects of the app into a more debug oriented mode. Currently (ie this may change) it simply changes function weightings so virtually all function nodes are FunctionNoiseOneChannel. By itself this is a pretty pointless thing to do, but in conjunction with the -X options it's useful for examining the behaviour of specific functions.

  • -E, --enlargement-threadpool
    Use a separate thread pool for computing enlargements. Using this option ensures computation of enlargements continue to make some progress even while the main grid is being actively worked on. However, this will be at the expense of main grid rendering performance. Without this option, enlargements' final high-resolution renderings are invariably lower priority than computation for images in the main grid. See also the -N option to control the priority of threads in this pool.

  • -n, --nice niceness
    Sets additional niceness (relative to the main application thread) of the compute (rendering) thread(s). It's useful to run compute threads at a slightly lower priority ("nice 4" is the default without this option) than the main (GUI) part of the program (but note that this means other normal/lowish priority tasks running on your machine may slow evolvotron down a bit more than expected).

  • -N, --Nice enlargement niceness
    Sets additional niceness (relative to the main application thread) of the compute thread(s) computing enlargements (default value is 8). Only effective in conjunction with -E option.

  • -t, --threads threads
    Sets number of compute threads. If this is not specified, then as many compute threads are created as there are processors on the system (unless this cannot be discovered in which case only a single compute thread is created). Non-linux builds will likely not include code to determine processor count (suitable patches gratefully received).

  • -u, --unwrapped
    Modifies -F behaviour so that the specified "favourite" function is NOT wrapped by space/colour transforms. NB For functions without leaf nodes or parameters (e.g FunctionSphericalToCartesian) this doesn't leave any scope for variation or future mutation. Function name recognition is case sensitive. Example: evolvotron -F FunctionKaleidoscope -u

  • -v, --verbose
    Verbose mode, writes various things to application stderr. This is primarily intended to assist debugging. This option used to be useful for getting a list of supported function names for use with the -F option, but those can also be inspected via the Settings dialogs.

  • -x, --favourite functionname
    Force a specific "favourite" function type to be used at the top level of all function trees. The specified function is still wrapped by spatial and colour warping functions which may disguise it considerably. A list of all the function names understood by evolvotron is output during app startup when the -v option is specified. Function name recognition is case sensitive. Example: evolvotron -F FunctionSpiralLinear

Mouse Control

Left-click

A left-click on an image in the main window spawns the mutant offspring of that image to all the other (non-locked) displays in the grid.

Right-click Context Menu

Right clicking on an image gets you a few more options:

  • "Respawn" regenerates just the current image from whatever it was spawned from (and using recolour or warp, if that's what was used to produce it). The main use of this is to make your grid of images look nice for screendumps, by regenerating any which aren't up to scratch. NB May not work as expected after an "undo".

  • "Spawn" is the same as clicking an image. It generates mutated images to all unlocked images in the grid.

  • "Recolour" to produce different coloured variants of the selected image

  • "Warp"'s sub-options produce variants of the image which have been zoomed/rotated/panned.

  • "Lock" to prevent an image from being overwritten by spawns from other images (select again to toggle).

  • "Enlarge" to produce a blow-up of the image in a single window. Submenu items select either a freely resizable window or a scrollable view of a fixed size image. If the application is running in fullscreen mode (NB this is NOT the same as a simply "maximised" window) then the enlarged image will also be fullscreen (the "Resizeable" mode is probably what you want in this case as the image will automatically be rendered at the correct resolution).

  • "Save image" to save the image in a file (.ppm or .png). You generally want to save an enlarged image: if you save a small image from the grid, the size you see on the screen is the size you get in the file. Save isn't allowed until the full resolution image has been generated; if you try to save too early a dialog box will be displayed telling you to try again later.

  • "Save function" to store the function to an XML file.

  • "Load function" to load a stored function from an XML file. NB if the file was saved from a different version numbered evolvotron, a warning message will be generated. Save/load of functions is an experimental feature and you should not count on future versions of evolvotron being able to load files saved from old versions, or producing the same image from a loaded function. Attempting to load functions from later versions into earlier versions is even less likely to succeed.

  • "Simplify" prunes the function tree of redundant branches where possible (the same action can be applied to all images from the main "Edit" menu). This doesn't change the appearance of the image, but may make it recompute faster.

  • "Properties" brings up a dialog box containing some information about the image (e.g the number of function nodes it contains).

Middle Mouse Button

[NB This feature will probably only be of practical use to those with high-end machines].

You can use the middle mouse button to drag-adjust individual images. This is useful for "final composition" type tweaks, e.g centering an image's most interesting feature, or just for satisfying your curiosity about what's off the edge of the image.

It also works on enlarged images, although it's virtually unusable without a bit of practice on smaller, faster ones (just boldly make the adjustment you want, release the button... and wait).

Changes made can be rolled-back on the main Edit/Undo menu item, one drag-action at a time.

An unmodified middle-mouse drag pans the image around following the mouse motion.

A SHIFT-middle drag zooms the image in and out with scaling proportional to the distance from the centre of the image. Beware of generating huge zooms by clicking too near the centre of the image.

An ALT-SHIFT-middle drag is similar but anisotropic: the scaling may be different in X and Y. Warning: this technique is very sensitive and can be quite tricky to use! In particular, if you initially click near the centre axes of the image the zoom factor can be HUGE, so the best way to start using this is to click about halfway on a diagonal between the image centre and a corner and gently move in and out radially. Dragging from one side of the image to the other flips it over (the degenerate case of infinite zoom at the centre is handled cleanly I think). If it all goes horribly wrong, undo and try again.

A CTRL-middle drag rotates the image about its centre.

A CTRL-ALT-middle drag shears the image (the best way to see what this does is to click in the corner of an image and move the mouse horizontally or vertically).

Keyboard Control

There are some keyboard shortcuts.

Main Window

  • "r"/"t"/"x" perform various starts of reset/restart.

  • "q" quits the application.

  • "u" (and also Ctrl-z) does an undo.

  • "f": full-screen mode (on X11, Qt does this by asking the window manager for a screen-filling undecorated window, and the documentation contains some dire warnings about problems with broken window managers). See also "-F" command line option. Fullscreen mode propagates to enlarged image display windows. NB The application may completely disappear from the screen for a brief interval while switching mode.

  • "m" : hides status and menu-bar hiding, which can be nice when in full-screen or window-maximised mode. See also "-M" command line option. Also note that while the menu bar is hidden, most of these keyboard shortcuts won't function as they're tied to the menu system.

  • Esc : exits full-screen and/or menu-hiding mode, putting the application into its normal default state.

Enlargement Windows

The image display windows created by selecting "Enlarge" from a context menu also have a couple of keyboard operations:

  • "f" : [NB only available with fullscreen build option] toggles full-screen mode. When returning to normal mode, if the main app window was fullscreen then it will also drop back to normal mode.

  • Esc : [NB only available with fullscreen build option] completely closes a fullscreen-mode enlargement window.

Gui Elements

Main Menu Bar

  • File menu: Items to restart, reset and quit the application. The difference between restart and reset is that reset sets the mutation parameters back the their default values. The "randomize function weights" version of restart scrambles the relative probability of the various function types (if you think evolvotron just keeps generating the same kinds of images give it a try). The "restart with specifc function" item duplicates the functionality of the "-x" and "-X" command-line options.
  • Edit menu: "Undo" lets you undo certain actions: e.g spawn, middle-button adjustment, simplification and lock/unlock. There is a large but limited number of levels of undo. "Simplify" is of curiosity value only: it prunes redundant branches from images ("junk DNA"); this may help them recompute faster but at the cost of there being less mutatable material.
  • Settings menu: "Mutations" brings up a dialog to modify the amount of change spawned images are subject to. (See "advanced usage" below.) "Functions" brings up a dialog to modify the relative probability of functions being used. By default all functions are equally likely except for iterative functions and fractals, which are almost but not completely supressed. But if you think there are too many spirals or grids (or not enough fractals) then this is the place to adjust the frequency with which they appear. If the software was built with the fullscreen option, that can also be controlled from this menu. "Favourite" brings up a dialog which allows you to select a specific function type to always be used as the root node of any new functions. The function can be wrapped by some other random stuff, or unwrapped. See also the -X and -x command line options.
  • Help menu: Items to bring up documentation, and the usual "About" box (which includes the license).

Status Bar

An area on the status bar shows how many compute "tasks" are outstanding (or "Ready" when there are none). When two task totals are reported, the first is for the main grid and the second for any enlargements being computed. Each "task" is the recomputation of an image at some resolution. Tasks are prioritised by their number of pixels (small image implies higher priority). This is why, if the main grid is still recomputing, recalculations of enlargements will appear to freeze after they have reached a certain resolution, at least until other lower resolution tasks have completed.

The status bar also provides some control over the "autocool" mechanism which reduces mutation strength with time. See the advanced usage section below.

Tips

  • Don't start a session with any preconceived ideas about the kind of image you want to get out of it. You will be disappointed.
  • I get the best results when I click the image which most immediately catches my eye as they start appearing. If you stop to think about it too much then things seem to go downhill.
  • If you seem to be just getting the same old spirals and grids all the time, stop clicking on spirals and grids! (The same goes for random mush).
  • Don't get too hung up on using the warp and middle-mouse drag adjustments every iteration... use those tools for final polishing of your masterpiece.
  • You can quickly cycle through a lot of initial images (until you find one with real potential) by bashing on Ctrl-r to repeatedly restart.
  • To add variety to an image's mutations, nudge it with a small middle-mouse drag. This introduces a top level transform, and therefore more parameters to be varied.
  • Enlargements take a long time to complete their final high-resolution rendering pass (especially with multisampling enabled). Most convenient practice seems to be to go away and leave them to complete, then come back and save them later. Continuing to click away on the main grid effectively starves them of CPU, unless the -E command-line option is used.

Animation

As of version 0.2.0 evolvotron contains some experimental support for generation of animations (although so far the results have been pretty disappointing IMHO, but it's still early days).

NB THIS IS EVEN MORE COMPUTATIONALLY AND MEMORY INTENSIVE THAN THE STATIC IMAGE MODE.

Simply supply a -f frames command line option and evolvotron will generate animated sequences with the specified number of frames. These will be displayed at the frame rate specified by the optional -s framerate option (default 8). So "evolvotron -s 24" will generate 3 second long animations. Animations reverse direction at each end to avoid a sudden jump.

If you save an animation as PPM or PNG, multiple files will be saved with .fnnnnnn (where nnnnnn is the zero-filled frame number) inserted in each filename before the filetype qualifier.

For example, if you enter foo.ppm as the filename to save, files foo.f000000.ppm, foo.f000001.ppm... will be saved. If you have the ImageMagick tools you can convert these to an animated GIF playing at approx. 8 frames per second with:

convert -delay 12 foo.f??????.ppm foo.gif

Advanced Usage

Evolvotron's idea of an image is a function which converts XYZ co-ordinates to an RGB colour (however we can only display a 2D plane for now so the input Z is fixed to zero, or varied with time when animating).

The image functions are constructed from trees of function nodes. (In the mathematical expression 1+(2*x) the "+" and the "*" would be function nodes.) Evolvotron's functions tend to correspond to geometric or colour-space operations or anything else which can be applied to a 3D vector.

By mutating the structure of the function tree (adding random branches, for example) and the values of the constant embedded within it, the image can be changed.

The mutation parameters are under control from the dialogs accessible via the Settings menu, and the "autocool" mechanism exposed in the status bar also has some influence.

There are two kinds of mutation: perturbations to the magnitude of constants, and structural mutations which rearrage the function tree of an image. Four types of structural mutations are currently implemented:

  • replacement of a function branch by a new random stub (a "Glitch" mutation).
  • a random shuffle of a node's sub-nodes
  • insertion of random nodes between a node and it's sub-nodes
  • the substitution of a node with one of a different type, with sub-nodes unaffected where possible).

The probability (per function node) of these mutations is controlled from spinboxes on the "Mutation Parameters" dialog (expressed as chances-in-a-hundred), as is the size of perturbations to constants.

It is useful to think of the perturbations to constant parameters as being a thermal effect (hence the "heat" and "cool" buttons), while structural alterations are more drastic and are caused by high energy gamma rays or something (hence "irradiate" and "shield" buttons to adjust the probability of structual mutations).

So why would you want to change the mutation parameters from the initial defaults ? Basically, if you're getting too much variation in spawned images (this tends to happen after many generations of images, by which time the function trees have grown quite large and therefore are experiencing a lot of mutations) then cool and/or shield. If all the images look too similar, heat and/or irradiate.

The "autocool" mechanism (enabled from the statusbar or mutation parameters dialog) automatically reduces the strength of mutations from the base values with successive generations. The cooling can be cancelled by disabling autocooling or pressing the "Reheat" button to zero the number of generations counted for cooling. The effect of the cooling is a compound halving of the mutation strength after some number of generations (this number is the "half-life" controllable from the mutation parameters dialog). Note that if autocooling is enabled then eventually, after a number of iterations more than many multiples of the half-life has passes, spawned images will differ very little from their parents (hence the need for "reheat").

There is also a dialog accessible from "Functions..." on the "Settings" menu. This allows control over the relative proportions in which functions occur. There is a tab showing the relative weighting of all functions (log-2 scale: each tick halves the probability of the function occurring), and additional tabs for various classifications of function for quicker access. The "Randomize" button on each tab assigns random weightings and helps increase the uniqueness of your session.

The "Functions" dialog also has a "Dilution" tab which allows the average function-tree branching ratio to be controlled (by changing the proportion of trivial zero-branch functions added): note that using a high branching ratio results in very complex images which will take a long time to compute, while reducing the ratio results in simple, boring images.

3 types of function node are considered fundamental: constant nodes (which return a constant), identity nodes (which return their position argument) and transform nodes (which transform their positon argument by random parameters). On the "Dilution" tab of the "Functions" dialog there are two slider controls to affect things related to these:

  • "proportion constant" controls the proportion of diluting fundamental nodes which are constants. Changing this from its default value of 0.5 doesn't actually seem to have much effect.
  • "proportion transforms" sets the proportion of non-constant nodes diluting which are transforms (as opposed to identity nodes). The main effect of this is that images are less commonly obviously centred on the origin or aligned with the axes. I think this is a good thing, so the value is at 1.0 by default.

Other Executables

This release also builds some other command-line driven (non-GUI, non-interactive) utilities. Consult the man pages for full details.

evolvotron_render reads a XML function description from its standard input and renders it to the file specified.

evolvotron_mutate reads an XML function description from its standard input and outputs a mutated version. A command line option allows the "genesis" situation of creating a random function description with no input.

Examples

Evolving and mutating on the command line:

evolvotron_mutate -g | tee fn.xml | evolvotron_render /tmp/xxx.ppm ; display /tmp/xxx.ppm

cat fn.xml | evolvotron_mutate | evolvotron_render -j -m 4 /tmp/xxx.ppm ; display /tmp/xxx.ppm

Animating a function ani.xml saved from evolvotron in animation mode:

cat ani.xml | evolvotron_render -f 100 -v -s 256 256 ani.ppm ; animate ani.f??????.ppm

Future Developments

Please check the TODO file first before you send me suggestions!

Please don't ask me to port evolvotron to proprietary platforms. You are of course Free under the terms of the GPL to do so yourself, but please read http://www.fefe.de/nowindows/ first.

Thanks

To those who have contributed feedback, suggestions and patches:

  • Dmitry Kirsanov
  • Jonathan Melhuish
  • Karl Robillard
  • Linc Davis
  • Paolo Greppi
  • Marcin Wojtczuk
  • Michael Sterrett
  • Massimiliano Guastafierro
  • Goetz Waschk
  • Forrest Walter

And to the anonymous Linspire reviewer who perhaps came up with the best summary of evolvotron yet: "Fascinating. Utterly pointless, but fascinating."

The friezegroups wouldn't have been possible without http://michaelshepperd.tripod.com/resources/groups.html

Thanks to www.di.fm, www.somafm.com and Trance4Ever for music to code to.

Thanks especially to a SIGGRAPH conference panel many years ago (likely including Karl Sims, the pioneer in this area) who first got me interested in this stuff.

Why ?

I have always admired those who have the skill to wield a pen or paintbrush and fill a sheet of paper or a canvas with some striking image from their imagination. Unfortunately I lack the patience to learn such skills, and probably the necessary manual dexterity and imagination too.

Evolvotron, and several predecessors developed on and off over a decade since I first came across the idea, are an attempt to compensate for this using the skills I do have i.e some mathematical sensibility and the ability to write working code (well, sometimes). If you like an image it produces, then as far as I'm concerned that's as satisfying a result as if you liked something I'd drawn myself.

Tim Day evolvotron/libfunction/update_register_all_functions0000755000175100017510000000173411055517066023220 0ustar timdaytimday#!/bin/bash rm -f register_all_functions.cpp cat <> register_all_functions.cpp /* AUTO GENERATED FILE. DO NOT EDIT */ /* Should be updated by update_register_all_functions script when new functions are added */ #include "libfunction_precompiled.h" #include "register_all_functions.h" #include "function_boilerplate.h" EOF HEADERS=`grep -l FUNCTION_BEGIN *.h | sed 's/function_boilerplate.h//'` for f in $HEADERS ; do sed -f stripcomments.sed "$f" \ | grep FUNCTION_BEGIN \ | sed 's/FUNCTION_BEGIN(//' \ | sed 's/,.*//' \ | awk '{printf("REGISTER_DCL(%s);\n",$0);}' \ >> register_all_functions.cpp done cat <> register_all_functions.cpp void register_all_functions(FunctionRegistry& r) { EOF for f in $HEADERS ; do sed -f stripcomments.sed "$f" \ | grep FUNCTION_BEGIN \ | sed 's/FUNCTION_BEGIN(//' \ | sed 's/,.*//' \ | awk '{printf(" register_%s(r);\n",$0);}' \ >> register_all_functions.cpp done cat <> register_all_functions.cpp } EOF evolvotron/mkdeb0000755000175100017510000000677312100750252013654 0ustar timdaytimday#!/bin/bash # Before using this you probably need to install # sudo pbuilder yada devscripts lintian cdebootstrap # and maybe dpkg-sig. Also: # set up for sudo # set up pbuilder's /etc/pbuilderrc (maybe no attention needed these days) # sudo pbuilder create --distribution squeeze # and/or update with # sudo pbuilder update # Expect a lot of warnings re LOGNAME - see Debian bug Bug#275118 # TODO: DEBEMAIL VER=`./VERSION` TARBALL=evolvotron-${VER}.tar.gz if [ ! -s ${TARBALL} ] ; then echo "Could't find ${TARBALL}" ; exit ; fi export DISTRIBUTION=`lsb_release -s -c` echo "*** Will package ${TARBALL} for distribution \"${DISTRIBUTION}\"" echo -n "*** Starting in 5 seconds..." for t in 5 4 3 2 1 ; do sleep 1 ; echo -n "." ; done PROJECT=`echo $TARBALL | sed 's/-.*//'` TARBALLORIG="${PROJECT}_${VER}.orig.tar.gz" REV="1${DISTRIBUTION}1" WORKDIR=pkg_${VER}-${REV} rm -r -f ${WORKDIR} mkdir ${WORKDIR} cd ${WORKDIR} cp ../${TARBALL} ${TARBALLORIG} tar xvfz ${TARBALLORIG} mv ${PROJECT} ${PROJECT}-${VER} cd ${PROJECT}-${VER} sed -i "s/${VER}/${VER}-${REV}/g" VERSION mkdir debian dch --create --package evolvotron --distribution stable --newversion ${VER}-${REV} "Created by mkdeb script" cat << EOF > debian/packages Source: evolvotron Section: graphics Priority: extra Maintainer: Tim Day Standards-Version: 3.6.1 Upstream-Source: Home-Page: Description: Interactive evolutionary texture generator Copyright: GPL Copyright 2009 Tim Day Build-Depends: qt4-qmake,qt4-dev-tools,libqt4-dev,libqt4-xml,libboost-dev,libboost-program-options-dev,yada Build: sh export QTDIR=/usr/share/qt4 # Note: yada install deals with DEB_BUILD_OPTIONS 'nostrip' if [ "${DEB_BUILD_OPTIONS#*noopt}" != "$DEB_BUILD_OPTIONS" ]; then ./configure "CONFIG -= release" "CONFIG += debug" else ./configure # No noticeable advantage in overriding qt optimisation options fi make Clean: sh make distclean || make clean || true Package: evolvotron Architecture: any Depends: [] Suggests: gimp Description: Interactive evolutionary texture generator A "generative art" application to evolve images/textures/patterns through an iterative process of random mutation and user-selection driven evolution. If you like lava lamps, and never got bored with the Mandelbrot Set, this could be the software for you. Install: sh yada install -bin evolvotron/evolvotron yada install -bin evolvotron_mutate/evolvotron_mutate yada install -bin evolvotron_render/evolvotron_render yada install -bin evolvotron/evolvotron yada install -doc evolvotron.html yada install -doc BUGS TODO NEWS USAGE yada install -man man/man1/evolvotron.1 yada install -man man/man1/evolvotron_mutate.1 yada install -man man/man1/evolvotron_render.1 Menu: ?package(evolvotron): needs="X11" section="Applications/Graphics" title="Evolvotron" hints="Bitmap" command="/usr/bin/evolvotron" longtitle="Evolutionary art program" EOF yada rebuild cd .. dpkg-source -b ${PROJECT}-${VER} ${TARBALLORIG} # Alternative but inferior approach is apparently to do # dpkg-buildpackage -rfakeroot mkdir result echo "Building package" sudo pbuilder build --allow-untrusted --buildresult ./result ${PROJECT}_${VER}-${REV}.dsc sudo chown ${USER}:${USER} result/* RESULT=`(cd .. ; find ${WORKDIR} -name '*.deb')` echo "Results: ${RESULT}" echo "Don't forget to lintian ${RESULT}" echo 'Also dpkg-sig --sign builder -k $DPKGSIG_KEYID any .deb files' evolvotron/mkdoc0000755000175100017510000000006111055517066013663 0ustar timdaytimday#!/bin/sh -v mkdir -p doc doxygen doxygen.cfg evolvotron/mktgz0000755000175100017510000000177212100750252013720 0ustar timdaytimday#!/bin/bash # Execute this to package up evolvotron as a .tar.gz VERSION=`./VERSION` DIR=${PWD##*/} cd .. # NB Don't ship contents of pkg PRUNE='-name moc -prune -o -name obj -prune -o -name pkg_* -prune' FILES_MISC=`ls ${DIR}/{README,BUILD,LICENSE,TODO,NEWS,VERSION,USAGE,BUGS,configure,doxygen.cfg,mktgz,mkdeb,mkdoc,text_to_markup.py,evolvotron.html} ${DIR}/libfunction/update_register_all_functions` FILES_EXTRAS="`ls ${DIR}/extras/{README,spheremap.pov,spheremap.sh}` `ls ${DIR}/rpm/{README,evolvotron.spec}`" FILES_H=`find ${DIR} ${PRUNE} -o -name '*.h' -print` FILES_CPP=`find ${DIR} ${PRUNE} -o -name '*.cpp' -print` FILES_PRO=`find ${DIR} ${PRUNE} -o -name '*.pro' -print` FILES_MAN=`find ${DIR}/man ${PRUNE} -o -name '*.1' -print` FILES="$FILES_MISC $FILES_EXTRAS $FILES_H $FILES_CPP $FILES_PRO $FILES_MAN" tar --transform "s:^${DIR}/:evolvotron/:" -cz -f ${DIR}/evolvotron.tar.gz $FILES echo "***" echo "*** Suggestion: mv evolvotron.tar.gz evolvotron-$VERSION.tar.gz" echo "***" evolvotron/text_to_markup.py0000755000175100017510000001464111267025132016264 0ustar timdaytimday#!/usr/bin/env python # Convert Tim-style text to html or qml # # The Rules: # - Lines with all upper case words to h2 or h3 capwords depending on next line underlining (first to h1/title though) # (must be 3 chars or more) # (todo: relax to not all upper case... no need to capwords if not) # - Other text to p, blank lines break a p # - Lines beginning with "- " (NB space) to ul/li (bulleted) # - Lines beginning with "-?" (no space) to ul/li (?) with
at end of first line # - Words delim to xxx # "$ " at start of line indicates one line of code (add
too) import sys import string import re def line_of_dashes(n): r="" for i in xrange(n): r+="-" return r def line_of_equals(n): r="" for i in xrange(n): r+="=" return r class TextToMarkup: def __init__(self,m,s): self.startup=1 # True self.scope_p=0 # False self.scope_ul=0 # False self.scope_li=0 # False self.done_title=0 # False self.skipnextline=0 # False self.mode=m self.stringify=s def dispose(self,l): if self.stringify: self.output.write("\"") # Actually, they should all have been "-ed anyway for c in l: if c=="\"": self.output.write("\\\"") else: self.output.write(c) self.output.write("\\n\"\n") else: self.output.write(l+"\n") def process_word(self,w): r="" if len(w)<3: # Special case allows "<" or "<>" without turning italic for i in xrange(len(w)): if w[i]=="<": r+="<" elif w[i]==">": r+=">" else: r+=w[i] else: for i in xrange(len(w)): if w[i]=="<": r+="" elif w[i]==">": r+="" elif w[i]=='"': r+=""" elif w[i]=="&": r+="&" else: r+=w[i] return r def process_paragraph_text(self,txt): is_code=0 # False specialbreak=0 # False r=" " if txt[0]=="-": if txt[1]==" ": txt=txt[2:] else: specialbreak=1 # True if self.scope_ul and self.scope_li: r+="" self.scope_li=0 # False if not self.scope_ul: r+="

    " self.scope_ul=1 # True if not self.scope_li: r+="
  • " self.scope_li=1 # True elif txt[0]=="$": is_code=1 # True r+="" txt=txt[2:] for w in txt.split(): r+=self.process_word(w) r+=" " if is_code: r+="" if specialbreak: r+="
    " return r def process(self,in_stream,out_stream): self.output=out_stream self.input=in_stream if self.mode=="html": self.dispose("") while 1: # True if self.startup: self.currline_raw=in_stream.readline() self.nextline_raw=in_stream.readline() self.startup=0 # False else: self.currline_raw=self.nextline_raw self.nextline_raw=in_stream.readline() if not self.currline_raw: break if self.skipnextline: self.skipnextline=0 # False continue # Should track last line too self.currline=self.currline_raw.strip() self.nextline=self.nextline_raw.strip() if len(self.currline)>2 and self.nextline==line_of_equals(len(self.currline)): if self.done_title: self.dispose("

    "+string.capwords(self.currline)+"

    ") self.skipnextline=1 # True continue else: if (self.mode=="html"): self.dispose("") self.dispose("") self.dispose(""+string.capwords(self.currline)+"") self.dispose("") self.dispose("") elif (self.mode=="qml"): self.dispose("") self.dispose("

    "+string.capwords(self.currline)+"

    ") self.done_title=1 # True self.skipnextline=1 # True continue elif len(self.currline)>2 and self.nextline==line_of_dashes(len(self.currline)): self.dispose("

    "+string.capwords(self.currline)+"

    ") self.skipnextline=1 # True continue elif self.scope_p: if (len(self.currline)): self.dispose(self.process_paragraph_text(self.currline)) else: if self.scope_li: self.dispose("
  • ") self.scope_li=0 # False if self.scope_ul: self.dispose("
") self.scope_ul=0 # False self.dispose("

") self.scope_p=0 # False elif len(self.currline): self.dispose("

") self.dispose(self.process_paragraph_text(self.currline)) self.scope_p=1 # True else: self.dispose("") if self.mode=="html": self.dispose("") self.dispose("") ######################################### if __name__=='__main__': mode=None stringify=0 # False for i in xrange(1,len(sys.argv)): if sys.argv[i]=="-qml": mode="qml" if sys.argv[i]=="-html": mode="html" elif sys.argv[i]=="-s": stringify=1 # True t2m=TextToMarkup(mode,stringify) # "html" and "qml" are alternatives. Should be stringify option. t2m.process(sys.stdin,sys.stdout) evolvotron/extras/README0000644000175100017510000000045311055517061015026 0ustar timdaytimday --- spheremap.sh is a script to animate a spheremap applied to a rotating sphere. The scene description is in spheremap.pov. It assumes the existence of a file called spheremap.png, which you should create by saving an (enlarged, probably) image from evolvotron running in -spheremap mode. --- evolvotron/extras/spheremap.pov0000644000175100017510000000036011055517061016655 0ustar timdaytimday#include "colors.inc" camera {perspective location <0,1,-4.5> look_at <0,0,0> angle 45} light_source {<100,100,-100> color White} sphere { <0,0,0>,1 pigment { image_map {png "spheremap.png" map_type 1} } rotate <0,clock*360,0.0> } evolvotron/extras/spheremap.sh0000755000175100017510000000023211055517061016464 0ustar timdaytimday#!/bin/bash # Disclaimer: I'm using povray version "3.5 Unix". Which is probably quite old now. povray spheremap.pov +KFI1 +KFF100 +H240 +W320 +Of.png evolvotron/rpm/README0000644000175100017510000000045511055517056014324 0ustar timdaytimdayThis directory contains contributed RPM packaging related resources. ----- evolvotron.spec - Karl Robillard's .spec file to build RPM packages on Mandriva, Fedora and Suse. ----- See http://www.bottlenose.demon.co.uk/share/evolvotron/download.htm for up-to-date news re downloadable packages. evolvotron/rpm/evolvotron.spec0000644000175100017510000000234711055517056016537 0ustar timdaytimdaySummary: Evolvotron Interactive Art Generator Name: evolvotron Version: 0.5.1 Release: 1 License: GPL URL: http://sourceforge.net/projects/evolvotron Packager: Group: Applications/Graphics Source: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?fedora_version} BuildRequires: gcc-c++ boost-devel python qt-devel %else BuildRequires: gcc-c++ boost-devel python qt3-devel %endif %description Evolvotron is interactive "generative art" software to evolve images/textures/patterns through an iterative process of random mutation and user-selection driven evolution. %prep %setup -q -n %{name} %build %if 0%{?fedora_version} source /etc/profile.d/qt.sh %endif %if 0%{?mandriva_version} export QTDIR=%{_prefix}/lib/qt3 export PATH=$QTDIR/bin:$PATH %endif %if 0%{?suse_version} export QTDIR=/usr/%{_lib}/qt3 export PATH=$QTDIR/bin:$PATH %endif ./configure make %install # make install mkdir -p $RPM_BUILD_ROOT/usr/bin install -s -m 755 evolvotron/evolvotron $RPM_BUILD_ROOT/usr/bin %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) /usr/bin/evolvotron %doc README USAGE CHANGES %changelog * Fri Mar 28 2008 Karl Robillard - Initial package release. evolvotron/evolvotron_render/evolvotron_render_precompiled.h0000644000175100017510000000312612100750300024707 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Precompiled header for evolvotron_render */ #ifndef _evolvotron_render_precompiled_h_ #define _evolvotron_render_precompiled_h_ #include "libevolvotron_precompiled.h" #include #endif evolvotron/evolvotron/evolvotron_precompiled.h0000644000175100017510000000310112100750300022002 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Precompiled header for evolvotron */ #ifndef _evolvotron_precompiled_h_ #define _evolvotron_precompiled_h_ #include "libevolvotron_precompiled.h" #include #endif evolvotron/evolvotron_mutate/evolvotron_mutate_precompiled.h0000644000175100017510000000311712100750250024753 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Precompiled header for evolvotron */ #ifndef _evolvotron_mutate_precompiled_h_ #define _evolvotron_mutate_precompiled_h_ #include "libevolvotron_precompiled.h" #include #endif evolvotron/libfunction/functions_friezegroup_step.h0000644000175100017510000000530712100750300022777 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_friezegroup_step_h_ #define _functions_friezegroup_step_h_ #include "friezegroup.h" //! Step (Conway p1a1): glide reflection only. /*! Sawtooth x, out of step by half range across y-axis. \verbatim o o --- --- --- --- o o \endverbatim */ struct Step { const XY operator()(const XY& p) const { return XY ( (p.y()>0.0 ? modulusf(p.x(),1.0) : modulusf(p.x()+0.5,1.0)), fabs(p.y()) ); } }; struct StepInvariant; struct StepBlend; //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupStepFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Step(),FreeZ()); } FUNCTION_END(FunctionFriezeGroupStepFreeZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupStepClampZ,1,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Step(),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupStepClampZ) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/random.h0000644000175100017510000000701012100750300016564 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces for class Random and derived classes. */ #ifndef _random_h_ #define _random_h_ //! Abstract base class for random number generation class Random { public: //! Constructor (nothing to do in base class) Random() {} //! Trivial destructor. virtual ~Random() {} //! Return a random number. /*! \warning Returns double instead of real because suspect NegExp can return Inf otherwise. */ virtual double operator()() =0; }; //! Generates random numbers in the range [0,1). class Random01 : public Random { public: //! Constructor Random01(uint seed); //! Trivial destructor virtual ~Random01(); //! Return next number in sequence. virtual double operator()(); private: //! Base generator boost::mt19937 _rng; //! Distribution boost::uniform_real<> _dist; //! Actual generator boost::variate_generator > _gen; }; //! Return negative-exponentially distributed random numbers. class RandomNegExp : public Random { protected: //! Underlying generator. Random01 _generator; //! Mean value of distribution. double _mean; public: //! Construct generator of numbers with mean value m. RandomNegExp(uint seed,double m) :_generator(seed) ,_mean(m) {} //! Trivial destructor. virtual ~RandomNegExp() {} //! Return next number in sequence. virtual double operator()() { return -_mean*log(1.0-_generator()); } }; template void random_shuffle(boost::ptr_vector& v,Random01& r01) { boost::ptr_vector nv; while (!v.empty()) { const uint n=static_cast(r01()*v.size()); nv.transfer(nv.end(),v.begin()+n,v); } v.transfer(v.end(),nv.begin(),nv.end(),nv); } //! Adapter to use our random number generator to feed std::random_shuffle class RandomInt { public: RandomInt(Random01& r01) :_r01(r01) {} uint operator()(uint n) { return static_cast(_r01()*n); } private: Random01& _r01; }; template void random_shuffle(std::vector& v,Random01& r01) { RandomInt r0n(r01); std::random_shuffle(v.begin(),v.end(),r0n); } #endif evolvotron/libfunction/register_all_functions.h0000644000175100017510000000333612100750300022057 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief File declaring function to register all functions. NB The corresponding register_all_functions.cpp is AUTO GENERATED by update_register_all_functions script. */ #ifndef _libevolvotron_register_all_functions_h_ #define _libevolvotron_register_all_functions_h_ class FunctionRegistry; extern void register_all_functions(FunctionRegistry&); #endif evolvotron/libfunction/functions_juliabrot.h0000644000175100017510000001402612100750300021374 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_juliabrot_h_ #define _functions_juliabrot_h_ //------------------------------------------------------------------------------------------ //! Mandelbrot/Julia iterator for fractal functions. /*! Returns i in 0 to iterations inclusive. i==iterations implies "in" set. */ inline uint brot(const real z0r,const real z0i,const real cr,const real ci,const uint iterations) { real zr=z0r; real zi=z0i; uint i; for (i=0;i4.0) break; const real nzr=zr2-zi2+cr; const real nzi=2.0*zr*zi+ci; zr=nzr; zi=nzi; } return i; } //------------------------------------------------------------------------------------------ //! Function selects arg to evaluate based on test for point in Mandelbrot set. FUNCTION_BEGIN(FunctionMandelbrotChoose,0,2,true,FnIterative|FnFractal) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return (brot(0.0,0.0,p.x(),p.y(),iterations())==iterations() ? arg(0)(p) : arg(1)(p)); } FUNCTION_END(FunctionMandelbrotChoose) //----------------------------------------------------------------------------------------- //! Function returns -1 for points in set, 0-1 for escaped points FUNCTION_BEGIN(FunctionMandelbrotContour,0,0,true,FnIterative|FnFractal) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint i=brot(0.0,0.0,p.x(),p.y(),iterations()); return (i==iterations() ? XYZ::fill(-1.0) : XYZ::fill(static_cast(i)/iterations())); } FUNCTION_END(FunctionMandelbrotContour) //------------------------------------------------------------------------------------------ //! Function selects arg to evaluate based on test for point in Julia set. FUNCTION_BEGIN(FunctionJuliaChoose,2,2,true,FnIterative|FnFractal) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return (brot(p.x(),p.y(),param(0),param(1),iterations())==iterations() ? arg(0)(p) : arg(1)(p)); } FUNCTION_END(FunctionJuliaChoose) //------------------------------------------------------------------------------------------ //! Function returns -1 for points in set, 0-1 for escaped points FUNCTION_BEGIN(FunctionJuliaContour,2,0,true,FnIterative|FnFractal) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint i=brot(p.x(),p.y(),param(0),param(1),iterations()); return (i==iterations() ? XYZ::fill(-1.0) : XYZ::fill(static_cast(i)/iterations())); } FUNCTION_END(FunctionJuliaContour) //------------------------------------------------------------------------------------------ //! Function selects arg to evaluate based on test for point in Juliabrot set. /*! Juliabrot is 4 dimensional, but we only have 3 incoming parameters, so have 4 4d-basis vector parameters. */ FUNCTION_BEGIN(FunctionJuliabrotChoose,16,2,true,FnIterative|FnFractal) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real zr=p.x()*param( 0)+p.y()*param( 1)+p.z()*param( 2)+param( 3); const real zi=p.x()*param( 4)+p.y()*param( 5)+p.z()*param( 6)+param( 7); const real cr=p.x()*param( 8)+p.y()*param( 9)+p.z()*param(10)+param(11); const real ci=p.x()*param(12)+p.y()*param(13)+p.z()*param(14)+param(15); return (brot(zr,zi,cr,ci,iterations())==iterations() ? arg(0)(p) : arg(1)(p)); } FUNCTION_END(FunctionJuliabrotChoose) //------------------------------------------------------------------------------------------ //! Function returns -1 for points in set, 0-1 for escaped points /*! Juliabrot is 4 dimensional, but we only have 3 incoming parameters, so have 4 4d-basis vector parameters. */ FUNCTION_BEGIN(FunctionJuliabrotContour,16,0,true,FnIterative|FnFractal) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real zr=p.x()*param( 0)+p.y()*param( 1)+p.z()*param( 2)+param( 3); const real zi=p.x()*param( 4)+p.y()*param( 5)+p.z()*param( 6)+param( 7); const real cr=p.x()*param( 8)+p.y()*param( 9)+p.z()*param(10)+param(11); const real ci=p.x()*param(12)+p.y()*param(13)+p.z()*param(14)+param(15); const uint i=brot(zr,zi,cr,ci,iterations()); return (i==iterations() ? XYZ::fill(-1.0) : XYZ::fill(static_cast(i)/iterations())); } FUNCTION_END(FunctionJuliabrotContour) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_post_transform.h0000644000175100017510000000444612100750300022303 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces for class FunctionPostTransform This class would normally live in functions.h (and is included and registered there), but is split out so it can be efficiently used by MutatableImageDisplay and EvolvotronMain. NB There is no class heirarchy here as all virtualisation and boilerplate services are supplied when the functions are plugged into the FunctionNode template. */ #ifndef _function_post_transform_h_ #define _function_post_transform_h_ #include "transform.h" //! Function class returning leaf node evaluated at given position; result is then transfomed by a 12-component linear transform. FUNCTION_BEGIN(FunctionPostTransform,12,1,false,0) //! Return the evaluation of arg(0) at the transformed position argument. virtual const XYZ evaluate(const XYZ& p) const { const Transform transform(params()); return transform.transformed(arg(0)(p)); } FUNCTION_END(FunctionPostTransform) #endif evolvotron/libfunction/functions_transform.h0000644000175100017510000001212412100750300021411 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_transform_h_ #define _functions_transform_h_ #include "transform.h" //------------------------------------------------------ //! Function class returning simply scaled position FUNCTION_BEGIN(FunctionIsotropicScale,1,0,false,0) //! Return the evaluation of arg(0) at the transformed position argument. virtual const XYZ evaluate(const XYZ& p) const { return param(0)*p; } FUNCTION_END(FunctionIsotropicScale) //------------------------------------------------------------------------------------------ //! Function class returning leaf node evaluated at position transfomed by a 12-component linear transform. /*! Unlike FunctionPreTransform, the basis vectors for the transform are not fixed but determined from leaf functions */ FUNCTION_BEGIN(FunctionPreTransformGeneralised,0,5,false,0) //! Return the evaluation of arg(0) at the transformed position argument. virtual const XYZ evaluate(const XYZ& p) const { const Transform transform(arg(1)(p),arg(2)(p),arg(3)(p),arg(4)(p)); return arg(0)(transform.transformed(p)); } FUNCTION_END(FunctionPreTransformGeneralised) //------------------------------------------------------------------------------------------ //! Function class returning leaf node evaluated at given position; result is then transfomed by a 12-component linear transform. /*! Unlike FunctionPostTransform, the basis vectors for the transform are not fixed but determined from leaf functions */ FUNCTION_BEGIN(FunctionPostTransformGeneralised,0,5,false,0) //! Return the evaluation of arg(0) at the transformed position argument. virtual const XYZ evaluate(const XYZ& p) const { const Transform transform(arg(1)(p),arg(2)(p),arg(3)(p),arg(4)(p)); return transform.transformed(arg(0)(p)); } FUNCTION_END(FunctionPostTransformGeneralised) //------------------------------------------------------------------------------------------ //! Transforms position transformed by a 30 paramter quadratic transform. /*! This used to be a core function but it doesn't look that great. */ FUNCTION_BEGIN(FunctionTransformQuadratic,30,0,false,0) //! Return p transformed. virtual const XYZ evaluate(const XYZ& p) const { const XYZ translate(param( 0),param( 1),param( 2)); const XYZ basis_x (param( 3),param( 4),param( 5)); const XYZ basis_y (param( 6),param( 7),param( 8)); const XYZ basis_z (param( 9),param(10),param(11)); const XYZ basis_xy (param(12),param(13),param(14)); const XYZ basis_xz (param(15),param(16),param(17)); const XYZ basis_yz (param(18),param(19),param(20)); const XYZ basis_xx (param(21),param(22),param(23)); const XYZ basis_yy (param(24),param(25),param(26)); const XYZ basis_zz (param(27),param(28),param(29)); return translate +basis_x*p.x()+basis_y*p.y()+basis_z*p.z() +basis_xy*(p.x()*p.y())+basis_xz*(p.x()*p.z())+basis_yz*(p.y()*p.z()) +basis_xx*(p.x()*p.x())+basis_yy*(p.y()*p.y())+basis_zz*(p.z()*p.z()); } FUNCTION_END(FunctionTransformQuadratic) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionRotate,0,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ a(arg(0)(p)*M_PI); const TransformRotateX rx(a.x()); const TransformRotateY ry(a.y()); const TransformRotateZ rz(a.z()); return rx*(ry*(rz*p)); } FUNCTION_END(FunctionRotate) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_gradient.h0000644000175100017510000001555012100750300021201 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_gradient_h_ #define _functions_gradient_h_ //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionDerivative,3,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ d(epsilon()*XYZ(param(0),param(1),param(2)).normalised()); const XYZ v0(arg(0)(p-d)); const XYZ v1(arg(0)(p+d)); return (v1-v0)*inv_epsilon2(); } FUNCTION_END(FunctionDerivative) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionDerivativeGeneralised,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ d(epsilon()*(arg(1)(p)).normalised()); const XYZ v0(arg(0)(p-d)); const XYZ v1(arg(0)(p+d)); return (v1-v0)*inv_epsilon2(); } FUNCTION_END(FunctionDerivativeGeneralised) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionGradient,3,1,false,0) //! Evaluate function. /*! Gradient converts scalar to vector, so need a scalar to work on. */ virtual const XYZ evaluate(const XYZ& p) const { const XYZ k(param(0),param(1),param(2)); const real vx0=k%arg(0)(p-XYZ(epsilon(),0.0,0.0)); const real vy0=k%arg(0)(p-XYZ(0.0,epsilon(),0.0)); const real vz0=k%arg(0)(p-XYZ(0.0,0.0,epsilon())); const real vx1=k%arg(0)(p+XYZ(epsilon(),0.0,0.0)); const real vy1=k%arg(0)(p+XYZ(0.0,epsilon(),0.0)); const real vz1=k%arg(0)(p+XYZ(0.0,0.0,epsilon())); return XYZ(vx1-vx0,vy1-vy0,vz1-vz0)*inv_epsilon2(); } FUNCTION_END(FunctionGradient) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionGradientGeneralised,0,2,false,0) //! Evaluate function. /*! Gradient converts scalar to vector, so need a scalar to work on. */ virtual const XYZ evaluate(const XYZ& p) const { const XYZ k(arg(1)(p)); const real vx0=k%arg(0)(p-XYZ(epsilon(),0.0,0.0)); const real vy0=k%arg(0)(p-XYZ(0.0,epsilon(),0.0)); const real vz0=k%arg(0)(p-XYZ(0.0,0.0,epsilon())); const real vx1=k%arg(0)(p+XYZ(epsilon(),0.0,0.0)); const real vy1=k%arg(0)(p+XYZ(0.0,epsilon(),0.0)); const real vz1=k%arg(0)(p+XYZ(0.0,0.0,epsilon())); return XYZ(vx1-vx0,vy1-vy0,vz1-vz0)*inv_epsilon2(); } FUNCTION_END(FunctionGradientGeneralised) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionDivergence,0,1,false,0) //! Evaluate function. /*! Divergence maps scalar to a scalar, so no problem doing vector->vector. */ virtual const XYZ evaluate(const XYZ& p) const { const XYZ vx0(arg(0)(p-XYZ(epsilon(),0.0,0.0))); const XYZ vy0(arg(0)(p-XYZ(0.0,epsilon(),0.0))); const XYZ vz0(arg(0)(p-XYZ(0.0,0.0,epsilon()))); const XYZ vx1(arg(0)(p+XYZ(epsilon(),0.0,0.0))); const XYZ vy1(arg(0)(p+XYZ(0.0,epsilon(),0.0))); const XYZ vz1(arg(0)(p+XYZ(0.0,0.0,epsilon()))); return (vx1-vx0+vy1-vy0+vz1-vz0)*inv_epsilon2(); } FUNCTION_END(FunctionDivergence) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionCurl,0,1,false,0) //! Evaluate function. /*! Curl maps vector to vector, which is what we want. */ virtual const XYZ evaluate(const XYZ& p) const { const XYZ vx0(arg(0)(p-XYZ(epsilon(),0.0,0.0))); const XYZ vy0(arg(0)(p-XYZ(0.0,epsilon(),0.0))); const XYZ vz0(arg(0)(p-XYZ(0.0,0.0,epsilon()))); const XYZ vx1(arg(0)(p+XYZ(epsilon(),0.0,0.0))); const XYZ vy1(arg(0)(p+XYZ(0.0,epsilon(),0.0))); const XYZ vz1(arg(0)(p+XYZ(0.0,0.0,epsilon()))); const XYZ d_dx((vx1-vx0)*inv_epsilon2()); const XYZ d_dy((vy1-vy0)*inv_epsilon2()); const XYZ d_dz((vz1-vz0)*inv_epsilon2()); const real dzdy=d_dy.z(); const real dydz=d_dz.y(); const real dxdz=d_dz.x(); const real dzdx=d_dx.z(); const real dydx=d_dx.y(); const real dxdy=d_dy.x(); return XYZ ( dzdy-dydz, dxdz-dzdx, dydx-dxdy ); } FUNCTION_END(FunctionCurl) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionScalarLaplacian,0,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { // Need to use a bigger baseline to avoid noise being amplified const XYZ vx0(arg(0)(p-XYZ(big_epsilon(),0.0,0.0))); const XYZ vy0(arg(0)(p-XYZ(0.0,big_epsilon(),0.0))); const XYZ vz0(arg(0)(p-XYZ(0.0,0.0,big_epsilon()))); const XYZ v(arg(0)(p)); const XYZ vx1(arg(0)(p+XYZ(big_epsilon(),0.0,0.0))); const XYZ vy1(arg(0)(p+XYZ(0.0,big_epsilon(),0.0))); const XYZ vz1(arg(0)(p+XYZ(0.0,0.0,big_epsilon()))); const XYZ dx0(v-vx0); const XYZ dy0(v-vy0); const XYZ dz0(v-vz0); const XYZ dx1(vx1-v); const XYZ dy1(vy1-v); const XYZ dz1(vz1-v); return XYZ(dx1-dx0+dy1-dy0+dz1-dz0)/(big_epsilon()*big_epsilon()); } FUNCTION_END(FunctionScalarLaplacian) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_tartan.h0000644000175100017510000001260412100750300020672 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Functions inspired by tartan patterns. */ #ifndef _functions_tartan_h_ #define _functions_tartan_h_ //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionTartanSelectFree,10,6,false,FnStructure) //! Evaluate function. /*! Sign of one 1D function's dot product determines one bit, ditto for another bit. 2 bits used to select from 4 possibilities. There's no guarantee of a repetitive pattern unless the generator functions are. */ virtual const XYZ evaluate(const XYZ& p) const { const XYZ p0(p.x(),param(0),param(1)); const XYZ p1(param(2),p.y(),param(3)); const XYZ d0(param(4),param(5),param(6)); const XYZ d1(param(7),param(8),param(9)); const int b0=(arg(0)(p0)%XYZ(d0)>0.0); const int b1=(arg(1)(p1)%XYZ(d1)>0.0); const int which=2+b0+2*b1; assert(2<=which && which<6); return arg(which)(p); } FUNCTION_END(FunctionTartanSelectFree) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionTartanSelect,14,6,false,FnStructure) //! Evaluate function. /*! Similar to function free except the generators repeat. */ virtual const XYZ evaluate(const XYZ& p) const { const real x=(param(0)>0.0 ? modulusf(p.x(),param(1)) : trianglef(p.x(),param(1))); const real y=(param(2)>0.0 ? modulusf(p.y(),param(3)) : trianglef(p.y(),param(3))); const XYZ p0(x,param(4),param(5)); const XYZ p1(param(6),y,param(7)); const XYZ d0(param(8),param(9),param(10)); const XYZ d1(param(11),param(12),param(13)); const int b0=(arg(0)(p0)%XYZ(d0)>0.0); const int b1=(arg(1)(p1)%XYZ(d1)>0.0); const int which=2+b0+2*b1; assert(2<=which && which<6); return arg(which)(p); } FUNCTION_END(FunctionTartanSelect) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionTartanSelectRepeat,14,6,false,FnStructure) //! Evaluate function. /*! Similar to above function except the invoked functions repeat too. */ virtual const XYZ evaluate(const XYZ& p) const { const real x=(param(0)>0.0 ? modulusf(p.x(),param(1)) : trianglef(p.x(),param(1))); const real y=(param(2)>0.0 ? modulusf(p.y(),param(3)) : trianglef(p.y(),param(3))); const XYZ p0(x,param(4),param(5)); const XYZ p1(param(6),y,param(7)); const XYZ d0(param(8),param(9),param(10)); const XYZ d1(param(11),param(12),param(13)); const int b0=(arg(0)(p0)%XYZ(d0)>0.0); const int b1=(arg(1)(p1)%XYZ(d1)>0.0); const int which=2+b0+2*b1; assert(2<=which && which<6); return arg(which)(XYZ(x,y,p.z())); } FUNCTION_END(FunctionTartanSelectRepeat) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionTartanMixFree,4,2,false,0) //! Evaluate function. /*! As above, but mix 2 functions. */ virtual const XYZ evaluate(const XYZ& p) const { const XYZ p0(p.x(),param(0),param(1)); const XYZ p1(param(2),p.y(),param(3)); const XYZ warp(arg(0)(p0)); const XYZ weft(arg(1)(p1)); return 0.5*(warp+weft); } FUNCTION_END(FunctionTartanMixFree) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionTartanMixRepeat,8,2,false,0) //! Evaluate function. /*! As above, but mix 2 functions. */ virtual const XYZ evaluate(const XYZ& p) const { const real x=(param(0)>0.0 ? modulusf(p.x(),param(1)) : trianglef(p.x(),param(1))); const real y=(param(2)>0.0 ? modulusf(p.y(),param(3)) : trianglef(p.y(),param(3))); const XYZ p0(x,param(4),param(5)); const XYZ p1(param(6),y,param(7)); const XYZ warp(arg(0)(p0)); const XYZ weft(arg(1)(p1)); return 0.5*(warp+weft); } FUNCTION_END(FunctionTartanMixRepeat) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/xy.h0000644000175100017510000001152712100750300015754 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class XY. */ #ifndef _xy_h_ #define _xy_h_ //! Class to hold vectors in 2D cartesian co-ordinates. /*! Direct access to the x,y members is not permitted. */ class XY { protected: boost::array _rep; public: //@{ //! Accessor. real x() const { return _rep[0]; } real y() const { return _rep[1]; } void x(real v) { _rep[0]=v; } void y(real v) { _rep[1]=v; } //@} //! Null constructor. /*! NB The components are not cleared to zero. */ XY() {} //! Copy constructor. XY(const XY& v) { _rep[0]=v._rep[0]; _rep[1]=v._rep[1]; } //! Initialise from separate components. XY(real vx,real vy) { _rep[0]=vx; _rep[1]=vy; } //! Trivial destructor. ~XY() {} //! Subtract a vector void operator-=(const XY& v) { _rep[0]-=v._rep[0]; _rep[1]-=v._rep[1]; } //! Add a vector void operator+=(const XY& v) { _rep[0]+=v._rep[0]; _rep[1]+=v._rep[1]; } //! Multiply by scalar void operator*=(real k) { _rep[0]*=k; _rep[1]*=k; } //! Divide by scalar. /*! Implemented assuming one divide and two multiplies is faster than two divides. */ void operator/=(real k) { const real ik(1.0/k); (*this)*=ik; } //! Assignment. void assign(const XY& v) { x(v.x()); y(v.y()); } //! Negation. const XY operator-() const { return XY(-x(),-y()); } //! Return the square of the magnitude. real magnitude2() const { return x()*x()+y()*y(); } //! Return the magnitude. real magnitude() const { return sqrt(magnitude2()); } //! Returns sum of x and y components. real sum_of_components() const { return x()+y(); } //! Return the vector normalised. const XY normalised() const; //! Normalise this vector. void normalise(); //! Returns true if an origin centred rectangle with this vectors' semi-axes contains the argument. bool origin_centred_rect_contains(const XY& p) const { return (-x()<=p.x() && p.x()<=x() && -y()<=p.y() && p.y()<=y()); } //! Write the vector. std::ostream& write(std::ostream&) const; //! Helper for common case of creating an instance filled with a common value. static const XY fill(real v) { return XY(v,v); } }; //! Dot product. /*! Perhaps a curious choice of operator but it works for me. */ inline real operator%(const XY& a,const XY& b) { return a.x()*b.x()+a.y()*b.y(); } //! Vector addition. inline const XY operator+(const XY& a,const XY& b) { return XY(a.x()+b.x(),a.y()+b.y()); } //! Vector subtraction. inline const XY operator-(const XY& a,const XY& b) { return XY(a.x()-b.x(),a.y()-b.y()); } //! Multiplication by scalar. inline const XY operator*(real k,const XY& v) { XY ret(v); ret*=k; return ret; } //! Multiplication by scalar. inline const XY operator*(const XY& v,real k) { XY ret(v); ret*=k; return ret; } //! Division by scalar. inline const XY operator/(const XY& v,real k) { return v*(1.0/k); } /*! If magnitude is zero we return zero vector. */ inline const XY XY::normalised() const { const real m=magnitude(); return (m==0.0 ? XY(0.0,0.0) : (*this)/m); } inline void XY::normalise() { (*this)=normalised(); } //! Stream output operator. /*! Calls write(). */ inline std::ostream& operator<<(std::ostream& out,const XY& v) { return v.write(out); } #endif evolvotron/libfunction/transform.h0000644000175100017510000001231412100750300017322 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class Transform. */ #ifndef _transform_h_ #define _transform_h_ //! Class representing 3d linear transforms. /*! Not much functionality currently because is used mainly to pass info around for warp functionality */ class Transform { public: //! Default constructor. NB Doesn't set up identity or anything. Transform(); //! Copy constructor. Transform(const Transform&); //! Constructor specifying column vectors. Transform(const XYZ& t,const XYZ& x,const XYZ& y,const XYZ& z); //! Constructor specifying column-wise elements. Transform(const std::vector& v,uint starting_element=0); //! virtual destructor in case of extension virtual ~Transform(); //@{ //! Accessor const XYZ& translate() const { return _translate; } const XYZ& basis_x() const { return _basis_x; } const XYZ& basis_y() const { return _basis_y; } const XYZ& basis_z() const { return _basis_z; } void translate(const XYZ &t) { _translate=t; } void basis_x(const XYZ &x) { _basis_x=x; } void basis_y(const XYZ &y) { _basis_y=y; } void basis_z(const XYZ &z) { _basis_z=z; } //@} //! Get column-wise element values as a vector const std::vector get_columns() const; //! Transform a point const XYZ transformed(const XYZ& p) const; //! Transform a point with no translation const XYZ transformed_no_translate(const XYZ& p) const; //! Concatenate transforms Transform& concatenate_on_right(const Transform& t); //! Concatenate transforms Transform& concatenate_on_left(const Transform& t); protected: //@{ //! Translation component (column vector in matrix). XYZ _translate; XYZ _basis_x; XYZ _basis_y; XYZ _basis_z; }; inline const XYZ operator*(const Transform& t,const XYZ& p) { return t.basis_x()*p.x() +t.basis_y()*p.y() +t.basis_z()*p.z() +t.translate(); } inline std::ostream& operator<<(std::ostream& out,const Transform& t) { return out << t.translate() << ";" << t.basis_x() << "," << t.basis_y() << "," << t.basis_z(); } class TransformIdentity : public Transform { public: TransformIdentity() { translate(XYZ(0.0,0.0,0.0)); basis_x(XYZ(1.0,0.0,0.0)); basis_y(XYZ(0.0,1.0,0.0)); basis_z(XYZ(0.0,0.0,1.0)); } }; class TransformTranslate : public Transform { public: TransformTranslate(const XYZ& t) { translate(t); basis_x(XYZ(1.0,0.0,0.0)); basis_y(XYZ(0.0,1.0,0.0)); basis_z(XYZ(0.0,0.0,1.0)); } }; class TransformScale : public Transform { public: TransformScale(const XYZ& s) { translate(XYZ(0.0,0.0,0.0)); basis_x(XYZ(s.x(),0.0,0.0)); basis_y(XYZ(0.0,s.y(),0.0)); basis_z(XYZ(0.0,0.0,s.z())); } TransformScale(real s) { translate(XYZ(0.0,0.0,0.0)); basis_x(XYZ(s,0.0,0.0)); basis_y(XYZ(0.0,s,0.0)); basis_z(XYZ(0.0,0.0,s)); } }; class TransformRotateX : public Transform { public: TransformRotateX(real a) { const real sa=sin(a); const real ca=cos(a); translate(XYZ(0.0,0.0,0.0)); basis_x(XYZ(1.0,0.0,0.0)); basis_y(XYZ(0.0, ca , sa )); basis_z(XYZ(0.0,-sa , ca )); } }; class TransformRotateY : public Transform { public: TransformRotateY(real a) { const real sa=sin(a); const real ca=cos(a); translate(XYZ(0.0,0.0,0.0)); basis_x(XYZ( ca ,0.0,-sa )); basis_y(XYZ(0.0,1.0,0.0)); basis_z(XYZ( sa ,0.0, ca )); } }; class TransformRotateZ : public Transform { public: TransformRotateZ(real a) { const real sa=sin(a); const real ca=cos(a); translate(XYZ(0.0,0.0,0.0)); basis_x(XYZ( ca , sa ,0.0)); basis_y(XYZ(-sa , ca ,0.0)); basis_z(XYZ(0.0,0.0,1.0)); } }; #endif evolvotron/libfunction/mutation_parameters.h0000644000175100017510000002637112100750300021402 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class MutationParameters. */ #ifndef _mutation_parameters_h_ #define _mutation_parameters_h_ #include "random.h" class FunctionNode; class FunctionRegistration; class FunctionRegistry; //! Class encapsulating mutation parameters. /*! For example, magnitude of variations, probability of leaves being dropped. Also provides a random number generator. */ class MutationParameters { private: const std::auto_ptr _function_registry; protected: //! A random number generator. /*! Declared mutable so we can pass const MutationParameters& around and still do useful work with it. */ mutable Random01 _r01; //! Negative-exponential generator might be useful too. mutable RandomNegExp _r_negexp; //! Specifies the base magnitude of random changes the function parameters. real _base_magnitude_parameter_variation; //! Specifies the base probability of a the parameter set being completely reset. real _base_probability_parameter_reset; //! Specifies the base probability of a child being dropped and replaced with a new random stub. real _base_probability_glitch; //! Specifies the base probability of all child nodes being reordered. real _base_probability_shuffle; //! Specifies the base probability of a random stub being inserted before a child. real _base_probability_insert; //! Specifies the base probability of a node being replaced with an alternate type. real _base_probability_substitute; //! Specifies the proportion of basic node types. real _proportion_basic; //! Specifies the proportion of Constant nodes vs Position type nodes. real _proportion_constant; //! Specifies the probability of a using a FunctionNodePositionTransformed instead of FunctionNodePosition real _identity_supression; //! The maximum number of iterations an iterative function node can have initially. uint _max_initial_iterations; //! The base probability of the number of iterations changing by plus or minus 1. real _base_probability_iterations_change_step; //! The base probability of the number of iterations changing by times or divide 2. real _base_probability_iterations_change_jump; //! Individual weighting modifiers for each function type /*! Will only be applied to random functions we're asked for. The bulk of nodes are created by FunctionNode and are boring to keep the branching ratio down. \todo Implement a branching ratio query method. */ std::map _function_weighting; //! Total of function weights, for normalisation. real _function_weighting_total; //! Map from [0,1] to a function registration, taking weights into account. std::map _function_pick; //! What state a reset should return autocool to. const bool _autocool_reset_state; //! Whether autocooling is being applied. bool _autocool_enable; //! Number of generations at which parameters will be half cooled. uint _autocool_halflife; //! Count of number of generations for decay cooling. uint _autocool_generations; //! Just use SingleChannelNoise for almost all functions (useful for debugging). const bool _debug_mode; void recalculate_function_stuff(); public: //! Trivial constructor. MutationParameters(uint seed,bool ac,bool debug_mode); //! Trivial destructor. virtual ~MutationParameters(); //! Accessor. const FunctionRegistry& function_registry() const { return *_function_registry; } //! Reset to initial values. void reset(); //! Multiply most parameters by the given factor void general_cool(real f); //! Returns a reference to the random number generator. /*! Need this for e.g RandomXYZInSphere constructor. */ Random01& rng01() const { return _r01; } //! Return a number in the range [0,1) real r01() const { return _r01(); } real rnegexp() const { return _r_negexp(); } //! Accessor, with decay. real effective_magnitude_parameter_variation() const { return base_magnitude_parameter_variation()*decay_factor(); } //! Accessor. real base_magnitude_parameter_variation() const { return _base_magnitude_parameter_variation; } //! Accessor. void base_magnitude_parameter_variation(real v) { _base_magnitude_parameter_variation=v; report_change(); } //! Accessor, with decay. real effective_probability_parameter_reset() const { return base_probability_parameter_reset()*decay_factor(); } //! Accessor. real base_probability_parameter_reset() const { return _base_probability_parameter_reset; } //! Accessor. void base_probability_parameter_reset(real v) { _base_probability_parameter_reset=v; report_change(); } //! Accessor, with decay. real effective_probability_glitch() const { return base_probability_glitch()*decay_factor(); } //! Accessor. real base_probability_glitch() const { return _base_probability_glitch; } //! Accessor. void base_probability_glitch(real v) { _base_probability_glitch=v; report_change(); } //! Accessor, with decay. real effective_probability_shuffle() const { return base_probability_shuffle()*decay_factor(); } //! Accessor. real base_probability_shuffle() const { return _base_probability_shuffle; } //! Accessor. void base_probability_shuffle(real v) { _base_probability_shuffle=v; report_change(); } //! Accessor, with decay. real effective_probability_insert() const { return base_probability_insert()*decay_factor(); } //! Accessor. real base_probability_insert() const { return _base_probability_insert; } //! Accessor. void base_probability_insert(real v) { _base_probability_insert=v; report_change(); } //! Accessor. real effective_probability_substitute() const { return base_probability_substitute()*decay_factor(); } //! Accessor. real base_probability_substitute() const { return _base_probability_substitute; } //! Accessor. void base_probability_substitute(real v) { _base_probability_substitute=v; report_change(); } //! Accessor. real proportion_constant() const { return _proportion_constant; } //! Accessor. void proportion_constant(real v) { _proportion_constant=v; report_change(); } //! Accessor. real identity_supression() const { return _identity_supression; } //! Accessor. void identity_supression(real v) { _identity_supression=v; report_change(); } //! Accessor. uint max_initial_iterations() const { return _max_initial_iterations; } //! Accessor. void max_initial_iterations(uint v) { _max_initial_iterations=v; report_change(); } //! Accessor, with decay. real effective_probability_iterations_change_step() const { return base_probability_iterations_change_step()*decay_factor(); } //! Accessor. real base_probability_iterations_change_step() const { return _base_probability_iterations_change_step; } //! Accessor. void base_probability_iterations_change_step(real v) { _base_probability_iterations_change_step=v; report_change(); } //! Accessor, with decay. real effective_probability_iterations_change_jump() const { return base_probability_iterations_change_jump()*decay_factor(); } //! Accessor. real base_probability_iterations_change_jump() const { return _base_probability_iterations_change_jump; } //! Accessor. void base_probability_iterations_change_jump(real v) { _base_probability_iterations_change_jump=v; report_change(); } //! Accessor. real proportion_basic() const { return _proportion_basic; } //! Accessor. void proportion_basic(real p) { _proportion_basic=p; report_change(); } //! Accessor. bool autocool_enable() const { return _autocool_enable; } //! Accessor. void autocool_enable(bool v) { _autocool_enable=v; std::clog << "Autocooling " << (autocool_enable() ? "ON" : "OFF") << "\n"; report_change(); } //! Accessor. int autocool_halflife() const { return _autocool_halflife; } //! Accessor. void autocool_halflife(int v) { _autocool_halflife=v; report_change(); } //! Accessor int autocool_generations() const { return _autocool_generations; } //! Accessor. void autocool_generations(int v) { _autocool_generations=v; report_change(); } //! Accessor. void autocool_generations_increment() { _autocool_generations++; report_change(); } //! Calculate branching ratio for above calls /* Call user should be checking this and diluting with boring nodes to keep it under control */ real random_function_branching_ratio() const; //! This returns a new random bit of tree. /*! Setting the "exciting" flag avoids the most basic node types, but only at the top level of the stub tree. */ std::auto_ptr random_function_stub(bool exciting) const; void change_function_weighting(const FunctionRegistration* fn,real w); void randomize_function_weightings_for_classifications(uint classification_mask); real get_weighting(const FunctionRegistration* fn); protected: //! Compute current decay factor real decay_factor() const; //! Return a random function appropriately biased by current settings std::auto_ptr random_function() const; //! Return a random function registration, appropriately biased by current settings const FunctionRegistration* random_weighted_function_registration() const; //! Intended for Qt-world subclass to override to emit signal. virtual void report_change(); }; #endif evolvotron/libfunction/functions_friezegroup_hop.h0000644000175100017510000000745512100750300022620 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_friezegroup_hop_h_ #define _functions_friezegroup_hop_h_ #include "friezegroup.h" //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupHopFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Hop(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupHopFreeZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupHopClampZ,1,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Hop(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupHopClampZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupHopBlendClampZ,1,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupBlend(arg(0),arg(1),p,HopBlend(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupHopBlendClampZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupHopBlendFreeZ,0,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupBlend(arg(0),arg(1),p,HopBlend(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupHopBlendFreeZ) //------------------------------------------------------------------------------------------ /* FUNCTION_BEGIN(FunctionFriezeGroupHopCutClampZ,2,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { const int d=FriezegroupCut(arg(1),p,HopCut(1.0),ClampZ(param(1))); return FriezegroupEvaluate(arg(0),p,Hop(1.0,d),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupHopCutClampZ) */ //------------------------------------------------------------------------------------------ /* FUNCTION_BEGIN(FunctionFriezeGroupHopCutFreeZ,0,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { const int d=FriezegroupCut(arg(1),p,HopCut(1.0),FreeZ()); return FriezegroupEvaluate(arg(0),p,Hop(1.0,d),FreeZ()); } FUNCTION_END(FunctionFriezeGroupHopCutFreeZ) */ //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_shadow.h0000644000175100017510000000463112100750300020667 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_shadow_h_ #define _functions_shadow_h_ //------------------------------------------------------------------------------------------ //! Sum of two evaluations of a function, one sampled at a constant offset and weighted. FUNCTION_BEGIN(FunctionShadow,4,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(0)(p)+param(3)*arg(0)(p+XYZ(param(0),param(1),param(2))); } FUNCTION_END(FunctionShadow) //------------------------------------------------------------------------------------------ //! Like FunctionShadow but the offset is obtained from a function. FUNCTION_BEGIN(FunctionShadowGeneralised,1,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(0)(p)+param(0)*arg(0)(p+arg(1)(p)); } FUNCTION_END(FunctionShadowGeneralised) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_boilerplate_instantiate.h0000644000175100017510000000367612100750300024134 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Modifications to function_boilerplate macros. Include this in function .cpp files before the header is included. (This used to be simulated by putting #define INSTANTIATE_FN in front of function_boilerplate.h, but we wanted function_boilerplate.h to go in precompiled header. */ #ifndef _function_boilerplate_instantiate_h_ #define _function_boilerplate_instantiate_h_ #undef FUNCTION_END //! Replace definition to obtain concrete implementations #define FUNCTION_END(FN) };FN_CTOR_IMP(FN);FN_DTOR_IMP(FN);FN_VNAME_IMP(FN);FN_SNAME_IMP(FN);REGISTER_IMP(FN); #endif evolvotron/libfunction/functions_friezegroup_sidle.h0000644000175100017510000000450612100750300023124 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_friezegroup_sidle_h_ #define _functions_friezegroup_sidle_h_ #include "friezegroup.h" //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSidleFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Sidle(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupSidleFreeZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSidleClampZ,1,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Sidle(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupSidleClampZ) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_compose_triple.h0000644000175100017510000000376612100750300022253 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for FunctionComposeTriple */ #ifndef _function_compose_triple_h_ #define _function_compose_triple_h_ FUNCTION_BEGIN(FunctionComposeTriple,0,3,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(2)(arg(1)(arg(0)(p))); } //! Is constant if any (rather than default "all") function is constant. /*! One of the few cases it's worth overriding this method */ virtual bool is_constant() const { return (arg(0).is_constant() || arg(1).is_constant() || arg(2).is_constant()); } FUNCTION_END(FunctionComposeTriple) #endif evolvotron/libfunction/libfunction_precompiled.h0000644000175100017510000000331112100750300022203 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Precompiled header for libfunction */ #ifndef _libfunction_precompiled_h_ #define _libfunction_precompiled_h_ // Ordering is important here because all headers assume all precompiled headers preceed them. #include "useful.h" #include "xy.h" #include "xyz.h" #include "function_node.h" #include "function_boilerplate.h" #endif evolvotron/libfunction/function_node.h0000644000175100017510000002020012100750300020132 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces for class FunctionNode and derived classes. */ #ifndef _function_node_h_ #define _function_node_h_ class FunctionNodeInfo; class FunctionTop; class FunctionPreTransform; class FunctionPostTransform; class FunctionRegistry; class MutatableImage; class MutationParameters; class Function : boost::noncopyable { public: virtual ~Function() {} //! Convenience wrapper for evaluate (actually, evaluate is protected so can't be called externally anyway) const XYZ operator()(const XYZ& p) const { return evaluate(p); } //! Weighted evaluate; fastpath for zero weight. const XYZ operator()(const real weight,const XYZ& p) const { return (weight==0.0 ? XYZ(0.0,0.0,0.0) : weight*evaluate(p)); } //! This what distinguishes different types of function. virtual const XYZ evaluate(const XYZ&) const =0; }; //! Abstract base class for all kinds of mutatable image node. /*! MutatableImage declared a friend to help constification of the public accessors. */ class FunctionNode : public Function { public: friend class MutatableImage; private: //! The arguments (ie child nodes) for this node. boost::ptr_vector _args; //! The parameters (ie constant values) for this node. std::vector _params; //! Number of iterations for iterative function types. If zero, indicates non-iterative function. /*! \todo Perhaps someday push this out into a derived class. */ uint _iterations; protected: //! This returns a deep-cloned copy of the node's children. std::auto_ptr > cloneargs() const; //! This returns a copy of the node's parameters const std::vector cloneparams() const; //! Obtain some statistics about the image function void get_stats(uint& total_nodes,uint& total_parameters,uint& depth,uint& width,real& proportion_constant) const; //! Check function info against given number of parameters/arguments/iterative-flag. /*! Return true on success, false on fail with reasons in report string. Mainly for use by derived FunctionBoilerplate template to avoid duplicate code proliferation. */ static bool verify_info(const FunctionNodeInfo& info,unsigned int np,unsigned int na,bool it,std::string& report); //! Build argument list. /*! Return true on success, false on fail with reasons in report string. Mainly for use by derived FunctionBoilerplate template to avoid duplicate code proliferation. */ static bool create_args(const FunctionRegistry&,const FunctionNodeInfo& info,boost::ptr_vector& args,std::string& report); public: //! Returns true if the function is independent of it's position argument. /*! This isn't used for optimisation (which would require FunctionNode to have computation-specific state, which would wreck plans for reference counted deepclone()), but to cull boring constant images on creation. Default implementation (and probably the only sensible one) is constant if all args are constant; no args returns false. */ virtual bool is_constant() const; //! Internal self consistency check. virtual bool ok() const; //! Bits give some classification of the function type virtual uint self_classification() const =0; //@{ //! Query the node as to whether it is a FunctionTop (return null if not). virtual const FunctionTop* is_a_FunctionTop() const; virtual FunctionTop* is_a_FunctionTop(); //@} //! This returns a new random bit of tree. Setting the "exciting" flag avoids basic node types, but only at the top level of the stub tree. static std::auto_ptr stub(const MutationParameters& parameters,bool exciting); //! This returns a vector of random parameter values. static void stubparams(std::vector&,const MutationParameters& parameters,uint n); //! This returns a vector of new random bits of tree. static void stubargs(boost::ptr_vector&,const MutationParameters& parameters,uint n,bool exciting=false); //! Return a suitable starting value for a node's iteration count (assuming it's iterative). static uint stubiterations(const MutationParameters& parameters); //! Constructor given an array of params and args and an iteration count. /*! These MUST be provided; there are no alterative constructors. */ FunctionNode(const std::vector& p,boost::ptr_vector& a,uint iter); //! Build a FunctionNode given a description static std::auto_ptr create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report); //! Destructor. virtual ~FunctionNode(); //! Accessor void params(const std::vector& p) { _params=p; } //! Accessor. const std::vector& params() const { return _params; } //! Accessor. real param(uint n) const { assert(n& args() const { return _args; } //! Accessor. void args(boost::ptr_vector& a) { _args=a.release(); } //! Accessor. const FunctionNode& arg(uint n) const { assert(n deepclone() const =0; //! Prune any is_constant() nodes and replace them with an actual constant node virtual void simplify_constants(); //! Return a deepcloned copy of the node's arguments virtual std::auto_ptr > deepclone_args() const; //! Save the function tree. virtual std::ostream& save_function(std::ostream& out,uint indent) const =0; protected: //! Save the function tree. Common code needing a function name. std::ostream& save_function(std::ostream& out,uint indent,const std::string& function_name) const; //! Accessor (non-const). boost::ptr_vector& args() { return _args; } //! Accessor (non-const). std::vector& params() { return _params; } //! Accessor. FunctionNode& arg(uint n) { assert(n. */ /**************************************************************************/ /*! \file \brief Interface for class XYZ. */ #ifndef _xyz_h_ #define _xyz_h_ class Random01; //! Class to hold vectors in 3D cartesian co-ordinates. /*! Direct access to the x,y,z members is not permitted. */ class XYZ { protected: boost::array _rep; public: //@{ //! Accessor. real x() const { return _rep[0]; } real y() const { return _rep[1]; } real z() const { return _rep[2]; } const XY xy() const { return XY(x(),y()); } void x(real v) { _rep[0]=v; } void y(real v) { _rep[1]=v; } void z(real v) { _rep[2]=v; } //@} //! Null constructor. /*! NB The components are not cleared to zero. */ XYZ() {} //! Copy constructor. XYZ(const XYZ& v) { _rep[0]=v._rep[0]; _rep[1]=v._rep[1]; _rep[2]=v._rep[2]; } //! Initialise from an XY and a z component. XYZ(const XY& p,real vz) { _rep[0]=p.x(); _rep[1]=p.y(); _rep[2]=vz; } //! Initialise from separate components. XYZ(real vx,real vy,real vz) { _rep[0]=vx; _rep[1]=vy; _rep[2]=vz; } //! Trivial destructor. ~XYZ() {} //! Subtract a vector void operator-=(const XYZ& v) { _rep[0]-=v._rep[0]; _rep[1]-=v._rep[1]; _rep[2]-=v._rep[2]; } //! Add a vector void operator+=(const XYZ& v) { _rep[0]+=v._rep[0]; _rep[1]+=v._rep[1]; _rep[2]+=v._rep[2]; } //! Multiply by scalar void operator*=(real k) { _rep[0]*=k; _rep[1]*=k; _rep[2]*=k; } //! Divide by scalar. /*! Implemented assuming one divide and three multiplies is faster than three divides. */ void operator/=(real k) { const real ik(1.0/k); (*this)*=ik; } //! Assignment. void assign(const XYZ& v) { x(v.x()); y(v.y()); z(v.z()); } //! Negation. const XYZ operator-() const { return XYZ(-x(),-y(),-z()); } //! Return the square of the magnitude. real magnitude2() const { return x()*x()+y()*y()+z()*z(); } //! Return the magnitude. real magnitude() const { return sqrt(magnitude2()); } //! Returns sum of x, y and z components. real sum_of_components() const { return x()+y()+z(); } //! Return the vector normalised. const XYZ normalised() const; //! Normalise this vector. void normalise(); //! Returns true if an origin centred cuboid with this vectors semi-axes contains the argument. bool origin_centred_rect_contains(const XYZ& p) const { return (-x()<=p.x() && p.x()<=x() && -y()<=p.y() && p.y()<=y() && -z()<=p.z() && p.z()<=z()); } //! Write the vector. std::ostream& write(std::ostream&) const; //! Helper for common case of creating an instance filled with a common value. static const XYZ fill(real v) { return XYZ(v,v,v); } }; //! Cross product. inline const XYZ operator*(const XYZ& a,const XYZ& b) { return XYZ( a.y()*b.z()-a.z()*b.y(), a.z()*b.x()-a.x()*b.z(), a.x()*b.y()-a.y()*b.x() ); } //! Dot product. /*! Perhaps a curious choice of operator but it works for me. */ inline real operator%(const XYZ& a,const XYZ& b) { return a.x()*b.x()+a.y()*b.y()+a.z()*b.z(); } //! Vector addition. inline const XYZ operator+(const XYZ& a,const XYZ& b) { return XYZ(a.x()+b.x(),a.y()+b.y(),a.z()+b.z()); } //! Vector subtraction. inline const XYZ operator-(const XYZ& a,const XYZ& b) { return XYZ(a.x()-b.x(),a.y()-b.y(),a.z()-b.z()); } //! Multiplication by scalar. inline const XYZ operator*(real k,const XYZ& v) { XYZ ret(v); ret*=k; return ret; } //! Multiplication by scalar. inline const XYZ operator*(const XYZ& v,real k) { XYZ ret(v); ret*=k; return ret; } //! Division by scalar. inline const XYZ operator/(const XYZ& v,real k) { return v*(1.0/k); } //! Modulus all components by 1.0 inline const XYZ modulusf(const XYZ& p) { return XYZ ( modulusf(p.x(),1.0), modulusf(p.y(),1.0), modulusf(p.z(),1.0) ); } //! Componentwise modulus inline const XYZ modulusf(const XYZ& p,const XYZ& q) { return XYZ ( modulusf(p.x(),q.x()), modulusf(p.y(),q.y()), modulusf(p.z(),q.z()) ); } /*! If magnitude is zero we return zero vector. */ inline const XYZ XYZ::normalised() const { const real m=magnitude(); return (m==0.0 ? XYZ(0.0,0.0,0.0) : (*this)/m); } inline void XYZ::normalise() { (*this)=normalised(); } //! Stream output operator. /*! Calls write(). */ inline std::ostream& operator<<(std::ostream& out,const XYZ& v) { return v.write(out); } //! Generates a random point in the cube bounded by (0,0,0) and (1.0,1.0,1.0) class RandomXYZInUnitCube : public XYZ { public: //! Constructor. RandomXYZInUnitCube(Random01&); }; //! Generates random points in a recnangular box centred on the origin class RandomXYZInBox : public XYZ { public: //! Constructor. RandomXYZInBox(Random01& rng,const XYZ& bounds); }; //! Generates a random point in or on a unit-radius sphere centred on the origin. class RandomXYZInSphere : public XYZ { public: //! Constructor. RandomXYZInSphere(Random01& rng,real radius); }; //! Generates a random point on the surface of a unit-radius sphere class RandomXYZSphereNormal : public XYZ { public: //! Constructor. RandomXYZSphereNormal(Random01& rng); }; //! Generates a random point in or on an origin-centred ellipsoid with semi-axes of the specified size. class RandomXYZInEllipsoid : public XYZ { public: //! Constructor. RandomXYZInEllipsoid(Random01& rng,const XYZ& axes); }; //! Generates a random point in or on a disc in the XY plane of the specified radius. class RandomXYZInXYDisc : public XYZ { public: //! Constructor. RandomXYZInXYDisc(Random01& rng,real radius); }; #endif evolvotron/libfunction/margin.h0000644000175100017510000000361512100750300016570 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class Margin */ #ifndef _margin_h_ #define _margin_h_ //! Utility class for outputting the margin for a given level of indentation. class Margin { //! Levels of indentation const uint _n; public: //! Constructor. Margin(uint n) :_n(n) {} //! Output some spaces for each level of indentation. std::ostream& write(std::ostream& out) const; }; //! Make Margin usable using << operator. inline std::ostream& operator<<(std::ostream& out,const Margin& m) { return m.write(out); } #endif evolvotron/libfunction/function_identity.h0000644000175100017510000000401612100750300021045 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for certain core Function classes. Split out from functions.h as included in mutation_parameters.cpp */ #ifndef _function_identity_h_ #define _function_identity_h_ //------------------------------------------------------------------------------------------ //! Function class simply returning the position argument. FUNCTION_BEGIN(FunctionIdentity,0,0,false,FnCore) //! Simply return the position argument. virtual const XYZ evaluate(const XYZ& p) const { return p; } FUNCTION_END(FunctionIdentity) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_filter.h0000644000175100017510000001600312100750300020663 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_filter_h_ #define _functions_filter_h_ //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFilter2D,2,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(0)(p) -( arg(0)(p+XYZ(param(0),0.0,0.0)) +arg(0)(p+XYZ(-param(0),0.0,0.0)) +arg(0)(p+XYZ(0.0,param(1),0.0)) +arg(0)(p+XYZ(0.0,-param(1),0.0)) )/4.0; } FUNCTION_END(FunctionFilter2D) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFilter3D,3,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(0)(p) -( arg(0)(p+XYZ(param(0),0.0,0.0)) +arg(0)(p+XYZ(-param(0),0.0,0.0)) +arg(0)(p+XYZ(0.0,param(1),0.0)) +arg(0)(p+XYZ(0.0,-param(1),0.0)) +arg(0)(p+XYZ(0.0,0.0,param(2))) +arg(0)(p+XYZ(0.0,0.0,-param(2))) )/6.0; } FUNCTION_END(FunctionFilter3D) //------------------------------------------------------------------------------------------ //! Function returning average value of evenly spaced samples between two points FUNCTION_BEGIN(FunctionAverageSamples,3,1,true,FnIterative) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ baseline(param(0),param(1),param(2)); XYZ p0; XYZ p1; XYZ delta; if (iterations()==1) { p0=p; p1=p; delta=XYZ(0.0,0.0,0.0); } else { // In the case of two iterations the samples will be at p0 and p1 p0=p-baseline; p1=p+baseline; delta=(p1-p0)/(iterations()-1); } XYZ ret(0.0,0.0,0.0); XYZ ps=p0; for (uint i=0;i(i)/iterations(); ret+=k*arg(0)(ps); w+=k; ps+=delta; } ret/=w; return ret; } FUNCTION_END(FunctionStreak) //------------------------------------------------------------------------------------------ //! Average of samples around a ring FUNCTION_BEGIN(FunctionAverageRing,1,1,true,FnIterative) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { if (iterations()==1) return arg(0)(p); const real da=2.0*M_PI/iterations(); XYZ ret(0.0,0.0,0.0); for (uint i=0;i. */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_geometry_h_ #define _functions_geometry_h_ //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionCross,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ v0(arg(0)(p)); const XYZ v1(arg(1)(p)); return v0*v1; } FUNCTION_END(FunctionCross) //------------------------------------------------------------------------------------------ //! Invert the leaf function using a radius-one origin centred sphere. FUNCTION_BEGIN(FunctionGeometricInversion,0,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real radius2=p.magnitude2(); const XYZ ip(p/radius2); return arg(0)(ip); } FUNCTION_END(FunctionGeometricInversion) //------------------------------------------------------------------------------------------ //! Implements reflection of sampling point about a plane FUNCTION_BEGIN(FunctionReflect,0,3,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ pt_in_plane(arg(0)(p)); const XYZ normal(arg(1)(p).normalised()); XYZ pos(arg(2)(p)); const real distance_from_plane=(pos-pt_in_plane)%normal; // If pos is on the wrong side of the plane, reflect it over // Check: normal (0,0,1), pos (0,0,-1) => distance -1, pos-=(2*-1)*(0,0,1) => pos-=(0,0,-2) if (distance_from_plane<0.0) { pos-=(2.0*distance_from_plane)*normal; } return pos; } FUNCTION_END(FunctionReflect) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/friezegroup.h0000644000175100017510000002457112100750300017660 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for friezegroup related code. */ #ifndef _friezegroup_h_ #define _friezegroup_h_ //! Functor implementing a pass-through Z coordinate policy struct FreeZ { float operator()(float z) const { return z; } }; //! Functor implementing a clamping Z coordinate policy struct ClampZ { ClampZ(float z) :_z(z) {} float operator()(float) const { return _z; } private: const float _z; }; //! Function evaluation via symmetry. template inline const XYZ FriezegroupEvaluate ( const Function& f,const XYZ& p,const SYMMETRY& sym,const ZPOLICY& zpol ) { return f(XYZ(sym(p.xy()),zpol(p.z()))); } //! Function evaluation with blending. /*! NB Is symmetry unaware; blend must have already reduced points to base domain. */ template inline const XYZ FriezegroupBlend ( const Function& f0,const Function& f1,const XYZ& p,const BLEND& blend,const ZPOLICY& zpol ) { const boost::tuple b(blend(p.xy())); return b.get<0>() *f0(XYZ(b.get<1>(),zpol(p.z()))) +(1.0-b.get<0>())*f1(XYZ(b.get<2>(),zpol(p.z()))); } template inline const XYZ FriezegroupBlend ( const Function& f,const XYZ& p,const BLEND& blend,const ZPOLICY& zpol ) { return FriezegroupBlend(f,f,p,blend,zpol); } //! Generate domain shift for when cutting. /*! This function actually far too specific to Hop and Jump, so move into their Cut functions as done for SpinhopCut */ /* template inline const int FriezegroupCut ( const Function& f,const XYZ& p,const CUT& cut,const ZPOLICY& zpol ) { const XY pc(cut(p.xy())); const real k=tanh(f(XYZ(pc,zpol(p.z()))).sum_of_components()); const real t=pc.x()/(0.5*cut.width()); // -1 to +1 over domain used for cut function (should be in -width/2 to +width/2) if (pc.x()<0.0 && k=0.0 && k>t) return 1; else return 0; } */ //------------------------------------------------------------------------------------------ struct Friezegroup { Friezegroup(real width) :_width(width) { assert(_width>0.0f); } real width() const { return _width; } private: const real _width; }; //------------------------------------------------------------------------------------------ //! Hop (Conway p111): no reflections or rotation. /*! Just have to cycle x range. \verbatim o o o --- --- --- \endverbatim Domain is over (-width/2,width/2), centred on zero. Default domain we use -0.5 to +0.5 to see symmetry at default sort of zoom. */ struct Hop : public Friezegroup { Hop(real width,int domain=0) :Friezegroup(width) ,_domain(domain) {} const XY operator()(const XY& p) const { return XY ( (_domain-0.5)*width()+modulusf(p.x()-0.5*width(),width()), p.y() ); } private: const int _domain; }; //! Constructs two points and a blending weight which will behave sensibly for Hop. /*! The additional point is half a domain width away. The blend weight is the weight of the primary point, should be maximum in the centre of the domain (0) and zero at the edges +/-0.5*width */ struct HopBlend : public Friezegroup // subclassing doesn't make much sense really { HopBlend(real width) :Friezegroup(width) {} const boost::tuple operator()(const XY& p) const { const Hop hop(width()); return boost::tuple ( (2.0/width())*trianglef(p.x()-0.5*width(),0.5*width()), // 0 at -width/2 and +width/2, 1 at 0 hop(p), hop(p-XY(0.5*width(),0.0)) ); } }; //! Generates points suitable for evaluating cutting function /* struct HopCut : public Friezegroup { HopCut(real width) :Friezegroup(width) {} const XY operator()(const XY& p) const { return Hop(width())(p+XY(0.5*width(),0.0)); } }; */ //------------------------------------------------------------------------------------------ //! Jump (Conway p1m1): horizontal reflection only /*! Just cycle x range and reflect in y. Is simply Hop with a relection about y=0 \verbatim o o o --- --- --- --- --- --- o o o \endverbatim */ struct Jump : public Hop { Jump(real width,int domain=0) :Hop(width,domain) {} const XY operator()(const XY& p) const { return Hop::operator()(XY(p.x(),fabs(p.y()))); } }; //! Constructs two points and a blending weight which will behave sensibly for Jump struct JumpBlend : public HopBlend { JumpBlend(real width) :HopBlend(width) {} const boost::tuple operator()(const XY& p) const { return HopBlend::operator()(XY(p.x(),fabs(p.y()))); } }; /* struct JumpCut : public HopCut { JumpCut(real width) :HopCut(width) {} const XY operator()(const XY& p) const { return HopCut::operator()(XY(p.x(),fabs(p.y()))); } }; */ //------------------------------------------------------------------------------------------ //! Sidle (Conway pm11): vertical reflection /*! Bounce x backwards and forwards. Can't be blended or cut because there are only reflection lines. (Well we could blend it by increasing the domain width and blending between overlapping domains, but the reflection lines aren't really worth going to any trouble to hide. \verbatim o| |o o| |o | | | | | | | | \endverbatim */ struct Sidle : public Friezegroup { Sidle(real width) :Friezegroup(width) {} const XY operator()(const XY& p) const { return XY ( trianglef(p.x()+0.5*width(),width())-0.5*width(), // So -width/2 maps to -width/2 p.y() ); } }; //------------------------------------------------------------------------------------------ //! Spinjump (Conway pmm2): vertical & horizontal reflection and half-rotation. /*! Oscillate x and reflect y. Is just sidle with a reflection about y=0. Can't be blended or cut because there are only reflection lines. \verbatim o o o o --- --- --- --- --- --- --- --- o o o o \endverbatim */ struct Spinjump : public Sidle { Spinjump(real width) :Sidle(width) {} const XY operator()(const XY& p) const { return Sidle::operator()(XY(p.x(),fabs(p.y()))); } }; //------------------------------------------------------------------------------------------ //! Spinhop (Conway p112): Half turn rotation only. /*! Sawtooth x increasing or decreasing depending on which side, with y inverting. Don't think this can be blended because it would change symmetry. \verbatim o o --- --- --- --- o o \endverbatim */ struct Spinhop : public Friezegroup { Spinhop(real width,int domain=0) :Friezegroup(width) ,_domain(domain) {} const XY operator()(const XY& p) const { bool flipped=(modulusf(p.x()+0.5*width(),2.0*width())>width()); if (_domain!=0) flipped=!flipped; real x=modulusf(p.x()+0.5*width(),width())-0.5*width()+_domain*width(); real y=p.y(); if (flipped) { x=-x; y=-y; } return XY(x,y); } private: const int _domain; }; //! Blended Spinhop /*! Can build this from blending two rotated hop sequences. Make the domains wider. \verbatim o o o o ----- ----- ----- ----- v blend these two together ----- ----- ----- ----- ^ using triangular alpha fn o o o o \endverbatim */ struct SpinhopBlend : public Friezegroup // subclassing doesn't make much sense really { SpinhopBlend(real width) :Friezegroup(width) {} const boost::tuple operator()(const XY& p) const { const Hop hop(2*width()); return boost::tuple ( trianglef(p.x()-width(),width())/width(), // zero at x=-width and +width, 1 at x=0 hop(p), hop(XY(width()-p.x(),-p.y())) ); } }; //! Only suitable cut I can see looks like Sidle with rotate across y=0 /*! \todo There's something different could be done here. The cutting is too constrained (needs pictures :^) \todo Some "softening" of the cut around y=0 would be good to stop odd looking hard lines. */ /* template struct SpinhopCut : public Friezegroup { SpinhopCut(real width) :Friezegroup(width) {} const int operator()(const Function& f,const XYZ& p,const ZPOLICY& zpol) const { const XY pm(p.x()-0.5*width(),fabs(p.y())); // Shift out of alignment with spinhop being cut, and add reflection about y=0 const XY r(Sidle(width())(pm)); // in combo with sidle, gets us something suitable for cutting without breaking spinhop const XY pc(p.y()<0.0 ? XY(-r.x(),r.y()) : r); // if we also flip it below y=0 const real k=tanh(f(XYZ(pc,zpol(p.z()))).sum_of_components()); const real t=(modulusf(pm.x()-0.5*width(),width())-0.5*width())/(0.5*width()); // Scans -1 to 1 across each (shifted, cutting) domain int d=0; if (t<0.0 && k=0.0 && k>t) d=1; return d; } }; */ //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_registration.h0000644000175100017510000001033312100750300021725 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces for class FunctionRegistration */ #ifndef _function_registration_h_ #define _function_registration_h_ class FunctionNode; class FunctionRegistry; class MutationParameters; class FunctionNodeInfo; //! Enum for classification bits enum { FnCore=1, // Constant, Identity or Transform: the 3 zero-child diluting functions FnStructure=2, // Functions which give rise to a lot of structure e.g spirals and grids FnRender=4, // Functions which use rendering algorithms FnIterative=8, // Iterative functions FnFractal=16, // Fractal functions FnClassifications=5 // The number of function classifications defined. }; extern const char*const function_classification_name[FnClassifications]; //! Define FunctionNodeStubNewFnPtr for convenience. typedef std::auto_ptr (*FunctionNodeStubNewFnPtr)(const MutationParameters&,bool); typedef std::auto_ptr (*FunctionNodeCreateFnPtr)(const FunctionRegistry&,const FunctionNodeInfo&,std::string&); //! Class for meta information about functions. class FunctionRegistration { public: //! Constructor. FunctionRegistration(const std::string& n,FunctionNodeStubNewFnPtr fs,FunctionNodeCreateFnPtr fc,uint np,uint na,bool i,uint fnc) :_name(n) ,_stubnew_fn(fs) ,_create_fn(fc) ,_params(np) ,_args(na) ,_iterative(i) ,_classification(fnc) {} //! Void constructor FunctionRegistration() :_name() ,_stubnew_fn(0) ,_create_fn(0) ,_params(0) ,_args(0) ,_iterative(false) ,_classification(0) {} //! Constructor (copy) FunctionRegistration(const FunctionRegistration& f) :_name(f._name) ,_stubnew_fn(f._stubnew_fn) ,_create_fn(f._create_fn) ,_params(f._params) ,_args(f._args) ,_iterative(f._iterative) ,_classification(f._classification) {} //! Accessor. const std::string& name() const { return _name; } //! Accessor. FunctionNodeStubNewFnPtr stubnew_fn() const { return _stubnew_fn; } //! Accessor. FunctionNodeCreateFnPtr create_fn() const { return _create_fn; } //! Accessor. uint params() const { return _params; } //! Accessor. uint args() const { return _args; } //! Accessor. bool iterative() const { return _iterative; } //! Accessor. uint classification() const { return _classification; } protected: //! Name of the function. std::string _name; //! The FunctionNodeUsing's stubnew function. FunctionNodeStubNewFnPtr _stubnew_fn; //! The FunctionNodeUsing's create function. FunctionNodeCreateFnPtr _create_fn; //! Number of parameters uint _params; //! Number of arguments uint _args; //! Whether iterative bool _iterative; //! Classification bits uint _classification; }; #endif evolvotron/libfunction/functions_spiral.h0000644000175100017510000000546312100750300020700 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_spiral_h_ #define _functions_spiral_h_ //------------------------------------------------------ FUNCTION_BEGIN(FunctionSpiralLinear,0,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real r=p.magnitude(); real theta=atan2(p.y(),p.x()); if (theta<0.0) theta+=2.0*M_PI; const real winding=floorf(r-theta/(2.0*M_PI)); const real x=2.0*winding+theta/M_PI; const real y=2.0*r-x; return arg(0)(XYZ(x,y,p.z())); } FUNCTION_END(FunctionSpiralLinear) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionSpiralLogarithmic,0,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real r=p.magnitude(); real theta=atan2(p.y(),p.x()); if (theta<0.0) theta+=2.0*M_PI; const real lnr=log(r); const real winding=floorf(lnr-theta/(2.0*M_PI)); const real x=2.0*winding+theta/M_PI; const real y=2.0*lnr-x; return arg(0)(XYZ(x,y,p.z())); } FUNCTION_END(FunctionSpiralLogarithmic) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/useful.h0000644000175100017510000001254712100750300016622 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief File containing all the author's favourite little helpers. */ #ifndef _useful_h_ #define _useful_h_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //! Convenience typedef. typedef unsigned int uint; //! Convenience typedef. typedef unsigned short ushort; //! Convenience typedef. typedef unsigned char uchar; //! float turns out to not be sufficient for some noise-amplifying ops (e.g gradient type things) so choice of double is deliberate. typedef double real; //! Maximum of 2 arguments. template inline const T maximum(T a,T b) {return (a>b ? a : b);} //! Maximum of 3 arguments. template inline const T maximum(T a,T b,T c) {return maximum(a,maximum(b,c));} //! Maximum of 4 arguments. template inline const T maximum(T a,T b,T c,T d) {return maximum(maximum(a,b),maximum(c,d));} //! Minimum of 2 arguments template inline const T minimum(T a,T b) {return (a inline const T minimum(T a,T b,T c) {return minimum(a,minimum(b,c));} //! Minimum of 4 arguments template inline const T minimum(T a,T b,T c,T d) {return minimum(minimum(a,b),minimum(c,d));} //! Returns argument multiplied by itself. template inline const T sqr(T a) {return a*a;} //! Returns result of clamping first argument to range specified by second and third. template inline const T clamped(T v,T lo,T hi) {return (vhi ? hi : v));} //! Clamps v to lie between lo and hi template inline void clamp(T& v,T lo,T hi) {v=(vhi ? hi : v));} //! Exchanges values of a and b. template inline void exchange(T& a,T& b) {const T x(a);a=b;b=x;} //! Print fatal error message and exit. extern void fatal_error(const char*); //! Print fatal error message and exit. inline void fatal_error(const std::string& s) { fatal_error(s.c_str()); } //! Call this for fatal internal error type messages. extern void fatal_internal_error(const char* src_file,uint src_line); //! Called if constraint macro fails. extern void constraint_violation(const char* test,const char* src_file,uint src_line); //! Use this to provide assert-like behaviour which is never disabled. #define constraint(TEST) {if (!TEST) {constraint_violation(#TEST,__FILE__,__LINE__);}} //! Sane modulus function always returning a number in the range [0,y) inline real modulusf(real x,real y) { if (y<0.0) y=-y; real r=fmod(x,y); if (r<0.0) r+=y; return r; } //! Sane modulus function always returning a number in the range [0,y-1] inline uint modulusi(int x,int y) { if (y<0) y=-y; int r=x%y; if (r<0) r+=y; assert(r>=0); return r; } //! Triangle function: like modulus, but starts ramping down instead of discontinuity at y. /*! Always has slope 1. Setting y=1 ensures x in [0,1] */ inline real trianglef(real x,real y) { if (y<0.0) y=-y; if (x<0.0) x=-x; real r=fmod(x,2.0*y); if (r>y) r=2.0*y-r; return r; } //! Use this to divert clog to supress verbose logging. Needs longer life than scope of main(). extern std::ofstream sink_ostream; #ifndef NDEBUG //! Inherit from this class (in debug only) and then assert(InstanceCounted::is_clean) at progam exit to check all instances are gone. class InstanceCounted { public: InstanceCounted(const std::string& what,bool verbose); virtual ~InstanceCounted(); static bool is_clear(); private: const std::string _what; const bool _verbose; static std::auto_ptr > _instance_counts; }; #endif #endif evolvotron/libfunction/function_transform.h0000644000175100017510000000407312100750300021232 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function class. */ #ifndef _function_transform_h_ #define _function_transform_h_ #include "transform.h" //------------------------------------------------------------------------------------------ //! Function class returning position transfomed by a 12-component linear transform. FUNCTION_BEGIN(FunctionTransform,12,0,false,FnCore) //! Return the transformed position argument. virtual const XYZ evaluate(const XYZ& p) const { const Transform transform(params()); return transform.transformed(p); } FUNCTION_END(FunctionTransform) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_friezegroup_spinjump.h0000644000175100017510000000462312100750300023671 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_friezegroup_spinjump_h_ #define _functions_friezegroup_spinjump_h_ #include "friezegroup.h" //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinjumpFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Spinjump(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupSpinjumpFreeZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinjumpClampZ,1,1,false,FnStructure) // Don't think this form can be warped without breaking symmetry virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Spinjump(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupSpinjumpClampZ) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_top.h0000644000175100017510000000621212100750300020016 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces for class FunctionTop This class would normally live in functions.h (and is included and registered there), but is split out so it can be efficiently used by MutatableImageDisplay and EvolvotronMain. NB There is no class heirarchy here as all virtualisation and boilerplate services are supplied when the functions are plugged into the FunctionNode template */ #ifndef _function_top_h_ #define _function_top_h_ class Transform; //! Function intended primarily to be the top level function node. /*! First 12 parameters are a space transform, second 12 paramters are a colour space transform. */ FUNCTION_BEGIN(FunctionTop,24,1,false,0) public: //! This returns a random tree suitable for use as a starting image. static std::auto_ptr initial(const MutationParameters& parameters,const FunctionRegistration* specific_fn=0,bool unwrapped=false); virtual const XYZ evaluate(const XYZ& p) const; virtual FunctionTop* is_a_FunctionTop() { return this; } virtual const FunctionTop* is_a_FunctionTop() const { return this; } //! Overridden so transform and colours don't keep changing virtual void mutate(const MutationParameters& parameters,bool mutate_own_parameters=true); virtual void concatenate_pretransform_on_right(const Transform& transform); virtual void mutate_pretransform_parameters(const MutationParameters& parameters); virtual void reset_pretransform_parameters(const MutationParameters& parameters); virtual void mutate_posttransform_parameters(const MutationParameters& parameters); virtual void reset_posttransform_parameters(const MutationParameters& parameters); private: const Transform interesting_pretransform(const MutationParameters& parameters,const real k); FUNCTION_END(FunctionTop) #endif evolvotron/libfunction/functions_misc.h0000644000175100017510000001015612100750300020334 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. Use this for functions under development, but they should really be split out into separate files eventually. */ #ifndef _functions_misc_h_ #define _functions_misc_h_ //------------------------------------------------------------------------------------------ //! Multiply x and y by z. FUNCTION_BEGIN(FunctionCone,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return XYZ(p.x()*p.z(),p.y()*p.z(),p.z()); } FUNCTION_END(FunctionCone) //------------------------------------------------------------------------------------------ //! Multiply x and y by exp(z). FUNCTION_BEGIN(FunctionExpCone,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real k=exp(p.z()); return XYZ(p.x()*k,p.y()*k,p.z()); } FUNCTION_END(FunctionExpCone) //------------------------------------------------------------------------------------------ //! Separate influence of z co-ordinate. /*! Interesting as a top level node for animations as structure will tend to be fixed, with only colour map changing */ FUNCTION_BEGIN(FunctionSeparateZ,3,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ v=arg(0)(XYZ(p.x(),p.y(),0.0)); return arg(1)(v+p.z()*XYZ(param(0),param(1),param(2))); } FUNCTION_END(FunctionSeparateZ) //------------------------------------------------------------------------------------------ //! Function repeatedly applying it's leaf function to the argument FUNCTION_BEGIN(FunctionIterate,0,1,true,FnIterative) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { XYZ ret(p); for (uint i=0;i. */ /**************************************************************************/ /*! \file \brief Helper functions for hexagons. */ #include "xy.h" //! Returns cartesian coords of given hex-grid const XY hex_coord(int x,int y); //! Finds integer hex-grid coordinates of hex containing cartesian px,py extern const std::pair nearest_hex(real px,real py); evolvotron/libfunction/function_transform_generalised.h0000644000175100017510000000356712100750300023603 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for FunctionTransformGeneralised */ #ifndef _function_transform_generalised_h_ #define _function_transform_generalised_h_ #include "transform.h" FUNCTION_BEGIN(FunctionTransformGeneralised,0,4,false,0) //! Return the transformed position argument. virtual const XYZ evaluate(const XYZ& p) const { const Transform transform(arg(0)(p),arg(1)(p),arg(2)(p),arg(3)(p)); return transform.transformed(p); } FUNCTION_END(FunctionTransformGeneralised) #endif evolvotron/libfunction/functions_friezegroup_spinsidle.h0000644000175100017510000000543412100750300024017 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_friezegroup_spinsidle_h_ #define _functions_friezegroup_spinsidle_h_ #include "friezegroup.h" //! Spinsidle (Conway pma2): Glide reflection with half rotation. /*! Oscillate x, reflect y in alternate x cycles. \verbatim |oo| |oo| | | | | | | | | | | | | |oo| \endverbatim */ struct Spinsidle { const XY operator()(const XY& p) const { return XY ( trianglef(p.x(),0.5), modulusf(p.x()+0.5,2.0)<1.0 ? p.y() : -p.y() ); } }; struct SpinsidleInvariant; struct SpinsidleBlend; //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinsidleFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Spinsidle(),FreeZ()); } FUNCTION_END(FunctionFriezeGroupSpinsidleFreeZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinsidleClampZ,1,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Spinsidle(),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupSpinsidleClampZ) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_node_info.h0000644000175100017510000000476512100750300021167 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class FunctioNodeInfo. */ #ifndef _function_node_info_h_ #define _function_node_info_h_ //! Trivial class used during XML parsing. /*! Encapsulates enough info to build a function tree from */ class FunctionNodeInfo { public: FunctionNodeInfo() :_type("UNKNOWN") ,_iterations(0) {} ~FunctionNodeInfo() {} //! Accessor. const std::string& type() const { return _type; } //! Accessor. void type(const std::string& t) { _type=t; } //! Accessor. const std::vector& params() const { return _params; } //! Accessor. std::vector& params() { return _params; } //! Accessor. const boost::ptr_vector& args() const { return _args; } //! Accessor. boost::ptr_vector& args() { return _args; } //! Accessor. uint iterations() const { return _iterations; } //! Accessor. void iterations(uint i) { _iterations=i; } protected: std::string _type; std::vector _params; boost::ptr_vector _args; uint _iterations; }; #endif evolvotron/libfunction/function_pre_transform.h0000644000175100017510000000441512100750300022100 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces for class FunctionPreTransform This class would normally live in functions.h (and is included and registered there), but is split out so it can be efficiently used by MutatableImageDisplay and EvolvotronMain. NB There is no class heirarchy here as all virtualisation and boilerplate services are supplied when the functions are plugged into the FunctionNode template. */ #ifndef _function_pre_transform_h_ #define _function_pre_transform_h_ #include "transform.h" //! Function class returning leaf node evaluated at position transfomed by a 12-component linear transform. FUNCTION_BEGIN(FunctionPreTransform,12,1,false,0) //! Return the evaluation of arg(0) at the transformed position argument. virtual const XYZ evaluate(const XYZ& p) const { const Transform transform(params()); return arg(0)(transform.transformed(p)); } FUNCTION_END(FunctionPreTransform) #endif evolvotron/libfunction/functions_friezegroup_jump.h0000644000175100017510000000750312100750300022777 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_friezegroup_jump_h_ #define _functions_friezegroup_jump_h_ #include "friezegroup.h" //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupJumpFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Jump(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupJumpFreeZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupJumpClampZ,1,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Jump(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupJumpClampZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupJumpBlendClampZ,1,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupBlend(arg(0),arg(1),p,JumpBlend(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupJumpBlendClampZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupJumpBlendFreeZ,0,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupBlend(arg(0),arg(1),p,JumpBlend(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupJumpBlendFreeZ) //------------------------------------------------------------------------------------------ /* FUNCTION_BEGIN(FunctionFriezeGroupJumpCutClampZ,2,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { const int d=FriezegroupCut(arg(1),p,JumpCut(1.0),ClampZ(param(1))); return FriezegroupEvaluate(arg(0),p,Jump(1.0,d),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupJumpCutClampZ) */ //------------------------------------------------------------------------------------------ /* FUNCTION_BEGIN(FunctionFriezeGroupJumpCutFreeZ,0,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { const int d=FriezegroupCut(arg(1),p,JumpCut(1.0),FreeZ()); return FriezegroupEvaluate(arg(0),p,Jump(1.0,d),FreeZ()); } FUNCTION_END(FunctionFriezeGroupJumpCutFreeZ) */ //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_spherical.h0000644000175100017510000000734412100750300021360 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_spherical_h_ #define _functions_spherical_h_ //------------------------------------------------------ //! Transforms cartesian coordinates to spherical FUNCTION_BEGIN(FunctionCartesianToSpherical,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real r=p.magnitude(); // Angles are normalised (-1 to +1) over their usual possible range. const real theta=atan2(p.y(),p.x())*(1.0/M_PI); const real phi=(r== 0.0 ? 0.0 : asin(p.z()/r)*(1.0/(0.5*M_PI))); return XYZ(r,theta,phi); } FUNCTION_END(FunctionCartesianToSpherical) //------------------------------------------------------------------------------------------ //! Transforms spherical coordinates to cartesian FUNCTION_BEGIN(FunctionSphericalToCartesian,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real r=p.x(); const real theta=M_PI*p.y(); const real phi=0.5*M_PI*p.z(); const real x=r*cos(theta)*sin(phi); const real y=r*sin(theta)*sin(phi); const real z=r*cos(phi); return XYZ(x,y,z); } FUNCTION_END(FunctionSphericalToCartesian) //------------------------------------------------------------------------------------------ // Converts the position argument to spherical coords, pass these through the leaf node, and convert the result back to cartesian. FUNCTION_BEGIN(FunctionEvaluateInSpherical,0,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real in_r=p.magnitude(); const real in_theta=atan2(p.y(),p.x())*(1.0/M_PI); const real in_phi=(in_r== 0.0 ? 0.0 : asin(p.z()/in_r)*(1.0/(0.5*M_PI))); const XYZ v(arg(0)(XYZ(in_r,in_theta,in_phi))); const real out_r=v.x(); const real out_theta=M_PI*v.y(); const real out_phi=0.5*M_PI*v.z(); const real x=out_r*cos(out_theta)*sin(out_phi); const real y=out_r*sin(out_theta)*sin(out_phi); const real z=out_r*cos(out_phi); return XYZ(x,y,z); } FUNCTION_END(FunctionEvaluateInSpherical) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_kaleidoscope.h0000644000175100017510000001266512100750300022052 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_kaleidoscope_h_ #define _functions_kaleidoscope_h_ //------------------------------------------------------------------------------------------ //! Implements reflection of sampling point about multiple planes FUNCTION_BEGIN(FunctionKaleidoscope,1,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint n=2+static_cast(floor(8.0*fabs(param(0)))); const real a=atan2(p.x(),p.y()); const real r=sqrt(p.x()*p.x()+p.y()*p.y()); const real sa=trianglef(a,M_PI/n); const XYZ s(r*sin(sa),r*cos(sa),p.z()); return arg(0)(s); } FUNCTION_END(FunctionKaleidoscope) //------------------------------------------------------------------------------------------ //! Like FunctionKaleidoscope but Z drives rotation of underlying function /*! Good for animation */ FUNCTION_BEGIN(FunctionKaleidoscopeZRotate,2,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint n=2+static_cast(floor(8.0*fabs(param(0)))); const real a=atan2(p.x(),p.y()); const real r=sqrt(p.x()*p.x()+p.y()*p.y()); const real sa=trianglef(a,M_PI/n)+param(1)*p.z(); const XYZ s(r*sin(sa),r*cos(sa),0.0); return arg(0)(s); } FUNCTION_END(FunctionKaleidoscopeZRotate) //------------------------------------------------------------------------------------------ //! Like FunctionKaleidoscope with a twist FUNCTION_BEGIN(FunctionKaleidoscopeTwist,2,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint n=2+static_cast(floor(8.0*fabs(param(0)))); const real a=atan2(p.x(),p.y()); const real r=sqrt(p.x()*p.x()+p.y()*p.y()); const real sa=trianglef(a-r*param(1),M_PI/n); const XYZ s(r*sin(sa),r*cos(sa),p.z()); return arg(0)(s); } FUNCTION_END(FunctionKaleidoscopeTwist) //------------------------------------------------------------------------------------------ //! Implements reflection of sampling point about multiple planes FUNCTION_BEGIN(FunctionWindmill,1,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint n=1+static_cast(floor(8.0*fabs(param(0)))); const real a=atan2(p.x(),p.y()); const real r=sqrt(p.x()*p.x()+p.y()*p.y()); const real sa=modulusf(a,M_PI/n); const XYZ s(r*sin(sa),r*cos(sa),p.z()); return arg(0)(s); } FUNCTION_END(FunctionWindmill) //------------------------------------------------------------------------------------------ //! Like FunctionWindmill but Z drives rotation of underlying function /*! Good for animation */ FUNCTION_BEGIN(FunctionWindmillZRotate,2,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint n=1+static_cast(floor(8.0*fabs(param(0)))); const real a=atan2(p.x(),p.y()); const real r=sqrt(p.x()*p.x()+p.y()*p.y()); const real sa=modulusf(a,M_PI/n)+param(1)*p.z(); const XYZ s(r*sin(sa),r*cos(sa),0.0); return arg(0)(s); } FUNCTION_END(FunctionWindmillZRotate) //------------------------------------------------------------------------------------------ //! Like FunctionWindmill with twist FUNCTION_BEGIN(FunctionWindmillTwist,2,1,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const uint n=1+static_cast(floor(8.0*fabs(param(0)))); const real a=atan2(p.x(),p.y()); const real r=sqrt(p.x()*p.x()+p.y()*p.y()); const real sa=modulusf(a-r*param(1),M_PI/n); const XYZ s(r*sin(sa),r*cos(sa),p.z()); return arg(0)(s); } FUNCTION_END(FunctionWindmillTwist) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_boilerplate.h0000644000175100017510000002123312100750300021516 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for abstract base class FunctionBoilerplate. And implementation given that it's a template. */ #ifndef _function_boilerplate_h_ #define _function_boilerplate_h_ #include "function_node.h" #include "function_node_info.h" #include "function_registry.h" #include "margin.h" //! Template class to generate boilerplate for virtual methods. template class FunctionBoilerplate : public FunctionNode { public: typedef FunctionNode Superclass; //! Constructor /*! \warning Careful to pass an appropriate initial iteration count for iterative functions. */ FunctionBoilerplate(const std::vector& p,boost::ptr_vector& a,uint iter); //! Destructor. virtual ~FunctionBoilerplate(); //! Accessor providing function name virtual const char* thisname() const =0; //! Registration member returns a reference to class meta-information. static const FunctionRegistration get_registration(const char* fn_name); //! Bits give some classification of the function type static uint type_classification() {return CLASSIFICATION;} //! Bits give some classification of the function type virtual uint self_classification() const; //! Factory method to create a stub node for this type static std::auto_ptr stubnew(const MutationParameters& mutation_parameters,bool exciting); //! Factory method to create a node given contents. /*! Returns null if there's a problem, in which case explanation is in report */ static std::auto_ptr create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report); //! Return a deeploned copy. virtual std::auto_ptr deepclone() const; //! Return a deeploned copy with more specific type (but of course this can't be virtual). std::auto_ptr typed_deepclone() const; //! Internal self-consistency check. We can add some extra checks. virtual bool ok() const; //! Save this node. virtual std::ostream& save_function(std::ostream& out,uint indent) const; }; template FunctionBoilerplate::FunctionBoilerplate(const std::vector& p,boost::ptr_vector& a,uint iter) :FunctionNode(p,a,iter) { assert(params().size()==PARAMETERS); assert(args().size()==ARGUMENTS); assert((iter==0 && !ITERATIVE) || (iter!=0 && ITERATIVE)); } template FunctionBoilerplate::~FunctionBoilerplate() {} //! Provide a complete registration for the function template const FunctionRegistration FunctionBoilerplate::get_registration(const char* fn_name) { return FunctionRegistration ( std::string(fn_name), &FunctionBoilerplate::stubnew, &FunctionBoilerplate::create, PARAMETERS, ARGUMENTS, ITERATIVE, FUNCTION::type_classification() ); } template uint FunctionBoilerplate::self_classification() const { return CLASSIFICATION; } template std::auto_ptr FunctionBoilerplate::stubnew(const MutationParameters& mutation_parameters,bool exciting) { std::vector params; stubparams(params,mutation_parameters,PARAMETERS); boost::ptr_vector args; stubargs(args,mutation_parameters,ARGUMENTS,exciting); return std::auto_ptr ( new FUNCTION ( params, args, (ITERATIVE ? stubiterations(mutation_parameters) : 0) ) ); } template std::auto_ptr FunctionBoilerplate::create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report) { if (!verify_info(info,PARAMETERS,ARGUMENTS,ITERATIVE,report)) return std::auto_ptr(); boost::ptr_vector args; if (!create_args(function_registry,info,args,report)) return std::auto_ptr(); return std::auto_ptr(new FUNCTION(info.params(),args,info.iterations())); } template std::auto_ptr FunctionBoilerplate::deepclone() const { return std::auto_ptr(typed_deepclone()); } template std::auto_ptr FunctionBoilerplate::typed_deepclone() const { return std::auto_ptr(new FUNCTION(cloneparams(),*cloneargs(),iterations())); } template bool FunctionBoilerplate::ok() const { return ( params().size()==PARAMETERS && args().size()==ARGUMENTS && ((iterations()==0 && !ITERATIVE) || (iterations()!=0 && ITERATIVE)) && FunctionNode::ok() ); } template std::ostream& FunctionBoilerplate::save_function(std::ostream& out,uint indent) const { return Superclass::save_function(out,indent,thisname()); } #define FN_CTOR_DCL(FN) FN(const std::vector& p,boost::ptr_vector& a,uint iter); #define FN_CTOR_IMP(FN) FN::FN(const std::vector& p,boost::ptr_vector& a,uint iter) :Superclass(p,a,iter) {} #define FN_DTOR_DCL(FN) virtual ~FN(); #define FN_DTOR_IMP(FN) FN::~FN() {} #define FN_VNAME_DCL(FN) virtual const char* thisname() const; #define FN_VNAME_IMP(FN) const char* FN::thisname() const {return FN::classname();} #define FN_SNAME_DCL(FN) static const char* classname(); #define FN_SNAME_IMP(FN) const char* FN::classname() {return #FN;} #define FUNCTION_BEGIN(FN,NP,NA,IT,CL) \ class FN : public FunctionBoilerplate \ {public: \ typedef FunctionBoilerplate Superclass; \ FN_CTOR_DCL(FN) \ FN_DTOR_DCL(FN) \ FN_VNAME_DCL(FN) \ FN_SNAME_DCL(FN) //! Macro to push registrations through to registry. /*! Used by register_all_functions.h/register_all_functions.cpp */ #define REGISTER(R,FN) R.register_function(FN::get_registration(#FN)); #define REGISTER_DCL(FN) extern void register_ ## FN(FunctionRegistry&); #define REGISTER_IMP(FN) void register_ ## FN(FunctionRegistry& r){REGISTER(r,FN);} #define FUNCTION_END(FN) };REGISTER_DCL(FN); #endif evolvotron/libfunction/functions_noise.h0000644000175100017510000000747712100750300020532 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for FunctionNoise */ #ifndef _functions_noise_h_ #define _functions_noise_h_ #include "noise.h" //------------------------------------------------------------------------------------------ //! Perlin noise function. /*! Returns a single value replicated into all three channels */ FUNCTION_BEGIN(FunctionNoiseOneChannel,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { // Crank up the frequency a bit otherwise don't see much variation in base case const real v=_noise(2.0*p); return XYZ(v,v,v); } protected: static Noise _noise; FUNCTION_END(FunctionNoiseOneChannel) //------------------------------------------------------------------------------------------ //! Multiscale noise function. /*! Returns a single value replicated into all three channels */ FUNCTION_BEGIN(FunctionMultiscaleNoiseOneChannel,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { real t=0.0; real tm=0.0; for (uint i=0;i<8;i++) { const real k=(1<. */ /**************************************************************************/ /*! \file \brief Interfaces for class FunctionRegistry. */ #ifndef _function_registry_h_ #define _function_registry_h_ #include "function_registration.h" //! Class acting as a dictionary from function name to registration info. /*! Intended to be used as singleton; get() obtains instance. This holds the "definitive" collection of registrations. FunctionRegistrations can be compared using pointer identiy. */ class FunctionRegistry { public: //! Constuctor public to Singleton boilerplate can new it. /*! \todo Figure out how to make this protected/private. */ FunctionRegistry(); ~FunctionRegistry(); //! Return the registration for the function named (returns 0 if unknown) const FunctionRegistration* lookup(const std::string& f) const; //! typedefed for convenience typedef boost::ptr_map Registrations; //! Just get the collection of registrations. const Registrations& registrations() const { return _registry_by_name; } //! Dump list of registered functions std::ostream& status(std::ostream& out) const; //! Register a function. Handles duplicates gracefully. void register_function(const FunctionRegistration& r); protected: //! Dictionary from names to Registration objects Registrations _registry_by_name; }; #endif evolvotron/libfunction/noise.h0000644000175100017510000000341612100750300016427 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface to Noise class. */ #ifndef _noise_h_ #define _noise_h_ //! Perlin noise generator. class Noise { public: //! Constructor. Noise(uint seed); //! Return noise value at a point. real operator()(const XYZ& p) const; protected: //! Number of table entries. enum {N=256}; int _p[N+N+2]; XYZ _g[N+N+2]; //void setup(const XYZ&,int,int&,int&,real&,real&); }; #endif evolvotron/libfunction/function_constant.h0000644000175100017510000000425012100750300021045 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function class. */ #ifndef _function_constant_h_ #define _function_constant_h_ //------------------------------------------------------------------------------------------ //! Function class representing a constant value. FUNCTION_BEGIN(FunctionConstant,3,0,false,FnCore) //! Returns the constant value virtual const XYZ evaluate(const XYZ&) const { return XYZ(param(0),param(1),param(2)); } //! Returns true, obviously. /*! One of the few cases this method is overriden; most (all?) other no-argument functions should return false */ virtual bool is_constant() const { return true; } FUNCTION_END(FunctionConstant) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_quantize.h0000644000175100017510000000570712100750300021247 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Functions inspired by tartan patterns. */ #ifndef _functions_quantize_h_ #define _functions_quantize_h_ #include "hex.h" //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionPixelize,2,0,false,FnStructure) //! Evaluate function. /*! Quantize coordinates to 2D grid */ virtual const XYZ evaluate(const XYZ& p) const { return XYZ ( param(0)*round(p.x()/param(0)), param(1)*round(p.y()/param(1)), p.z() ); } FUNCTION_END(FunctionPixelize) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionVoxelize,3,0,false,FnStructure) //! Evaluate function. /*! Quantize coordinates to 3D grid. */ virtual const XYZ evaluate(const XYZ& p) const { return XYZ ( param(0)*round(p.x()/param(0)), param(1)*round(p.y()/param(1)), param(2)*round(p.z()/param(2)) ); } FUNCTION_END(FunctionVoxelize) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionPixelizeHex,1,0,false,FnStructure) //! Evaluate function. /*! Quantize coordinates to 2D hexgrid. */ virtual const XYZ evaluate(const XYZ& p) const { const std::pair h=nearest_hex(p.x()/param(0),p.y()/param(0)); //std::cerr << h.first << " " << h.second << "\n"; return XYZ ( param(0)*hex_coord(h.first,h.second), p.z() ); } FUNCTION_END(FunctionPixelizeHex) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_arithmetic.h0000644000175100017510000001223612100750300021533 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_arithmetic_h_ #define _functions_arithmetic_h_ //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionAdd,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(0)(p)+arg(1)(p); } FUNCTION_END(FunctionAdd) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionMultiply,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ v0(arg(0)(p)); const XYZ v1(arg(1)(p)); // NB Don't use v0*v1 as it would be cross-product. return XYZ(v0.x()*v1.x(),v0.y()*v1.y(),v0.z()*v1.z()); } FUNCTION_END(FunctionMultiply) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionDivide,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ v0(arg(0)(p)); const XYZ v1(arg(1)(p)); return XYZ( (v1.x()==0.0 ? 0.0 : v0.x()/v1.x()), (v1.y()==0.0 ? 0.0 : v0.y()/v1.y()), (v1.z()==0.0 ? 0.0 : v0.z()/v1.z()) ); } FUNCTION_END(FunctionDivide) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionMax,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ v0(arg(0)(p)); const XYZ v1(arg(1)(p)); return XYZ( std::max(v0.x(),v1.x()), std::max(v0.y(),v1.y()), std::max(v0.z(),v1.z()) ); } FUNCTION_END(FunctionMax) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionMin,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ v0(arg(0)(p)); const XYZ v1(arg(1)(p)); return XYZ( std::min(v0.x(),v1.x()), std::min(v0.y(),v1.y()), std::min(v0.z(),v1.z()) ); } FUNCTION_END(FunctionMin) //------------------------------------------------------------------------------------------ //! Function returning components of one function modulus thos of another. /*! Sane always-positive modulus used to avoid funny business at zero. */ FUNCTION_BEGIN(FunctionModulus,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ v0(arg(0)(p)); const XYZ v1(arg(1)(p)); return XYZ( modulusf(v0.x(),fabs(v1.x())), modulusf(v0.y(),fabs(v1.y())), modulusf(v0.z(),fabs(v1.z())) ); } FUNCTION_END(FunctionModulus) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionExp,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return XYZ(exp(p.x()),exp(p.y()),exp(p.z())); } FUNCTION_END(FunctionExp) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionSin,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return XYZ(sin(p.x()),sin(p.y()),sin(p.z())); } FUNCTION_END(FunctionSin) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionCos,0,0,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return XYZ(cos(p.x()),cos(p.y()),cos(p.z())); } FUNCTION_END(FunctionCos) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_friezegroup_spinhop.h0000644000175100017510000000754412100750300023511 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. */ #ifndef _functions_friezegroup_spinhop_h_ #define _functions_friezegroup_spinhop_h_ #include "friezegroup.h" //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinhopFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Spinhop(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupSpinhopFreeZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinhopClampZ,1,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupEvaluate(arg(0),p,Spinhop(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupSpinhopClampZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinhopBlendClampZ,1,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupBlend(arg(0),p,SpinhopBlend(1.0),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupSpinhopBlendClampZ) //------------------------------------------------------------------------------------------ FUNCTION_BEGIN(FunctionFriezeGroupSpinhopBlendFreeZ,0,1,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { return FriezegroupBlend(arg(0),p,SpinhopBlend(1.0),FreeZ()); } FUNCTION_END(FunctionFriezeGroupSpinhopBlendFreeZ) //------------------------------------------------------------------------------------------ /* FUNCTION_BEGIN(FunctionFriezeGroupSpinhopCutClampZ,2,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { const int d=SpinhopCut(1.0)(arg(1),p,ClampZ(param(1))); return FriezegroupEvaluate(arg(0),p,Spinhop(1.0,d),ClampZ(param(0))); } FUNCTION_END(FunctionFriezeGroupSpinhopCutClampZ) */ //------------------------------------------------------------------------------------------ /* FUNCTION_BEGIN(FunctionFriezeGroupSpinhopCutFreeZ,0,2,false,FnStructure) virtual const XYZ evaluate(const XYZ& p) const { const int d=SpinhopCut(1.0)(arg(1),p,FreeZ()); return FriezegroupEvaluate(arg(0),p,Spinhop(1.0,d),FreeZ()); } FUNCTION_END(FunctionFriezeGroupSpinhopCutFreeZ) */ //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/function_compose_pair.h0000644000175100017510000000371412100750300021700 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for FunctionComposeTriple */ #ifndef _function_compose_pair_h_ #define _function_compose_pair_h_ FUNCTION_BEGIN(FunctionComposePair,0,2,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(1)(arg(0)(p)); } //! Is constant if any (rather than default "all") function is constant. /*! One of the few cases it's worth overriding this method */ virtual bool is_constant() const { return (arg(0).is_constant() || arg(1).is_constant()); } FUNCTION_END(FunctionComposePair) #endif evolvotron/libfunction/functions_magnitude.h0000644000175100017510000000504512100750300021357 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_magnitude_h_ #define _functions_magnitude_h_ //------------------------------------------------------------------------------------------ //! Function returns a value comprising the magnitude of three leaf functions. FUNCTION_BEGIN(FunctionMagnitudes,0,3,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return XYZ( arg(0)(p).magnitude(), arg(1)(p).magnitude(), arg(2)(p).magnitude() ); } FUNCTION_END(FunctionMagnitudes) //------------------------------------------------------------------------------------------ //! Function returns leaf function value magnitude scaled by position magnitude. FUNCTION_BEGIN(FunctionMagnitude,3,1,false,0) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { return arg(0)(p).magnitude()*XYZ(param(0),param(1),param(2)); } FUNCTION_END(FunctionMagnitude) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_choose.h0000644000175100017510000002473612100750300020672 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_choose_h_ #define _functions_choose_h_ #include "hex.h" //------------------------------------------------------------------------------------------ // Strip of one function across another FUNCTION_BEGIN(FunctionChooseStrip,3,3,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { if (fabs(p.y()) > fabs(arg(2)(p)%XYZ(param(0),param(1),param(2)))) return arg(1)(p); else return arg(0)(p); } FUNCTION_END(FunctionChooseStrip) //------------------------------------------------------------------------------------------ // Strip of one function across another FUNCTION_BEGIN(FunctionChooseStripBlend,6,4,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real r0=fabs(arg(2)(p)%XYZ(param(0),param(1),param(2))); const real r1=fabs(arg(3)(p)%XYZ(param(3),param(4),param(5))); const real inner=std::min(r0,r1); const real outer=std::max(r0,r1); const real ay=fabs(p.y()); if (ay<=inner) return arg(0)(p); if (ay>=outer) return arg(1)(p); const XYZ v0(arg(0)(p)); const XYZ v1(arg(1)(p)); return v0+(v1-v0)*(ay-inner)/(outer-inner); } FUNCTION_END(FunctionChooseStripBlend) //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on the relative magnitudes of 2 other functions FUNCTION_BEGIN(FunctionChooseSphere,0,4,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { if ((arg(0)(p)).magnitude2()<(arg(1)(p)).magnitude2()) return arg(2)(p); else return arg(3)(p); } FUNCTION_END(FunctionChooseSphere) //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on whether a rectangle contains a point FUNCTION_BEGIN(FunctionChooseRect,0,4,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const XYZ p0(arg(0)(p)); const XYZ p1(arg(1)(p)); if (p1.origin_centred_rect_contains(p0)) return arg(2)(p); else return arg(3)(p); } FUNCTION_END(FunctionChooseRect) //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on position in 3d mesh FUNCTION_BEGIN(FunctionChooseFrom2InCubeMesh,0,2,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const int x=static_cast(floorf(p.x())); const int y=static_cast(floorf(p.y())); const int z=static_cast(floorf(p.z())); if ((x+y+z)&1) return arg(0)(p); else return arg(1)(p); } FUNCTION_END(FunctionChooseFrom2InCubeMesh); //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on position in 3d mesh FUNCTION_BEGIN(FunctionChooseFrom3InCubeMesh,0,3,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const int x=static_cast(floorf(p.x())); const int y=static_cast(floorf(p.y())); const int z=static_cast(floorf(p.z())); return arg(modulusi(x+y+z,3))(p); } FUNCTION_END(FunctionChooseFrom3InCubeMesh) //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on position in 2d grid FUNCTION_BEGIN(FunctionChooseFrom2InSquareGrid,0,2,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const int x=static_cast(floorf(p.x())); const int y=static_cast(floorf(p.y())); if ((x+y)&1) return arg(0)(p); else return arg(1)(p); } FUNCTION_END(FunctionChooseFrom2InSquareGrid) //------------------------------------------------------------------------------------------ //! Function implements selection between 3 functions based on position in 2d grid FUNCTION_BEGIN(FunctionChooseFrom3InSquareGrid,0,3,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const int x=static_cast(floorf(p.x())); const int y=static_cast(floorf(p.y())); return arg(modulusi(x+y,3))(p); } FUNCTION_END(FunctionChooseFrom3InSquareGrid) //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on position in grid of triangles FUNCTION_BEGIN(FunctionChooseFrom2InTriangleGrid,0,2,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { static const XYZ d0(1.0 ,0.0 ,0.0); static const XYZ d1(cos( M_PI/3),sin( M_PI/3),0.0); static const XYZ d2(cos(2*M_PI/3),sin(2*M_PI/3),0.0); const int a=static_cast(floorf(p%d0)); const int b=static_cast(floorf(p%d1)); const int c=static_cast(floorf(p%d2)); if ((a+b+c)&1) return arg(0)(p); else return arg(1)(p); } FUNCTION_END(FunctionChooseFrom2InTriangleGrid) //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on position in grid of triangles /*! Not entirely sure this one produces a sensible pattern. Needs explicitly testing. */ FUNCTION_BEGIN(FunctionChooseFrom3InTriangleGrid,0,3,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { static const XYZ d0(1.0 ,0.0 ,0.0); static const XYZ d1(cos( M_PI/3),sin( M_PI/3),0.0); static const XYZ d2(cos(2*M_PI/3),sin(2*M_PI/3),0.0); const int a=static_cast(floorf(p%d0)); const int b=static_cast(floorf(p%d1)); const int c=static_cast(floorf(p%d2)); return arg(modulusi(a+b+c,3))(p); } FUNCTION_END(FunctionChooseFrom3InTriangleGrid) //------------------------------------------------------------------------------------------ //! Function implements selection between 3 functions based on position in grid of hexagons /*! Don't entirely understand how this works, but it looks nice. */ FUNCTION_BEGIN(FunctionChooseFrom3InDiamondGrid,0,3,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { // Basis vectors for hex grid static const XYZ d0(1.0 ,0.0 ,0.0); static const XYZ d1(cos( M_PI/3),sin( M_PI/3),0.0); static const XYZ d2(cos(2*M_PI/3),sin(2*M_PI/3),0.0); // Dot with basis const real p0=p%d0; const real p1=p%d1; const real p2=p%d2; // Find nearest on-grid point const int i0=(int)floorf(p0+0.5); const int i1=(int)floorf(p1+0.5); const int i2=(int)floorf(p2+0.5); // Measure distance const real m0=fabsf(p0-i0); const real m1=fabsf(p1-i1); const real m2=fabsf(p2-i2); // Closest one decides which function if (m0<=m1 && m0<=m2) return arg(0)(p); else if (m1<=m0 && m1<=m2) return arg(1)(p); else return arg(2)(p); } FUNCTION_END(FunctionChooseFrom3InDiamondGrid) //------------------------------------------------------------------------------------------ //! Function implements selection between 3 functions based on position in grid of hexagons FUNCTION_BEGIN(FunctionChooseFrom3InHexagonGrid,0,3,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const std::pair h=nearest_hex(p.x(),p.y()); const uint which=h.second+((h.first&1)? 2 : 0); return arg(modulusi(which,3))(p); } FUNCTION_END(FunctionChooseFrom3InHexagonGrid) //------------------------------------------------------------------------------------------ //! Function implements selection between 2 functions based on position in grid of hexagons FUNCTION_BEGIN(FunctionChooseFrom2InBorderedHexagonGrid,1,2,false,FnStructure) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const std::pair h=nearest_hex(p.x(),p.y()); bool in_border=false; // Hex centres are separated by 1.0 so limit border size const real b=modulusf(param(0),0.5); // Step along grid co-ordinates in various directions. If there's a nearer point, we're in the border. for (uint i=0;i<6;i++) { const real dx=b*sin(i*M_PI/3.0); const real dy=b*cos(i*M_PI/3.0); const std::pair a=nearest_hex(p.x()+dx,p.y()+dy); if (h!=a) { in_border=true; break; } } return arg(in_border)(p); } FUNCTION_END(FunctionChooseFrom2InBorderedHexagonGrid) //------------------------------------------------------------------------------------------ #endif evolvotron/libfunction/functions_render.h0000644000175100017510000001450512100750300020662 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces and implementation for specific Function classes. As much as possible of the implementation should be pushed into the FunctionBoilerplate template. */ #ifndef _functions_render_h_ #define _functions_render_h_ //------------------------------------------------------------------------------------------ //! Rays intersecting a textured unit sphere /*! arg(0) is background arg(1) is 3D texture for sphere param(0,1,2) is light source direction p.x, p.y is the 2D position of a ray from infinity travelling in direction (0 0 1) */ FUNCTION_BEGIN(FunctionOrthoSphereShaded,3,2,false,FnRender) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real pr2=p.x()*p.x()+p.y()*p.y(); if (pr2<1.0) { const real z=-sqrt(1.0-pr2); const XYZ n(p.x(),p.y(),z); const XYZ lu(param(0),param(1),param(2)); const XYZ l(lu.normalised()); const real i=0.5*(1.0+l%n); // In range 0-1 return i*arg(1)(n); } else { return arg(0)(p); } } FUNCTION_END(FunctionOrthoSphereShaded) //------------------------------------------------------------------------------------------ //! Rays intersecting a textured unit sphere, with bump mapping /*! arg(0) is background arg(1) is 3D texture for sphere arg(2) is bump-map for sphere (take magnitude2) param(0,1,2) is light source direction p.x, p.y is the 2D position of a ray from infinity travelling in direction (0 0 1) */ FUNCTION_BEGIN(FunctionOrthoSphereShadedBumpMapped,3,3,false,FnRender) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real pr2=p.x()*p.x()+p.y()*p.y(); if (pr2<1.0) { const real z=-sqrt(1.0-pr2); const XYZ n(p.x(),p.y(),z); // Tangent vectors const XYZ east((XYZ(0.0,1.0,0.0)*n).normalised()); const XYZ north(n*east); const real e0=(arg(2)(n-epsilon()*east)).magnitude2(); const real e1=(arg(2)(n+epsilon()*east)).magnitude2(); const real n0=(arg(2)(n-epsilon()*north)).magnitude2(); const real n1=(arg(2)(n+epsilon()*north)).magnitude2(); const real de=(e1-e0)*inv_epsilon2(); const real dn=(n1-n0)*inv_epsilon2(); const XYZ perturbed_n((n-east*de-north*dn).normalised()); const XYZ lu(param(0),param(1),param(2)); const XYZ l(lu.normalised()); const real i=0.5*(1.0+l%perturbed_n); // In range 0-1 return i*arg(1)(n); } else { return arg(0)(p); } } FUNCTION_END(FunctionOrthoSphereShadedBumpMapped) //------------------------------------------------------------------------------------------ //! Rays reflecting off a unit sphere /*! arg(0) is background arg(1) sampled using a normalised vector defines an environment for reflected rays p.x, p.y is the 2D position of a ray from infinity travelling in direction (0 0 1) */ FUNCTION_BEGIN(FunctionOrthoSphereReflect,0,2,false,FnRender) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real pr2=p.x()*p.x()+p.y()*p.y(); if (pr2<1.0) { const real z=-sqrt(1.0-pr2); // This is on surface of unit radius sphere - no need to normalise XYZ n(p.x(),p.y(),z); // The ray _towards_ the viewer v is (0 0 -1) const XYZ v(0.0,0.0,-1.0); // The reflected ray is (2n.v)n-v const XYZ reflected((2.0*(n%v))*n-v); return arg(1)(reflected); } else { return arg(0)(p); } } FUNCTION_END(FunctionOrthoSphereReflect) //------------------------------------------------------------------------------------------ //! Rays reflecting off a bump mapped unit sphere /*! arg(0) is background arg(1) sampled using a normalised vector defines an environment for reflected rays arg(2) is bump map p.x, p.y is the 2D position of a ray from infinity travelling in direction (0 0 1) */ FUNCTION_BEGIN(FunctionOrthoSphereReflectBumpMapped,0,3,false,FnRender) //! Evaluate function. virtual const XYZ evaluate(const XYZ& p) const { const real pr2=p.x()*p.x()+p.y()*p.y(); if (pr2<1.0) { const real z=-sqrt(1.0-pr2); // This is on surface of unit radius sphere - no need to normalise XYZ n(p.x(),p.y(),z); // Tangent vectors const XYZ east((XYZ(0.0,1.0,0.0)*n).normalised()); const XYZ north(n*east); const real e0=(arg(2)(n-epsilon()*east)).magnitude2(); const real e1=(arg(2)(n+epsilon()*east)).magnitude2(); const real n0=(arg(2)(n-epsilon()*north)).magnitude2(); const real n1=(arg(2)(n+epsilon()*north)).magnitude2(); const real de=(e1-e0)*inv_epsilon2(); const real dn=(n1-n0)*inv_epsilon2(); const XYZ perturbed_n((n-east*de-north*dn).normalised()); // The ray _towards_ the viewer is (0 0 -1) const XYZ v(0.0,0.0,-1.0); // The reflected ray is (2n.v)n-v const XYZ reflected((2.0*(perturbed_n%v))*perturbed_n-v); return arg(1)(reflected); } else { return arg(0)(p); } } FUNCTION_END(FunctionOrthoSphereReflectBumpMapped) //------------------------------------------------------------------------------------------ #endif evolvotron/libevolvotron/mutation_parameters_qobject.h0000644000175100017510000000363312100750252023503 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class MutationParametersQObject. */ #ifndef _mutation_parameters_qobject_h_ #define _mutation_parameters_qobject_h_ #include "mutation_parameters.h" //! class extending MutationParameters to emit changed signal when appropriate. class MutationParametersQObject : public QObject, public MutationParameters { Q_OBJECT; public: MutationParametersQObject(uint seed,bool autocool,bool debug_mode,QObject* parent); ~MutationParametersQObject(); signals: void changed(); protected: void report_change(); }; #endif evolvotron/libevolvotron/evolvotron_main.h0000644000175100017510000003307212100750252021132 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class EvolvotronMain. */ #ifndef _evolvotron_main_h_ #define _evolvotron_main_h_ #include "function_registry.h" #include "transform_factory.h" #include "mutatable_image.h" #include "mutatable_image_display.h" #include "mutatable_image_computer_farm.h" #include "mutation_parameters_qobject.h" #include "render_parameters.h" class DialogAbout; class DialogHelp; class DialogMutationParameters; class DialogRenderParameters; class DialogFunctions; class DialogFavourite; //! Utility class to expand "restart with" menu picks /*! A boost::bind kind of thing */ class SignalExpanderRestartWith : public QObject { private: Q_OBJECT const FunctionRegistration*const _fn; public: SignalExpanderRestartWith(QObject* parent,const FunctionRegistration* fn) :QObject(parent) ,_fn(fn) {} public slots: void restart_with() { emit restart_with(_fn); } signals: void restart_with(const FunctionRegistration*); }; //! Top level GUI component for evolvotron application class EvolvotronMain : public QMainWindow { private: Q_OBJECT protected: //! Class encapsulating everything needed for undo functionality. /*! \todo This is too big to be a nested class. */ class History { protected: //! Pointer to main app. EvolvotronMain*const _main; typedef std::map > ArchiveRecordEntries; typedef std::pair ArchiveRecord; typedef std::deque Archive; //! Each deque slot contains the collection of display-image pairs replaced by an single action (and a string naming that action). /*! We use a deque rather than a stack because we want to clean up the tail end (limited number of Undos). */ Archive _archive; //! Number of slots retained for history. const uint max_slots; //! Clean up the last slot in the queue. void purge(); //! Write some info to std::clog. void log_status() const; public: //! Constructor. History(EvolvotronMain*); //! Destructor. ~History(); //! Eliminate any references to the display (and clean up any undo actions which are empty as a result). void goodbye(MutatableImageDisplay*); //! Record that we are overwriting the given display. void replacing(MutatableImageDisplay* display); //! Starts a new action slot void begin_action(const std::string& action_name); //! Ends an action slot and updates the undoable state. void end_action(); //! Returns true if there is stuff to undo bool undoable(); //! Implements an undo. void undo(); }; protected: //! Convenience typedef for pointer to member function implementing a kind of spawn. typedef void (EvolvotronMain::* SpawnMemberFn)(const boost::shared_ptr& image,MutatableImageDisplay* display,bool one_of_many); //! Instance of History object to track activity. std::auto_ptr _history; //! Sweep z linearly through animations /*! \todo Move to mutation or render paraemeters ? */ const bool _linear_zsweep; //! Generate spheremaps /*! \todo Move to mutation or render paraemeters ? */ const bool _spheremap; //! Name of files to load on a reset. std::vector _startup_filenames; //! Whether to shuffle startup files (if any). const bool _startup_shuffle; //! Instance of mutation parameters for the app /*! This used to be held by DialogMutationParameters, but now we want to share it around a bit (although modifications should always be via the dialog slots, to keep the dialogs up to date) */ MutationParametersQObject _mutation_parameters; //! Instance of render parameters for the app RenderParameters _render_parameters; //! Somewhere to report what's going on QStatusBar* _statusbar; //! Label for displaying number of tasks running (more permanent than StatusBar's message method). QLabel* _statusbar_tasks_label; //! Number of main tasks the statusbar is currently reporting as active /*! Cached to avoid unnecessarily regenerating message */ uint _statusbar_tasks_main; //! Number of enlargement tasks the statusbar is currently reporting as active /*! Cached to avoid unnecessarily regenerating message */ uint _statusbar_tasks_enlargement; //! The "About" dialog widget. DialogAbout* _dialog_about; //! The "Help" dialog widget (quick reference text) DialogHelp* _dialog_help_short; //! The "Help" dialog widget (full manual text) DialogHelp* _dialog_help_long; //! The dialog for adjusting MutationParameters. DialogMutationParameters* _dialog_mutation_parameters; //! The dialog for adjusting RenderParameters. DialogRenderParameters* _dialog_render_parameters; //! Dialog for controlling which functions are in use. DialogFunctions* _dialog_functions; //! Dialog for selecting a favourite function (also holds the state for favourite stuff) DialogFavourite* _dialog_favourite; //! The file menu. QMenu* _popupmenu_file; //! The edit menu. QMenu* _popupmenu_edit; //! ID for the undo item (so we can disable it). QAction* _popupmenu_edit_undo_action; //! The settings menu QMenu* _popupmenu_settings; //! Action for setting fullscreen QAction* _menu_action_fullscreen; //! Action for hiding menubar QAction* _menu_action_hide_menu; //! The help menu. QMenu* _popupmenu_help; //! Select autocooling (also serves to reset the generation count). QCheckBox* _checkbox_autocool_enable; //! Report number of generations. QLabel* _label_autocool_enable; //! Button to reheat QPushButton* _button_autocool_reheat; //! Grid for image display areas QWidget* _grid; //! Timer to drive tick() slot QTimer* _timer; //! Two farms of compute threads. One for the main display, one for enlargements. std::auto_ptr _farm[2]; //! All the displays in the grid. std::vector _displays; //! Keeps track of which displays are still available for display (they might have been destroyed while an image was computing). /*! Non-const because we might need to notify them about various things */ std::set _known_displays; //! Keeps track of which displays are still resizing std::set _resizing; //! The last image spawned (used to regenerate single displays). boost::shared_ptr _last_spawned_image; //! Pointer to member function used for last spawn. SpawnMemberFn _last_spawn_method; //! An owned pointer to the current transform factory (needed for Respawn). std::auto_ptr _transform_factory; //! Accessor. const boost::shared_ptr last_spawned_image() const { return _last_spawned_image; } //! Accessor. SpawnMemberFn last_spawn_method() const { return _last_spawn_method; } //! Not just an accessor. Takes ownership of a deepclone of the image void last_spawned_image(const boost::shared_ptr& image,SpawnMemberFn method); //! Accessor const TransformFactory& transform_factory() const { // We shouldn't be here unless transform_factory has been set to something. assert(_transform_factory.get()!=0); return *_transform_factory; } //! Not just an accessor. Takes ownership of a deepclone of the argument. void transform_factory(const TransformFactory& tfactory) { _transform_factory=tfactory.clone(); } //@{ //! Perform a particular type of spawn from an individiual image to an individual display. (Locking not checked). void spawn_normal(const boost::shared_ptr& image,MutatableImageDisplay* display,bool one_of_many); void spawn_recoloured(const boost::shared_ptr& image,MutatableImageDisplay* display,bool one_of_many); void spawn_warped(const boost::shared_ptr& image,MutatableImageDisplay* display,bool one_of_many); //@} //! Spawn the specified display using the specified method. void spawn_all(MutatableImageDisplay* display,SpawnMemberFn method,const std::string& action_name); public: //! Constructor. EvolvotronMain ( QWidget* parent, const QSize& grid_size, uint frames, uint framerate, uint n_threads, bool separate_farm_for_enlargements, int niceness_grid, int niceness_enlargements, bool start_fullscreen, bool start_menuhidden, bool autocool, bool jitter, uint multisample_level, bool function_debug_mode, bool linear_zsweep, bool spheremap, const std::vector& startup_filenames, bool startup_shuffle ); //! Destructor. ~EvolvotronMain(); //! Accessor. Returns true if function name recognised. Forwards to DialogFavourite. bool favourite_function(const std::string& f); //! Accessor. Forwards to DialogFavourite. void favourite_function_unwrapped(bool v); //! Accessor. std::vector& displays() { return _displays; } //! Accessor. /*! NB Only const version made available publicly as modifications should be through an appropriate dialog slot. */ const MutationParameters& mutation_parameters() const { return _mutation_parameters; } //! Accessor. /*! NB Only const version made available publicly as modifications should be through an appropriate dialog slot. */ const RenderParameters& render_parameters() const { return _render_parameters; } //! Returns which farm to use for purpose. MutatableImageComputerFarm& farm(bool enlargement) { return *_farm[enlargement && _farm[1].get()]; } //! Accessor. History& history() { return *_history; } //! Called by History when performing undo. void restore(MutatableImageDisplay* display,const boost::shared_ptr&,bool one_of_many); //! Called by History to change undo menu status. void set_undoable(bool v,const std::string& name); //! Regenerates a single display using last spawn method and source. void respawn(MutatableImageDisplay* display); //! Mutates the image held by the given display to all the other displays owned. void spawn_normal(MutatableImageDisplay* spawning_display); //! Similar to spawn except just changes the colouration of the image. void spawn_recoloured(MutatableImageDisplay* spawning_display); //! Similar to spawn except just changes the input co-ordinates to the image. void spawn_warped(MutatableImageDisplay* spawning_display,const TransformFactory& tfactory); //! Called from display constructor to indicate the display is available for the disposal of its completed tasks. void hello(MutatableImageDisplay*); //! Called from display destructor to indicate the display is no longer available for the disposal of its completed tasks. void goodbye(MutatableImageDisplay*); //! Returns true if the display is known. bool is_known(MutatableImageDisplay* disp) const; //! Write a list of known displays (for debugging) void list_known(std::ostream& out) const; protected: //! Handle key-presses void keyPressEvent(QKeyEvent* e); //! Reset the specified display. void reset(MutatableImageDisplay* display); protected slots: //! Signalled by timer. void tick(); //! Signalled by menu item. Forwards to History object. void undo(); //! Signalled by menu item. Simplifies all functions. void simplify_constants(); public slots: //! Signalled by menu item. void toggle_hide_menu(); //! Signalled by menu item void toggle_fullscreen(); //! Signalled by menu item. Public because called from evolvotron app wrapper. void reset(bool reset_mutation_parameters,bool reset_locks); //! Forwards to reset(false) void reset_warm(); //! Forwards to reset(true) void reset_cold(); //! Resets and randomizes function weightings void reset_randomized(); //! So we can update any exposed mutation parameters (e.g autocool enable, generation count) void mutation_parameters_changed(); //! So we can re-render when render parameters change void render_parameters_changed(); }; #endif evolvotron/libevolvotron/obsolete/matrix.h0000644000175100017510000003005412100750251021025 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class Matrix. */ #ifndef _matrix_h_ #define _matrix_h_ #include "useful.h" #include "tuple.h" // Fwd declaration of helper class. template class MatrixHelperSumCofactorDeterminantProducts; template class MatrixHelperInvert; //! Common base for general and specialised cases. /*! Avoids having to reimplement some functions in Matrix<1,1,T> specialisation. */ template class MatrixBase : public Tuple > { public: //! Null constructor. MatrixBase() {} //! Copy constructor. MatrixBase(const MatrixBase& t) :Tuple >(t) {} ////! Destructor. //~MatrixBase() // {} uint rows() const { return R; } uint cols() const { return C; } static int cofactor_sign(uint mr,uint mc) { return ( ((mr+mc)&1) ? -1 : 1); } static const T cofactor_sign(uint mr,uint mc,const T v) { return ( ((mr+mc)&1) ? -v : v); } std::ostream& write(std::ostream& out) const { for (uint r=0;r class Matrix : public MatrixBase { protected: public: //! Null constructor. Matrix() :MatrixBase() {} //! Copy constructor. Matrix(const Matrix& m) :MatrixBase(m) {} //! Construct minor matrix (from a larger matrix) Matrix(uint mr,uint mc,const Matrix& m) :MatrixBase() { m.extract_minor(mr,mc,*this); } ////! Destructor. //~Matrix() // {} void operator*=(const T& v) { for (uint r=0;r transposed() const { Matrix ret; for (uint r=0;r& m) const { assert(mr void extract_minor(Matrix& m) const { TupleHelperDoubleCopyEliminate::execute(m,*this); } T determinant() const { /* Old code calls runtime minor generator: not efficient code. T ret(0); for (uint c=0;c(0,c,*this).determinant()); } return ret; */ // Better version uses metaprogramming to expand to straight-line code. return MatrixHelperSumCofactorDeterminantProducts::execute(*this); } Matrix inverted() const { Matrix ret; /* Old code calls runtime minor generator: not efficient code. for (uint r=0;r(r,c,(*this)).determinant()); } } */ // Better version uses metaprogramming to expand to straight-line code. MatrixHelperInvert::execute(ret,(*this)); ret*=(T(1.0)/determinant()); return ret; } }; //! Matrix multiplication /*! \todo Check assembler code. Want loops to unroll - use template recursion ? */ template inline const Matrix operator*(const Matrix& a,const Matrix& b) { Matrix ret; for (uint r=0;r inline const Tuple operator*(const Matrix& m,const Tuple& v) { Tuple ret; for (uint r=0;r class Matrix<1,1,T> : public MatrixBase<1,1,T> { protected: public: //! Null constructor. Matrix<1,1,T>() :MatrixBase<1,1,T>() {} //! Copy constructor. Matrix<1,1,T>(const Matrix<1,1,T>& t) :MatrixBase<1,1,T>(t) {} //! Construct minor matrix Matrix<1,1,T>(uint mr,uint mc,const Matrix<2,2,T>& m) :MatrixBase() { m.extract_minor(mr,mc,*this); } //! Convenient constructor Matrix<1,1,T>(T v00) :MatrixBase<1,1,T>() { (*this)[0][0]=v00; } ////! Destructor. //~Matrix<1,1,T>() // {} Matrix<1,1,T> transposed() const { return (*this); } //NB minor of 1x1 matrix makes no sense. //void extract_minor(uint mr,uint mc,Matrix& m) const T determinant() const { return (*this)[0][0]; } Matrix<1,1,T> inverted() const { return Matrix<1,1,T>(T(1.0)/(*this)[0][0]); } }; //! (Partial) specialisation for 2x2 matrix template class Matrix<2,2,T> : public MatrixBase<2,2,T> { protected: public: //! Null constructor. Matrix<2,2,T>() :MatrixBase<2,2,T>() {} //! Copy constructor. Matrix<2,2,T>(const Matrix<2,2,T>& t) :MatrixBase<2,2,T>(t) {} //! Construct minor matrix Matrix<2,2,T>(uint mr,uint mc,const Matrix<3,3,T>& m) :MatrixBase<2,2,T>() { m.extract_minor(mr,mc,*this); } //! Convenient constructor Matrix<2,2,T>(T v00,T v01,T v10,T v11) :MatrixBase<2,2,T>() { (*this)[0][0]=v00; (*this)[0][1]=v01; (*this)[1][0]=v10; (*this)[1][1]=v11; } ////! Destructor. //~Matrix<1,1,T>() // {} Matrix<2,2,T> transposed() const { return Matrix<2,2,T>((*this)[0][0],(*this)[1][0],(*this)[0][1],(*this)[1][1]); } void extract_minor(uint mr,uint mc,Matrix<1,1,T>& m) const { assert(mr==0 || mr==1); assert(mc==0 || mc==1); m[0][0]=(*this)[1-mr][1-mc]; } //! Template member for extracting minors when row and column to be eliminated are known at compile time. template void extract_minor(Matrix<1,1,T>& m) const { assert(SKIP_R==0 || SKIP_R==1); assert(SKIP_C==0 || SKIP_C==1); m[0][0]=(*this)[1-SKIP_R][1-SKIP_C]; } T determinant() const { return (*this)[0][0]*(*this)[1][1]-(*this)[0][1]*(*this)[1][0]; } Matrix<2,2,T> inverted() const { Matrix<2,2,T> ret((*this)[1][1],-(*this)[0][1],-(*this)[1][0],(*this)[0][0]); ret*=(T(1.0)/determinant()); return ret; } }; template class MatrixHelperSumCofactorDeterminantProducts { public: static T execute(const Matrix& m) { Matrix minor_matrix; // Would prefer to use //m.extract_minor<0,FC>(minor_matrix); // but compiler doesn't seem to like it (problem with partial specialisation?) TupleHelperDoubleCopyEliminate::execute(minor_matrix,m); return m[0][FC]*((FC&1) ? -1.0f : 1.0f)*minor_matrix.determinant() + MatrixHelperSumCofactorDeterminantProducts::execute(m); ; } }; template class MatrixHelperSumCofactorDeterminantProducts<0,R,C,T> { public: static float execute(const Matrix& m) { Matrix minor_matrix; TupleHelperDoubleCopyEliminate::execute(minor_matrix,m); return m[0][0]*minor_matrix.determinant(); } }; template class MatrixHelperInvert { public: static void execute(Matrix& m_out,const Matrix& m_in) { Matrix minor_matrix; TupleHelperDoubleCopyEliminate::execute(minor_matrix,m_in); m_out[C][R]=Matrix::cofactor_sign(R,C,minor_matrix.determinant()); MatrixHelperInvert::execute(m_out,m_in); } }; template class MatrixHelperInvert { public: static void execute(Matrix& m_out,const Matrix& m_in) { Matrix minor_matrix; TupleHelperDoubleCopyEliminate::execute(minor_matrix,m_in); m_out[0][R]=Matrix::cofactor_sign(R,0,minor_matrix.determinant()); MatrixHelperInvert::execute(m_out,m_in); } }; template class MatrixHelperInvert<0,0,ROWS,COLS,T> { public: static void execute(Matrix& m_out,const Matrix& m_in) { Matrix minor_matrix; TupleHelperDoubleCopyEliminate::execute(minor_matrix,m_in); m_out[0][0]=Matrix::cofactor_sign(0,0,minor_matrix.determinant()); } }; //! 3x3 matrix class class Matrix33 : public Matrix<3,3,float> { public: Matrix33() {} Matrix33(const Matrix33& m) :Matrix<3,3,float>(m) {} }; class Matrix33RotateX : public Matrix33 { public: Matrix33RotateX(float a) { const float sa=sin(a); const float ca=cos(a); (*this)[0][0]=1.0f;(*this)[0][1]=0.0f;(*this)[0][2]=0.0f; (*this)[1][0]=0.0f;(*this)[1][1]= ca;(*this)[1][2]= -sa; (*this)[2][0]=0.0f;(*this)[2][1]= sa;(*this)[2][2]= ca; } }; class Matrix33RotateY : public Matrix33 { public: Matrix33RotateY(float a) { const float sa=sin(a); const float ca=cos(a); (*this)[0][0]= ca;(*this)[0][1]=0.0f;(*this)[0][2]= sa; (*this)[1][0]= -sa;(*this)[1][1]=1.0f;(*this)[1][2]= ca; (*this)[2][0]=0.0f;(*this)[2][1]=0.0f;(*this)[2][2]=0.0f; } }; class Matrix33RotateZ : public Matrix33 { public: Matrix33RotateZ(float a) { const float sa=sin(a); const float ca=cos(a); (*this)[0][0]= ca;(*this)[0][1]= -sa;(*this)[0][2]=0.0f; (*this)[1][0]= sa;(*this)[1][1]= ca;(*this)[1][2]=0.0f; (*this)[2][0]=0.0f;(*this)[2][1]=0.0f;(*this)[2][2]=1.0f; } }; //! Tests basic matrix functionality. extern void testmatrix(); #endif evolvotron/libevolvotron/obsolete/tuple.h0000644000175100017510000001266612100750251020663 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class Tuple. */ #ifndef _tuple_h_ #define _tuple_h_ #include "useful.h" //! Class to hold a fixed size tuple of elements /*! Maybe Array would have been a better name. NB No destructor defined because gcc generates less efficient code for matrices. */ template class Tuple { protected: //! The elements. T _element[N]; public: //! Null constructor. Tuple() {} //! Copy constructor. Tuple(const Tuple& t) { for (uint i=0;i() // {} //! Accessor. T& operator[](uint i) { assert(i& t) { for (uint i=0;i& t) { for (uint i=0;i fill(T v) { Tuple ret; for (uint i=0;i inline const bool operator==(const Tuple& a,const Tuple& b) { for (uint i=0;i inline const bool operator!=(const Tuple& a,const Tuple& b) { return !(a==b); } //! Element-wise addition. template inline const Tuple operator+(const Tuple& a,const Tuple& b) { Tuple r(a); r+=b; return r; } //! Element-wise subtraction. template inline const Tuple operator-(const Tuple& a,const Tuple& b) { Tuple r(a); r-=b; return r; } //! Test whether this will expand to sensible straight-through code. /*! Call TupleHelperCopyEliminate::compute(Tuple& m_to,const Tuple& m_from); This _does_ seem to generate a nice straight-through run of move instructions. */ template class TupleHelperCopyEliminate { public: static void execute(Tuple& m_to,const Tuple& m_from) { m_to[I]=m_from[(I>=SKIP ? I+1 : I)]; TupleHelperCopyEliminate::execute(m_to,m_from); } }; //! Specialisation to end recursion template class TupleHelperCopyEliminate<0,SKIP,N,T> { public: static void execute(Tuple& m_to,const Tuple& m_from) { m_to[0]=m_from[(SKIP==0 ? 1 : 0)]; } }; //! Development of class TupleHelperCopyEliminate to provide elimination of a row and column. /*! Used by matrix class to generate minor matrices efficiently */ template class TupleHelperDoubleCopyEliminate { public: static void execute(Tuple >& m_to,const Tuple >& m_from) { TupleHelperCopyEliminate::execute(m_to[I],m_from[(I>=SKIP_R ? I+1 : I)]); TupleHelperDoubleCopyEliminate::execute(m_to,m_from); } }; //! Specialisation to end recursion template class TupleHelperDoubleCopyEliminate<0,SKIP_R,SKIP_C,N_R,N_C,T> { public: static void execute(Tuple >& m_to,const Tuple >& m_from) { TupleHelperCopyEliminate::execute(m_to[0],m_from[(SKIP_R==0 ? 1 : 0)]); } }; #endif evolvotron/libevolvotron/mutatable_image.h0000644000175100017510000001232312100750277021034 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interfaces for class MutatableImage. */ #ifndef _mutatable_image_h_ #define _mutatable_image_h_ class FunctionNull; class FunctionTop; //! Class to hold the base FunctionNode of an image. /*! Once it owns a root FunctionNode* the whole structure should be fixed (mutate isn't available, only mutated). \todo Do reference counting on this object ? Maybe not: have to worry about stateful nodes, \todo Generally tighten up const-ness of interfaces. */ class MutatableImage #ifndef NDEBUG : public InstanceCounted #endif { protected: //! The top level FunctionNode of the image. /*! This is partly here because FunctionNode::mutate can't change the type of the node it is invoked on (only child nodes can be zapped), partly so we can keep colour and space transforms under control. */ std::auto_ptr _top; //! Whether to sweep z sinusoidally (vs linearly) bool _sinusoidal_z; //! Whether xyz should be interpreted as long/lat/radius bool _spheremap; //! Whether this image is locked \todo Should be a property of display, not image. bool _locked; //! Serial number for identity tracking (used by display to discover whether a recompute is needed) unsigned long long _serial; //! Object count to generate serial numbers static unsigned long long _count; public: //! Take ownership of the image tree with the specified root node. MutatableImage(std::auto_ptr&,bool sinz,bool sm,bool lock); //! Create a new random image tree. MutatableImage(const MutationParameters& parameters,bool exciting,bool sinz,bool sm); //! Destructor. NB Deletes owned image function tree. virtual ~MutatableImage(); //! Returns the sampling co-ordinate given a (sub)pixel position in the given frame of an animation. /*! This depends on things like sinusoidal_z and spheremap */ const XYZ sampling_coordinate(real x,real y,uint z,uint sx,uint sy,uint sz) const; //! Accessor. const FunctionTop& top() const; //! Accessor. bool sinusoidal_z() const { return _sinusoidal_z; } //! Accessor. bool spheremap() const { return _spheremap; } //! Accessor. bool locked() const { return _locked; } //! Accessor. void locked(bool l) { _locked=l; } //! Accessor. unsigned long long serial() const { return _serial; } //! Clone this image. The cloned image will not have locked state. boost::shared_ptr deepclone() const; //! Clone this image, setting locked state to that specified. boost::shared_ptr deepclone(bool lock) const; //! Return a mutated version of this image boost::shared_ptr mutated(const MutationParameters& p) const; //! Return a simplified version of this image boost::shared_ptr simplified() const; //! Return the a 0-255-scaled RGB value at the specified location. const XYZ get_rgb(const XYZ& p) const; //! Return the a 0-255-scaled RGB value at the specified pixel of an image/animation taking jitter (if random number generator provided) and multisampling into account const XYZ get_rgb(uint x,uint y,uint f,uint width,uint height,uint frames,Random01* r01,uint multisample) const; //! Return whether image value is independent of position. bool is_constant() const; //! Save the function-tree to the stream std::ostream& save_function(std::ostream& out) const; //! Read a new function tree from the given stream. static boost::shared_ptr load_function(const FunctionRegistry& function_registry,std::istream& in,std::string& report); //! Obtain some statistics about the image function void get_stats(uint& total_nodes,uint& total_parameters,uint& depth,uint& width,real& proportion_constant) const; //! Check the function tree is ok. bool ok() const; }; #endif evolvotron/libevolvotron/mutatable_image_computer_farm.h0000644000175100017510000001306412100750252023753 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class MutatableImageComputerFarm. */ #ifndef _mutatable_image_computer_farm_h_ #define _mutatable_image_computer_farm_h_ #include "useful.h" #include "mutatable_image_computer.h" #include "mutatable_image_computer_task.h" class MutatableImageComputer; class MutatableImageDisplay; //! Class encapsulating some compute threads and queues of tasks to be done and tasks completed. /*! Priority queues are implemented using multiset becase we want to be able to iterate over all members. */ class MutatableImageComputerFarm { protected: //! Comparison class for STL template. class CompareTaskPriorityLoResFirst : public std::binary_function,boost::shared_ptr,bool> { public: //! Compare task priorities. bool operator()(const boost::shared_ptr& t0,const boost::shared_ptr& t1) { return (t0->priority() < t1->priority()); } }; //! Comparison class for STL template. class CompareTaskPriorityHiResFirst : public std::binary_function,boost::shared_ptr,bool> { public: //! Compare task priorities. bool operator()(const boost::shared_ptr& t0,const boost::shared_ptr& t1) { return (t0->priority() > t1->priority()); } }; //! Mutex for locking. This is the ONLY thing the compute threads should ever block on. mutable QMutex _mutex; //! Wait condition for threads waiting for a new task. QWaitCondition _wait_condition; //! The compute threads boost::ptr_vector _computers; //! Convenience typedef. typedef std::multiset,CompareTaskPriorityLoResFirst> TodoQueue; //! Queue of tasks to be performed, lowest resolution first TodoQueue _todo; //! Conveniencetypedef. typedef std::multiset,CompareTaskPriorityHiResFirst> DoneQueue; //! Convenience typedef. /*! const because never needs to do anything other than compare pointers */ typedef std::map DoneQueueByDisplay; //! Queue of tasks completed awaiting display. /*! We reverse the compute priority so that highest resolution images get displayed first. Lower resolution ones arriving later should be discarded by the displays. This mainly makes a difference for animation where enlarging multiple low resolution images to screen res takes a lot of time. May help low-bandwidth X11 connections by minimising redraws too. We now also sort by display and do round-robin delivery (ithout this one display can run way ahead of the others) */ DoneQueueByDisplay _done; //! Points to the next display queue to be returned (could be .end()) DoneQueueByDisplay::iterator _done_position; public: //! Constructor. MutatableImageComputerFarm(uint n_threads,int niceness); //! Destructor cleans up threads. ~MutatableImageComputerFarm(); //! Accessor. uint num_threads() const { return _computers.size(); } //! Move aborted tasks from todo queue to done queue. void fasttrack_aborted(); //! Enqueue a task for computing. void push_todo(const boost::shared_ptr&); //! Remove a task from the head of the todo queue (returns null if none). const boost::shared_ptr pop_todo(MutatableImageComputer& requester); //! Enqueue a task for display. void push_done(const boost::shared_ptr&); //! Remove a task from the head of the display queue (returns null if none). const boost::shared_ptr pop_done(); //! Flags all tasks in all queues as aborted, and signals the compute threads to abort their current task. void abort_all(); //! Flags all tasks for a particular display as aborted (including compute threads) void abort_for(const MutatableImageDisplay* disp); //! Number of tasks in queues uint tasks() const; }; #endif evolvotron/libevolvotron/license.h0000644000175100017510000000303312100750252017325 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Header for license boilerplate. */ #ifndef _license_h #define _license_h_ //! String containing GPL text. extern const char*const license_string; #endif evolvotron/libevolvotron/dialog_help.h0000644000175100017510000000336212100750252020157 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class DialogHelp. */ #ifndef _dialog_help_h_ #define _dialog_help_h_ //! Provides a dialog box with some user documentation. /*! More of a quick reference guide than a manual. */ class DialogHelp : public QDialog { private: Q_OBJECT public: //! Constructor. DialogHelp(QWidget* parent,bool full); //! Destructor. ~DialogHelp(); }; #endif evolvotron/libevolvotron/usage_text.h0000644000175100017510000010135112100750277020064 0ustar timdaytimday"\n" "

Evolvotron User Manual

\n" "\n" "

\n" " Evolvotron is interactive "generative art" software to evolve \n" " images/textures/patterns through an iterative process of random \n" " mutation and user-selection driven evolution. \n" "

\n" "

\n" " On starting the application, a grid of images is displayed. \n" " Resize or maximise the application if you like, but the more \n" " pixels have to be calculated, the slower it will be. \n" " (For the default 2D image mode, you will need a fast machine or patience. \n" " For the optional animation mode, you will need both.) \n" "

\n" "

\n" " Simply repeat the following until bored: \n" "

  • Click (singleclick) on an image you like to \n" " spawn the next generation of its mutant offspring. \n" "
  • Wait until variations on it are regenerated in sufficient \n" " detail that you can decide which one you like best again. \n" "
  • \n" "
\n" "

\n" "

\n" " IMPORTANT: Initially you should select images with some sort of variation. \n" " If you select a uniform image, you may get stuck in a degenerate zone with \n" " little to mutate and therefore little chance of escape to more interesting \n" " images. You can always reset/restart from the "File" menu (the difference is \n" " that "reset" also resets the mutation parameters to their default values). \n" " Selecting one of the "warp" options from a context menu (right-click on \n" " an image) can also help by introducing an additional opportunity for \n" " mutation on subsequent spawns. \n" "

\n" "

\n" " Note that various spirals, grids and tiles, although complex looking, \n" " are actually implemented by a single function node and may leave you stuck too. \n" "

\n" "

Command Line Options

\n" "

\n" " The following are equivalent: \n" "

  • evolvotron --grid 12x8 \n" "
  • evolvotron --grid=12x8 \n" "
  • evolvotron -g 12x8 \n" "
  • \n" "
\n" "

\n" "

General Options

\n" "\n" "

\n" "

  • -a, --autocool
    \n" " Enable autocooling by default, and cause resets of mutation \n" " parameters to re-enable autocooling if it was disabled. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -F, --fullscreen
    \n" " Start in "fullscreen" mode (NB for Qt on X11 this means \n" " a screen-filling borderless/undecorated window is used; \n" " it's not simply maximising the window, and it's not the \n" " sort of framebuffer hijacking used by SDL games). The Qt \n" " documentation claims some window managers may not be entirely \n" " cooperative with this (in which case sorry, you're on your own). \n" " evolvotron actions which bring up dialog boxes (e.g save) seem \n" " to generally behave fairly sensibly but child windows \n" " (e.g enlargements or dialogs) can show some "interesting" behaviour. \n" " Fullscreen mode can be toggled within the application using "F" key. \n" " The "Esc" key will also exit it. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -g, --grid colsxrows
    \n" " Sets size of the grid of image display cells in the main application area (defaults to 5x6) \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -h, --help
    \n" " Print summary of command line options and exit. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -j, --jitter
    \n" " Enable sample jittering. Samples will be made at a random position \n" " within a pixel instead of on a regular grid, providing some antialiasing. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -m, --multisample multisample grid
    \n" " Enables additional antialiasing passes. \n" " Specifing 2 or 3 will provide an additional pass with 2x2 or 3x3 samples per pixel. \n" " Specifiying 4 (of higher) will provide a 2x2 and a final 4x4 pass. \n" " Specifying 1 provides the default behaviour of one sample per pixel. \n" " For best rendering quality also specify -j. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -M, --menuhide
    \n" " Start with menu and status bar hidden. Nice with --fullscreen. \n" " Hiding can be toggled within the application using ctrl-m. \n" " The Esc key will also bring them back. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -p, --spheremap
    \n" " Images are produced by sampling the underlying 3D function on the \n" " latitude-longitude grid of a sphere. The resulting images should be \n" " usable as spheremaps/spherical environment maps. Animations vary \n" " the radius of the sphere. NB when in spheremap mode, \n" " middle mouse button adjustments do not yet behave like you'd expect. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -S, --startup function_filename
    \n" " Specify a function filename (evolvotron's XML format) to load on startup \n" " (or reset). The option can be provided multiple times, and this is \n" " also the interpretation of any positional arguments. Startup functions \n" " are placed in the grid from left to right, top to bottom. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -U, --shuffle
    \n" " Use in conjunction with -S / --startup options, to display the specified \n" " functions in random order, both on application startup and on each \n" " reset of the application. \n" "
  • \n" "
\n" "

\n" "

Animation Options

\n" "\n" "

\n" "

  • -f, --frames frames
    \n" " Number of frames in animations (defaults to 1 i.e no animation) \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -l, --linear
    \n" " Vary z linearly with time rather than sinusoidally. \n" " Sinusoidal variation generally looks better when animations are "bounced" \n" " forwards and backwards, but this option is useful when generating slices to \n" " use as volumetric textures. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -s, --fps framerate
    \n" " Rate at which frames are displayed per second (integer). (Defaults to 8). \n" "
  • \n" "
\n" "

\n" "

Power-user & Debug Options

\n" "\n" "

\n" " Note that the usual Qt/X11 options \n" " (for example, -geometry widthxheight option to set on-screen size in pixels) \n" " are processed and removed before evolvotron options are checked. \n" "

\n" "

\n" "

  • -D, --debug
    \n" " Puts the certain aspects of the app into a more debug oriented mode. \n" " Currently (ie this may change) it simply changes function weightings \n" " so virtually all function nodes are FunctionNoiseOneChannel. By itself \n" " this is a pretty pointless thing to do, but in conjunction with the -X \n" " options it's useful for examining the behaviour of specific functions. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -E, --enlargement-threadpool
    \n" " Use a separate thread pool for computing enlargements. \n" " Using this option ensures computation of enlargements \n" " continue to make some progress even while the main grid \n" " is being actively worked on. However, this will be at \n" " the expense of main grid rendering performance. \n" " Without this option, enlargements' final high-resolution \n" " renderings are invariably lower priority than computation \n" " for images in the main grid. \n" " See also the -N option to control the priority of threads \n" " in this pool. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -n, --nice niceness
    \n" " Sets additional niceness (relative to the main application thread) \n" " of the compute (rendering) thread(s). \n" " It's useful to run compute threads at a slightly lower priority \n" " ("nice 4\" is the default without this option) than the main (GUI) \n" " part of the program (but note that this means other normal/lowish \n" " priority tasks running on your machine may slow evolvotron down \n" " a bit more than expected). \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -N, --Nice enlargement niceness
    \n" " Sets additional niceness (relative to the main application thread) \n" " of the compute thread(s) computing enlargements (default value is 8). \n" " Only effective in conjunction with -E option. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -t, --threads threads
    \n" " Sets number of compute threads. \n" " If this is not specified, then as many compute threads are created \n" " as there are processors on the system (unless this cannot be \n" " discovered in which case only a single compute thread is created). \n" " Non-linux builds will likely not include code to determine processor count \n" " (suitable patches gratefully received). \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -u, --unwrapped
    \n" " Modifies -F behaviour so that the specified "favourite" function \n" " is NOT wrapped by space/colour transforms. NB For functions without leaf nodes \n" " or parameters (e.g FunctionSphericalToCartesian) this doesn't \n" " leave any scope for variation or future mutation. \n" " Function name recognition is case sensitive. \n" " Example: \n" " evolvotron -F FunctionKaleidoscope -u \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -v, --verbose
    \n" " Verbose mode, writes various things to application stderr. \n" " This is primarily intended to assist debugging. \n" " This option used to be useful for getting a list of supported function \n" " names for use with the -F option, but those can also be inspected \n" " via the Settings dialogs. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • -x, --favourite functionname
    \n" " Force a specific "favourite" function type to be used at the top level \n" " of all function trees. The specified function is still wrapped \n" " by spatial and colour warping functions which may disguise \n" " it considerably. A list of all the function names understood \n" " by evolvotron is output during app startup when the -v option \n" " is specified. Function name recognition is case sensitive. \n" " Example: \n" " evolvotron -F FunctionSpiralLinear \n" "
  • \n" "
\n" "

\n" "

Mouse Control

\n" "\n" "

Left-click

\n" "

\n" " A left-click on an image in the main window spawns the mutant offspring \n" " of that image to all the other (non-locked) displays in the grid. \n" "

\n" "

Right-click Context Menu

\n" "

\n" " Right clicking on an image gets you a few more options: \n" "

\n" "

\n" "

  • "Respawn" regenerates just the current image from whatever it was \n" " spawned from (and using recolour or warp, if that's what was used \n" " to produce it). \n" " The main use of this is to make your grid of images look nice \n" " for screendumps, by regenerating any which aren't up to scratch. \n" " NB May not work as expected after an "undo". \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Spawn" is the same as clicking an image. It generates mutated \n" " images to all unlocked images in the grid. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Recolour" to produce different coloured variants of the selected image \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Warp"'s sub-options produce variants of the image which have been \n" " zoomed/rotated/panned. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Lock" to prevent an image from being overwritten by spawns from other \n" " images (select again to toggle). \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Enlarge" to produce a blow-up of the image in a single window. \n" " Submenu items select either a freely resizable window or \n" " a scrollable view of a fixed size image. \n" " If the application is running in fullscreen mode (NB this is \n" " NOT the same as a simply "maximised" window) then the enlarged \n" " image will also be fullscreen (the "Resizeable" mode is probably \n" " what you want in this case as the image will automatically be \n" " rendered at the correct resolution). \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Save image" to save the image in a file (.ppm or .png). \n" " You generally want to save an enlarged image: if you \n" " save a small image from the grid, the size you see on the screen \n" " is the size you get in the file. Save isn't allowed until the \n" " full resolution image has been generated; if you try to save too \n" " early a dialog box will be displayed telling you to try again later. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Save function" to store the function to an XML file. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Load function" to load a stored function from an XML file. \n" " NB if the file was saved from a different version numbered \n" " evolvotron, a warning message will be generated. \n" " Save/load of functions is an experimental feature and you should \n" " not count on future versions of evolvotron being able to load \n" " files saved from old versions, or producing the same image \n" " from a loaded function. Attempting to load functions from later \n" " versions into earlier versions is even less likely to succeed. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Simplify" prunes the function tree of redundant branches where \n" " possible (the same action can be applied to all images from \n" " the main "Edit" menu). This doesn't change the appearance of \n" " the image, but may make it recompute faster. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "Properties" brings up a dialog box containing some information \n" " about the image (e.g the number of function nodes it contains). \n" "
  • \n" "
\n" "

\n" "

Middle Mouse Button

\n" "

\n" " [NB This feature will probably only be of practical use to those with high-end machines]. \n" "

\n" "

\n" " You can use the middle mouse button to drag-adjust individual images. \n" " This is useful for "final composition" type tweaks, e.g centering an \n" " image's most interesting feature, or just for satisfying your curiosity \n" " about what's off the edge of the image. \n" "

\n" "

\n" " It also works on enlarged images, although it's virtually unusable without \n" " a bit of practice on smaller, faster ones (just boldly make the adjustment \n" " you want, release the button... and wait). \n" "

\n" "

\n" " Changes made can be rolled-back on the main Edit/Undo menu item, \n" " one drag-action at a time. \n" "

\n" "

\n" " An unmodified middle-mouse drag pans the image around following \n" " the mouse motion. \n" "

\n" "

\n" " A SHIFT-middle drag zooms the image in and out with scaling \n" " proportional to the distance from the centre of the image. Beware of \n" " generating huge zooms by clicking too near the centre of the image. \n" "

\n" "

\n" " An ALT-SHIFT-middle drag is similar but anisotropic: the scaling \n" " may be different in X and Y. Warning: this technique is very \n" " sensitive and can be quite tricky to use! In particular, \n" " if you initially click near the centre axes of the image the zoom factor \n" " can be HUGE, so the best way to start using this is to click about halfway \n" " on a diagonal between the image centre and a corner and gently move in and \n" " out radially. Dragging from one side of the image to the other flips it over \n" " (the degenerate case of infinite zoom at the centre is handled cleanly I think). \n" " If it all goes horribly wrong, undo and try again. \n" "

\n" "

\n" " A CTRL-middle drag rotates the image about its centre. \n" "

\n" "

\n" " A CTRL-ALT-middle drag shears the image (the best way to see what \n" " this does is to click in the corner of an image and move the mouse \n" " horizontally or vertically). \n" "

\n" "

Keyboard Control

\n" "\n" "

\n" " There are some keyboard shortcuts. \n" "

\n" "

Main Window

\n" "\n" "

\n" "

  • "r"/"t"/"x" perform various starts of reset/restart. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "q" quits the application. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "u" (and also Ctrl-z) does an undo. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "f": full-screen mode (on X11, Qt does this by asking the \n" " window manager for a screen-filling undecorated window, and the \n" " documentation contains some dire warnings about problems with broken \n" " window managers). See also "-F" command line option. \n" " Fullscreen mode propagates to enlarged image display windows. \n" " NB The application may completely disappear from the screen for \n" " a brief interval while switching mode. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • "m" : hides status and menu-bar hiding, which can be nice when \n" " in full-screen or window-maximised mode. See also "-M" \n" " command line option. Also note that while the menu bar \n" " is hidden, most of these keyboard shortcuts won't function \n" " as they're tied to the menu system. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • Esc : exits full-screen and/or menu-hiding mode, putting the \n" " application into its normal default state. \n" "
  • \n" "
\n" "

\n" "

Enlargement Windows

\n" "

\n" " The image display windows created by selecting "Enlarge" from a \n" " context menu also have a couple of keyboard operations: \n" "

\n" "

\n" "

  • "f" : [NB only available with fullscreen build option] toggles \n" " full-screen mode. When returning to normal mode, if the main app \n" " window was fullscreen then it will also drop back to normal mode. \n" "
  • \n" "
\n" "

\n" "

\n" "

  • Esc : [NB only available with fullscreen build option] \n" " completely closes a fullscreen-mode enlargement window. \n" "
  • \n" "
\n" "

\n" "

Gui Elements

\n" "\n" "

Main Menu Bar

\n" "

\n" "

  • File menu: \n" " Items to restart, reset and quit the application. \n" " The difference between restart and reset is that reset \n" " sets the mutation parameters back the their default values. \n" " The "randomize function weights" version of restart scrambles \n" " the relative probability of the various function types (if you \n" " think evolvotron just keeps generating the same kinds of \n" " images give it a try). The "restart with specifc function" \n" " item duplicates the functionality of the "-x" and "-X" command-line \n" " options. \n" "
  • Edit menu: \n" " "Undo" lets you undo certain actions: e.g spawn, \n" " middle-button adjustment, simplification and lock/unlock. \n" " There is a large but limited number of levels of undo. \n" " "Simplify" is of curiosity value only: it prunes redundant \n" " branches from images ("junk DNA"); this may help them recompute \n" " faster but at the cost of there being less mutatable material. \n" "
  • Settings menu: \n" " "Mutations" brings up a dialog to modify the amount \n" " of change spawned images are subject to. \n" " (See "advanced usage" below.) \n" " "Functions" brings up a dialog to modify the relative probability \n" " of functions being used. By default all functions are equally \n" " likely except for iterative functions and fractals, which are \n" " almost but not completely supressed. But if you think there \n" " are too many spirals or grids (or not enough fractals) then this \n" " is the place to adjust the frequency with which they appear. \n" " If the software was built with the fullscreen option, \n" " that can also be controlled from this menu. \n" " "Favourite" brings up a dialog which allows you to select a specific \n" " function type to always be used as the root node of any new functions. \n" " The function can be wrapped by some other random stuff, or unwrapped. \n" " See also the -X and -x command line options. \n" "
  • Help menu: \n" " Items to bring up documentation, and the usual "About" box \n" " (which includes the license). \n" "
  • \n" "
\n" "

\n" "

Status Bar

\n" "

\n" " An area on the status bar shows how many compute "tasks" are \n" " outstanding (or "Ready" when there are none). When two task \n" " totals are reported, the first is for the main grid and the \n" " second for any enlargements being computed. \n" " Each "task" is the recomputation of an image at some resolution. \n" " Tasks are prioritised by their number of pixels (small image \n" " implies higher priority). This is why, if the main grid is still \n" " recomputing, recalculations of enlargements will appear to freeze \n" " after they have reached a certain resolution, at least until other \n" " lower resolution tasks have completed. \n" "

\n" "

\n" " The status bar also provides some control over the "autocool" \n" " mechanism which reduces mutation strength with time. \n" " See the advanced usage section below. \n" "

\n" "

Tips

\n" "

\n" "

  • Don't start a session with any preconceived ideas about the kind \n" " of image you want to get out of it. You will be disappointed. \n" "
  • I get the best results when I click the image which most \n" " immediately catches my eye as they start appearing. If you stop \n" " to think about it too much then things seem to go downhill. \n" "
  • If you seem to be just getting the same old spirals and grids \n" " all the time, stop clicking on spirals and grids! \n" " (The same goes for random mush). \n" "
  • Don't get too hung up on using the warp and middle-mouse drag \n" " adjustments every iteration... use those tools for final \n" " polishing of your masterpiece. \n" "
  • You can quickly cycle through a lot of initial images (until \n" " you find one with real potential) by bashing on Ctrl-r to \n" " repeatedly restart. \n" "
  • To add variety to an image's mutations, nudge it with a small \n" " middle-mouse drag. This introduces a top level transform, and \n" " therefore more parameters to be varied. \n" "
  • Enlargements take a long time to complete their final \n" " high-resolution rendering pass (especially with multisampling \n" " enabled). Most convenient practice seems to be to go away and \n" " leave them to complete, then come back and save them later. \n" " Continuing to click away on the main grid effectively starves \n" " them of CPU, unless the -E command-line option is used. \n" "
  • \n" "
\n" "

\n" "

Animation

\n" "

\n" " As of version 0.2.0 evolvotron contains some experimental support \n" " for generation of animations (although so far the results have been \n" " pretty disappointing IMHO, but it's still early days). \n" "

\n" "

\n" " NB THIS IS EVEN MORE COMPUTATIONALLY AND MEMORY INTENSIVE THAN \n" " THE STATIC IMAGE MODE. \n" "

\n" "

\n" " Simply supply a -f frames command line option and evolvotron will \n" " generate animated sequences with the specified number of frames. \n" " These will be displayed at the frame rate specified by the \n" " optional -s framerate option (default 8). So "evolvotron -s 24" \n" " will generate 3 second long animations. Animations reverse direction \n" " at each end to avoid a sudden jump. \n" "

\n" "

\n" " If you save an animation as PPM or PNG, multiple files will \n" " be saved with .fnnnnnn (where nnnnnn is the zero-filled frame \n" " number) inserted in each filename before the filetype qualifier. \n" "

\n" "

\n" " For example, if you enter foo.ppm as the filename to save, \n" " files foo.f000000.ppm, foo.f000001.ppm... will be saved. \n" " If you have the ImageMagick tools you can convert these to \n" " an animated GIF playing at approx. 8 frames per second with: \n" "

\n" "

\n" " convert -delay 12 foo.f??????.ppm foo.gif \n" "

\n" "

Advanced Usage

\n" "

\n" " Evolvotron's idea of an image is a function which converts \n" " XYZ co-ordinates to an RGB colour (however we can only display \n" " a 2D plane for now so the input Z is fixed to zero, or varied \n" " with time when animating). \n" "

\n" "

\n" " The image functions are constructed from trees of function nodes. \n" " (In the mathematical expression 1+(2*x) the "+" and the "*" would \n" " be function nodes.) Evolvotron's functions tend to correspond to \n" " geometric or colour-space operations or anything else which can be \n" " applied to a 3D vector. \n" "

\n" "

\n" " By mutating the structure of the function tree (adding random \n" " branches, for example) and the values of the constant embedded \n" " within it, the image can be changed. \n" "

\n" "

\n" " The mutation parameters are under control from the dialogs accessible \n" " via the Settings menu, and the "autocool" mechanism exposed in the \n" " status bar also has some influence. \n" "

\n" "

\n" " There are two kinds of mutation: perturbations to the magnitude of constants, \n" " and structural mutations which rearrage the function tree of an image. \n" " Four types of structural mutations are currently implemented: \n" "

  • replacement of a function branch by a new random stub (a "Glitch" mutation). \n" "
  • a random shuffle of a node's sub-nodes \n" "
  • insertion of random nodes between a node and it's sub-nodes \n" "
  • the substitution of a node with one of a different type, \n" " with sub-nodes unaffected where possible). \n" "
  • \n" "
\n" "

\n" "

\n" " The probability (per function node) of these mutations is controlled \n" " from spinboxes on the "Mutation Parameters" dialog (expressed as \n" " chances-in-a-hundred), as is the size of perturbations to constants. \n" "

\n" "

\n" " It is useful to think of the perturbations to constant parameters as \n" " being a thermal effect (hence the "heat" and "cool" buttons), while \n" " structural alterations are more drastic and are caused by high energy \n" " gamma rays or something (hence "irradiate" and "shield" buttons to \n" " adjust the probability of structual mutations). \n" "

\n" "

\n" " So why would you want to change the mutation parameters from the initial \n" " defaults ? Basically, if you're getting too much variation in spawned images \n" " (this tends to happen after many generations of images, by which time the \n" " function trees have grown quite large and therefore are experiencing a lot \n" " of mutations) then cool and/or shield. \n" " If all the images look too similar, heat and/or irradiate. \n" "

\n" "

\n" " The "autocool" mechanism (enabled from the statusbar or mutation parameters \n" " dialog) automatically reduces the strength of mutations from the base \n" " values with successive generations. The cooling can be cancelled by \n" " disabling autocooling or pressing the "Reheat" button to zero the number \n" " of generations counted for cooling. The effect of the cooling is a compound \n" " halving of the mutation strength after some number of generations (this number \n" " is the "half-life" controllable from the mutation parameters dialog). \n" " Note that if autocooling is enabled then eventually, after a number of \n" " iterations more than many multiples of the half-life has passes, spawned \n" " images will differ very little from their parents (hence the need for "reheat"). \n" "

\n" "

\n" " There is also a dialog accessible from "Functions..." on the "Settings" menu. \n" " This allows control over the relative proportions in which functions occur. \n" " There is a tab showing the relative weighting of all functions (log-2 scale: each \n" " tick halves the probability of the function occurring), and additional tabs \n" " for various classifications of function for quicker access. \n" " The "Randomize" button on each tab assigns random weightings and helps \n" " increase the uniqueness of your session. \n" "

\n" "

\n" " The "Functions" dialog also has a "Dilution" tab which allows the average \n" " function-tree branching ratio to be controlled (by changing the proportion \n" " of trivial zero-branch functions added): note that using a high branching \n" " ratio results in very complex images which will take a long time to compute, \n" " while reducing the ratio results in simple, boring images. \n" "

\n" "

\n" " 3 types of function node are considered fundamental: constant nodes \n" " (which return a constant), identity nodes (which return their \n" " position argument) and transform nodes (which transform their positon \n" " argument by random parameters). On the "Dilution" tab of the "Functions" \n" " dialog there are two slider controls to affect things related to these: \n" "

  • "proportion constant" controls the proportion of diluting fundamental nodes \n" " which are constants. Changing this from its default value of 0.5 doesn't \n" " actually seem to have much effect. \n" "
  • "proportion transforms" sets the proportion of non-constant nodes diluting \n" " which are transforms (as opposed to identity nodes). \n" " The main effect of this is that images are less commonly obviously centred \n" " on the origin or aligned with the axes. I think this is a good thing, so \n" " the value is at 1.0 by default. \n" "
  • \n" "
\n" "

\n" "

Other Executables

\n" "

\n" " This release also builds some other command-line driven (non-GUI, non-interactive) utilities. \n" " Consult the man pages for full details. \n" "

\n" "

\n" " evolvotron_render reads a XML function description from its standard input and renders it to the \n" " file specified. \n" "

\n" "

\n" " evolvotron_mutate reads an XML function description from its standard input and outputs a mutated version. \n" " A command line option allows the "genesis" situation of creating a random function description with no input. \n" "

\n" "

Examples

\n" "\n" "

\n" " Evolving and mutating on the command line: \n" "

\n" "

\n" " evolvotron_mutate -g | tee fn.xml | evolvotron_render /tmp/xxx.ppm ; display /tmp/xxx.ppm \n" "

\n" "

\n" " cat fn.xml | evolvotron_mutate | evolvotron_render -j -m 4 /tmp/xxx.ppm ; display /tmp/xxx.ppm \n" "

\n" "

\n" " Animating a function ani.xml saved from evolvotron in animation mode: \n" "

\n" "

\n" " cat ani.xml | evolvotron_render -f 100 -v -s 256 256 ani.ppm ; animate ani.f??????.ppm \n" "

\n" "

Future Developments

\n" "

\n" " Please check the TODO file first before you send me suggestions! \n" "

\n" "

\n" " Please don't ask me to port evolvotron to proprietary platforms. \n" " You are of course Free under the terms of the GPL to do so yourself, \n" " but please read \n" " http://www.fefe.de/nowindows/ \n" " first. \n" "

\n" "

Thanks

\n" "

\n" " To those who have contributed feedback, suggestions and patches: \n" "

  • Dmitry Kirsanov \n" "
  • Jonathan Melhuish \n" "
  • Karl Robillard \n" "
  • Linc Davis \n" "
  • Paolo Greppi \n" "
  • Marcin Wojtczuk \n" "
  • Michael Sterrett \n" "
  • Massimiliano Guastafierro \n" "
  • Goetz Waschk \n" "
  • Forrest Walter \n" "
  • \n" "
\n" "

\n" "

\n" " And to the anonymous Linspire reviewer who perhaps came up with the best \n" " summary of evolvotron yet: "Fascinating. Utterly pointless, but fascinating." \n" "

\n" "

\n" " The friezegroups wouldn't have been possible without \n" " http://michaelshepperd.tripod.com/resources/groups.html \n" "

\n" "

\n" " Thanks to www.di.fm, www.somafm.com and Trance4Ever for music to code to. \n" "

\n" "

\n" " Thanks especially to a SIGGRAPH conference panel many years ago (likely \n" " including Karl Sims, the pioneer in this area) who first got me interested \n" " in this stuff. \n" "

\n" "

Why ?

\n" "

\n" " I have always admired those who have the skill to wield a pen or paintbrush \n" " and fill a sheet of paper or a canvas with some striking image from their \n" " imagination. Unfortunately I lack the patience to learn such skills, \n" " and probably the necessary manual dexterity and imagination too. \n" "

\n" "

\n" " Evolvotron, and several predecessors developed on and off over a decade \n" " since I first came across the idea, are an attempt to compensate for \n" " this using the skills I do have i.e some mathematical sensibility \n" " and the ability to write working code (well, sometimes). If you like \n" " an image it produces, then as far as I'm concerned that's as satisfying \n" " a result as if you liked something I'd drawn myself. \n" "

\n" "

\n" " Tim Day \n" evolvotron/libevolvotron/dialog_favourite.h0000644000175100017510000000602712100750252021234 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class DialogFavourite. */ #ifndef _dialog_favourite_h_ #define _dialog_favourite_h_ class EvolvotronMain; //! Provides a dialog for controlling which functions are available. class DialogFavourite : public QDialog { private: Q_OBJECT protected: //! Owner. EvolvotronMain* _parent; //! Function name to be used as the root node of new image function tres (no favourite if empty) std::string _favourite_function; //! Flag specifying whether favourite function should be exposed bool _favourite_function_unwrapped; //! Map function names to combo box entries. std::map _favourite_fn_to_index; //! Look up function names from combo box. std::map _index_to_favourite_fn; //! Select favourite function, if any. QComboBox* _favourite; //! Controls unwrapped state. QCheckBox* _unwrapped; //! Make GUI match _favourite_function and _favourite_function_unwrapped state void update_gui_from_state(); protected slots: //! Invoked on combo-box selection. void changed_favourite(int i); //! Invoked on checkbox toggle. void changed_unwrapped(bool b); public: //! Constructor. DialogFavourite(EvolvotronMain* parent); //! Destructor. ~DialogFavourite(); //! Accessor const std::string& favourite_function() const { return _favourite_function; } //! Accessor. Returns true if function name recognised. bool favourite_function(const std::string& f); //! Accessor. bool favourite_function_unwrapped() const { return _favourite_function_unwrapped; } //! Accessor. void favourite_function_unwrapped(bool v); }; #endif evolvotron/libevolvotron/dialog_about.h0000644000175100017510000000344012100750252020336 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class DialogAbout. */ #ifndef _dialog_about_h_ #define _dialog_about_h_ //! Provides an "About" dialog box. /*! About dialog displays author info, web addresses and license info. */ class DialogAbout : public QDialog { private: Q_OBJECT public: //! Constructor. DialogAbout(QWidget* parent,int n_threads,bool separate_farm_for_enlargements); //! Destructor. ~DialogAbout(); }; #endif evolvotron/libevolvotron/dialog_render_parameters.h0000644000175100017510000000527212100750252022733 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class DialogRenderParameters. */ #ifndef _dialog_render_parameters_h_ #define _dialog_render_parameters_h_ #include "render_parameters.h" //! Provides an dialog box for controlling RenderParameters. class DialogRenderParameters : public QDialog { private: Q_OBJECT protected: //! Instance of MutationParameters under dialog control. /*! NB it's fairly important no-one modifies this except through methods of this class (or another class responsible for another part), else GUI components will get out of sync */ RenderParameters*const _render_parameters; //! Enables jittered samples. QCheckBox* _checkbox_jittered_samples; //! Chooses between multisampling levels. QWidget* _buttonvbox; //! Chooses between multisampling levels. QButtonGroup* _buttongroup; //! Button to close dialog. QPushButton* _ok; //! Reload from _render_parameters. void setup_from_render_parameters(); public: //! Constructor. DialogRenderParameters(QMainWindow* parent,RenderParameters* rp); //! Destructor. ~DialogRenderParameters(); public slots: //! Signalled by checkbox. void changed_jittered_samples(int buttonstate); //! Signalled by radio buttons. void changed_oversampling(int id); //! Signalled by mutation parameters void render_parameters_changed(); }; #endif evolvotron/libevolvotron/mutatable_image_display.h0000644000175100017510000002231212100750252022551 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class MutatableImageDisplay */ #ifndef _mutatable_image_display_h_ #define _mutatable_image_display_h_ #include "mutatable_image.h" #include "mutatable_image_computer.h" #include "dialog_mutatable_image_display.h" class EvolvotronMain; class MutatableImageComputerTask; //! Widget responsible for displaying a MutatableImage. /*! A MutatableImageDisplay is responsible for displaying the image computed from the MutatableImage it owns. Computations are split off into separate threads to take advantage of multiprocessor machines. */ class MutatableImageDisplay : public QWidget { Q_OBJECT protected: //! Pointer back to the application object to access services. EvolvotronMain* _main; //! Flag for whether context menu should display all options. /*! false also implies a standalone window */ const bool _full_functionality; //! Flag for whether the offscreen buffer has fixed size const bool _fixed_size; //! Size of offscreen buffer QSize _image_size; //! Number of frames in image uint _frames; //! Framerate for animation. uint _framerate; //! Currently displaying frame. uint _current_frame; //! Direction to play bool _animate_reverse; //! Timer for animating frames QTimer* _timer; //! Flag indicating resize is in progress (between resizeEvent and subsequent paintEvent). /*! Used to supress unnecessary task spawning. */ bool _resize_in_progress; //! The resolution level currently displaying (0=1-for-1 pixels, 1=half resolution etc). /*! Needed to handle possible out of order task returns from multiple compute threads. */ uint _current_display_level; //! Similar to _current_display_level, but for tracking multisample grids within a resolution level. uint _current_display_multisample_grid; //! An image suitable for setting as an icon. std::auto_ptr _icon; //! Track which image the icon is actually of. unsigned long long int _icon_serial; //! Offscreen image buffer. std::vector _offscreen_pixmaps; //! Offscreen image buffer in sensible image format (used for save, as pixmap is in display format which might be less bits). std::vector _offscreen_images; //! Type for staging area for incoming fragments. /*! Key is level and multisampling, mapped type is also itself a map from fragment number to tasks. */ typedef std::map,std::map > > OffscreenImageInbox; //! Staging area for incoming fragments. /*! Fragments are accumulated for each (level,multisample) key, and completed levels passed on for display */ OffscreenImageInbox _offscreen_images_inbox; //! The image function being displayed (its root node). /*! The held image is const because references to it could be held by history archive, compute tasks etc, so it should be completely replaced rather than manipulated. */ boost::shared_ptr _image_function; //! Properties dialog. DialogMutatableImageDisplay* _properties; //! Context (right-click) menu. QMenu* _menu; //! Submenu for spawn warped options. QMenu* _menu_warped; //! Submenu for Big image options. QMenu* _menu_big; //! Position of item in menu. /*! This is the only menu item we need to retain this information for becuase we need it to set the lock check-mark. */ QAction* _menu_item_action_lock; //! Coordinate of mouse event which started mid-button adjustment QPoint _mid_button_adjust_start_pos; //! Coordinate of last mouse event when mid-button adjusting QPoint _mid_button_adjust_last_pos; //! Serial number to kill some rare problems with out-of-order tasks being returned unsigned long long int _serial; public: //! Constructor. MutatableImageDisplay(EvolvotronMain* mn,bool full_functionality,bool fixed_size,const QSize& image_size,uint f,uint fr); //! Destructor. virtual ~MutatableImageDisplay(); //! Accessor. const boost::shared_ptr& image_function() { return _image_function; } //! Accessor. bool locked() const { return (_image_function.get()!=0 ? _image_function->locked() : false); } //! Accessor. EvolvotronMain& main() const { assert(_main!=0); return *_main; } //! Accessor. void main(EvolvotronMain* m) { _main=m; } //! Accessor. const QSize& image_size() const { return _image_size; } //! Load a new image (clears up old image, starts new compute tasks). /*! When the one_of_many parameter is true, it implies many other images are also being updated (affects fragmentation strategy for multithreading). */ void image_function(const boost::shared_ptr& image_fn,bool one_of_many); //! Evolvotron main calls this with completed (but possibly aborted) tasks. void deliver(const boost::shared_ptr& task); //! Set the lock state. void lock(bool l,bool record_in_history); protected: //! Which farm this display should use. MutatableImageComputerFarm& farm() const; //! Usual handler for repaint events. virtual void paintEvent(QPaintEvent* event); //! Usual handler for resize events. virtual void resizeEvent(QResizeEvent* event); //! Handler for mouse events. virtual void mousePressEvent(QMouseEvent* event); //! Handler for mouse events. virtual void mouseMoveEvent(QMouseEvent* event); public slots: //! Simplify the held image, return the number of nodes eliminated uint simplify_constants(bool single); //! Load a function from the given filename. void load_function_file(const QString&); protected slots: //! Called by timer void frame_advance(); //! Called from context menu. void menupick_respawn(); //! Called from context menu and also by click event. void menupick_spawn(); //! Called from context menu. void menupick_spawn_recoloured(); //! Called from context menu. void menupick_spawn_warped_random(); //! Called from context menu. void menupick_spawn_warped_zoom_in(); //! Called from context menu. void menupick_spawn_warped_zoom_out(); //! Called from context menu. void menupick_spawn_warped_rotate(); //! Called from context menu. void menupick_spawn_warped_pan_xy(); //! Called from context menu. void menupick_spawn_warped_pan_x(); //! Called from context menu. void menupick_spawn_warped_pan_y(); //! Called from context menu. void menupick_spawn_warped_pan_z(); //! Called from context menu. void menupick_lock(); //! Trivial wrapper for simplify_constants void menupick_simplify(); //! Called from context menu. void menupick_save_image(); //! Called from context menu. void menupick_save_function(); //! Called from context menu. void menupick_load_function(); //! Called from "Big" submenu of context menu. void menupick_big_resizable(); //! Called from "Big" submenu of context menu. void menupick_big_256x256(); //! Called from "Big" submenu of context menu. void menupick_big_512x512(); //! Called from "Big" submenu of context menu. void menupick_big_768x768(); //! Called from "Big" submenu of context menu. void menupick_big_1024x1024(); //! Called from "Big" submenu of context menu. void menupick_big_640x480(); //! Called from "Big" submenu of context menu. void menupick_big_1024x768(); //! Called from "Big" submenu of context menu. void menupick_big_1280x960(); //! Called from "Big" submenu of context menu. void menupick_big_1600x1200(); //! Called from "Big" submenu of context menu. void menupick_big_2048x2048(); //! Called from "Big" submenu of context menu. void menupick_big_4096x4096(); //! Called from "Properties" on context menu void menupick_properties(); protected: //! Common code for big slots. void spawn_big(bool scrollable,const QSize& sz); }; #endif evolvotron/libevolvotron/transform_factory.h0000644000175100017510000001112212100750252021443 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class TransformFactory. */ #ifndef _transform_factory_h_ #define _transform_factory_h_ class Random01; class Transform; //! Abstract base class for classes creating Transforms class TransformFactory { public: TransformFactory() {} virtual ~TransformFactory() {} //! Clone functionality needed to retain typed copies of factories. virtual std::auto_ptr clone() const =0; //! Method to build a Transform. virtual const Transform operator()(Random01&) const =0; protected: }; //! Factory for creating random warps /*! These are the mixed scale/rotate/translate ones used by the combo warp. */ class TransformFactoryRandomWarpXY : public TransformFactory { public: //! Constructor accepts power-of-2 specifiers, so -1 & 1 would generate scalings between 0.5 and 2, half zooming in and half zooming out. // Constructor. /*! \todo Should be parameterised with parameters specified at point of usage in MutatableImageDisplay */ TransformFactoryRandomWarpXY() {} //! Clone. virtual std::auto_ptr clone() const { return std::auto_ptr(new TransformFactoryRandomWarpXY()); } //! Return a random transform. virtual const Transform operator()(Random01& rng) const; protected: }; //! Factory for creating random scaling transforms class TransformFactoryRandomScaleXY : public TransformFactory { public: //! Constructor accepts power-of-2 specifiers, so -1 & 1 would generate scalings between 0.5 and 2, half zooming in and half zooming out. TransformFactoryRandomScaleXY(real lopow2,real hipow2) :_lopow2(lopow2),_hipow2(hipow2) {} //! Clone method. virtual std::auto_ptr clone() const { return std::auto_ptr(new TransformFactoryRandomScaleXY(_lopow2,_hipow2)); } //! Return a random scaling transform. virtual const Transform operator()(Random01& rng) const; protected: //! The low end of the scaling as a power of 2 real _lopow2; //! The high end of the scaling as a power of 2 real _hipow2; }; //! Factory for creating random z-axis rotation transforms class TransformFactoryRandomRotateZ : public TransformFactory { public: //! Constructor TransformFactoryRandomRotateZ() {} //! Clone method. virtual std::auto_ptr clone() const { return std::auto_ptr(new TransformFactoryRandomRotateZ()); } //! Create a transform. virtual const Transform operator()(Random01& rng) const; protected: }; //! Factory for creating random translation transforms class TransformFactoryRandomTranslateXYZ : public TransformFactory { public: //! Constructor accepts XYZ origin (centre) and range (+/-) TransformFactoryRandomTranslateXYZ(const XYZ& o,const XYZ& r) :_origin(o) ,_range(r) {} //! Clone method. virtual std::auto_ptr clone() const { return std::auto_ptr(new TransformFactoryRandomTranslateXYZ(_origin,_range)); } //! Return a random Transform virtual const Transform operator()(Random01& rng) const; protected: //! Base value for translations XYZ _origin; //! Range for translations XYZ _range; }; #endif evolvotron/libevolvotron/libevolvotron_precompiled.h0000644000175100017510000000470312100750277023206 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Precompiled header for libevolvotron Could load this up with Qt headers maybe. */ #ifndef _libevolvotron_precompiled_h_ #define _libevolvotron_precompiled_h_ #include "libfunction_precompiled.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define stringify(S) __STRING(S) #endif evolvotron/libevolvotron/render_parameters.h0000644000175100017510000000504512100750252021412 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class RenderParameters */ #ifndef _render_parameters_h_ #define _render_parameters_h_ template bool change(T& dst,const T& src) { const T previous=dst; dst=src; return (dst!=previous); } //! Class encapsulating things affecting rendering class RenderParameters : public QObject { Q_OBJECT; public: RenderParameters(bool jitter,uint multisample,QObject* parent); ~RenderParameters(); //! Accessor. bool jittered_samples() const { return _jittered_samples; } //! Accessor. void jittered_samples(bool v) { if (change(_jittered_samples,v)) report_change(); } //! Accessor. uint multisample_grid() const { assert(_multisample_grid>=1); return _multisample_grid; } //! Accessor. void multisample_grid(uint v) { assert(v>=1); if (change(_multisample_grid,v)) report_change(); } signals: void changed(); protected: void report_change(); private: //! Whether sample points should be randomized. bool _jittered_samples; //! Grid for multisampling. /*! Default is 1. 4 would be 16 samples in a 4x4 grid. */ uint _multisample_grid; }; #endif evolvotron/libevolvotron/dialog_mutation_parameters.h0000644000175100017510000001031012100750252023301 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class DialogMutationParameters. */ #ifndef _dialog_mutation_parameters_h_ #define _dialog_mutation_parameters_h_ #include "mutation_parameters_qobject.h" //! Provides an dialog box for controlling MutationParameters. class DialogMutationParameters : public QDialog { private: Q_OBJECT typedef QDialog Superclass; protected: //! Scale to spinbox's integer values. const int _scale; //! Owner of dialog (probably EvolvotronMain), used to access a statusbar. QMainWindow*const _parent; //! Instance of MutationParameters under dialog control. /*! NB it's fairly important no-one modifies this except through methods of this class (or another class responsible for another part), else GUI components will get out of sync */ MutationParametersQObject*const _mutation_parameters; //! Tabs for base parameters and autocool QTabWidget* _tabs; //! Tab for base mutation parameter controls QWidget* _vbox_base_mutation; //! Grid for buttons; QWidget* _grid_buttons; //! Grid for base parameter control spinners QWidget* _grid_base_mutation; //! Group for autocool parameters QWidget* _vbox_autocool; //! Grid for autocool parameters QWidget* _grid_autocool; //! Label to show number of generations QLabel* _label_autocool_generations; //! Button to reheeat autocooling QPushButton* _button_autocool_reheat; //@{ //! Button for quick adjustment of MutationParameters QPushButton* _button_reset; QPushButton* _button_cool; QPushButton* _button_heat; QPushButton* _button_shield; QPushButton* _button_irradiate; //@} //@{ //! Spinners for detailed control of specific parameters QSpinBox* _spinbox_magnitude; QSpinBox* _spinbox_parameter_reset; QSpinBox* _spinbox_glitch; QSpinBox* _spinbox_shuffle; QSpinBox* _spinbox_insert; QSpinBox* _spinbox_substitute; QSpinBox* _spinbox_autocool_halflife; //@} //! Control autocooling QCheckBox* _checkbox_autocool_enable; //! Button to close dialog. QPushButton* _ok; //! Reload spinboxes from _mutation_parameters. void setup_from_mutation_parameters(); public: //! Constructor. DialogMutationParameters(QMainWindow* parent,MutationParametersQObject* mp); //! Destructor. ~DialogMutationParameters(); public slots: //@{ //! Signalled by button. void reset(); void heat(); void cool(); void irradiate(); void shield(); void reheat(); //@} //! Signalled by checkbox. void changed_autocool_enable(int buttonstate); //@{ //! Signalled by spinbox. void changed_magnitude(int v); void changed_parameter_reset(int v); void changed_glitch(int v); void changed_shuffle(int v); void changed_insert(int v); void changed_substitute(int v); void changed_autocool_halflife(int v); //@} //! Signalled by mutation parameters void mutation_parameters_changed(); }; #endif evolvotron/libevolvotron/dialog_mutatable_image_display.h0000644000175100017510000000451112100750252024071 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class DialogMutatableImageDisplay. */ #ifndef _dialog_mutatable_image_display_h_ #define _dialog_mutatable_image_display_h_ //! Provides a "Properties" style dialog box for manipulating /*! Make this modal for simplicity: avoids spawned images changing underneath us, and the possibility of opening one for every display. */ class DialogMutatableImageDisplay : public QDialog { private: Q_OBJECT protected: //! Tabs for info and xml (summary and detail) QTabWidget* _tabs; //! Message displaying some info about the image. QLabel* _label_info; //! Scrolling text area for XML description. QTextEdit* _textedit_xml; //! Button to close dialog. QPushButton* _ok; public: //! Constructor. DialogMutatableImageDisplay(QWidget* parent); //! Destructor. ~DialogMutatableImageDisplay(); //! Set content of main text and scrolling area. void set_content(const std::string& m,const std::string& x); }; #endif evolvotron/libevolvotron/dialog_functions.h0000644000175100017510000001032412100750277021242 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class DialogFunctions. */ #ifndef _dialog_functions_h_ #define _dialog_functions_h_ #include "mutation_parameters_qobject.h" class EvolvotronMain; //! Utility class for DialogFunctions. Expands changed(int) to changed(src,int) /*! Would ideally live in dialog_functions.cpp, but that causes (moc-related?) problems with linking; seems to need wider visibility. \todo Move to own file and only include in dialog_functions.cpp */ class SignalExpanderValueChangedQSlider : public QObject { private: Q_OBJECT QSlider*const _src; public: SignalExpanderValueChangedQSlider(QObject* parent,QSlider* src) :QObject(parent) ,_src(src) {} public slots: void valueChanged(int v) { emit valueChanged(_src,v); } signals: void valueChanged(QSlider*,int); }; //! Similar to SignalExpanderQSlider except attaches an integer argument to the clicked signal class SignalExpanderClickedUint : public QObject { private: Q_OBJECT uint _arg; public: SignalExpanderClickedUint(QObject* parent,uint arg) :QObject(parent) ,_arg(arg) {} public slots: void clicked() { emit clicked(_arg); } signals: void clicked(uint); }; //! Provides a dialog for controlling which functions are available. class DialogFunctions : public QDialog { private: Q_OBJECT protected: //! Owner of dialog EvolvotronMain*const _parent; //! Instance of MutationParameters under dialog control. /*! \warning Careful of modifying things which might make DialogMutationParameters get out of sync */ MutationParametersQObject*const _mutation_parameters; //! Top level holder of all the dialog content. QWidget* _dialog_content; //! Notification of undiluted branching ratio. QLabel* _branching_ratio; //! Required branching ratio after dilution QSlider* _slider_target_branching_ratio; //! Proportion of diluting nodes which are pure constants QSlider* _slider_proportion_constant; //! Proportion of non-constant nodes which are 12-parameter transforms QSlider* _slider_identity_supression; //! Lookup from each slider in the weighting controls area to corresponding function. std::map _slider_to_function; public: //! Constructor. DialogFunctions(EvolvotronMain* parent,MutationParametersQObject* mp); //! Destructor. ~DialogFunctions(); //! Reload from _mutation_parameters void setup_from_mutation_parameters(); protected slots: //@{ //! Signalled by sliders. void changed_target_branching_ratio(int v); void changed_proportion_constant(int v); void changed_identity_supression(int v); void changed_function_weighting(QSlider*,int v); //@} //! Signalled by randomization methods void clicked_button_rand(uint mask); public slots: //! Signalled by mutation parameters void mutation_parameters_changed(); }; #endif evolvotron/libevolvotron/mutatable_image_display_big.h0000644000175100017510000000451112100750277023402 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class MutatableImageDisplayBig */ #ifndef _mutatable_image_display_big_h_ #define _mutatable_image_display_big_h_ class EvolvotronMain; //! Intended to be used as a top-level widget holding a single MutatableImageDisplay /*! We just used to use a display or scroll view itself as a top-level widget, but need this to get some specific keyboard effects. \todo class name is a bit misleading. This is really just a slightly modified top-level holder. */ class MutatableImageDisplayBig : public QWidget { Q_OBJECT protected: //! Pointer back to the application object to access fullscreen state EvolvotronMain* _main; public: //! Constructor. MutatableImageDisplayBig(EvolvotronMain* mn); //! Destructor. virtual ~MutatableImageDisplayBig(); //! Accessor. EvolvotronMain* main() const { assert(_main!=0); return _main; } protected: //! Handle key-presses void keyPressEvent(QKeyEvent* e); }; #endif evolvotron/libevolvotron/platform_specific.h0000644000175100017510000000365712100750252021410 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Try to isolate platform specific code here (or rather, in the .cpp implementations) */ #ifndef _platform_specific_h_ #define _platform_specific_h_ // qt3 for Darwin appears to define this, so use it to definitely select the PLATFORM_BSD option #ifdef __DARWIN_X11__ #define PLATFORM_BSD #undef PLATFORM_LINUX #endif //! Return the number of processors on the system extern uint get_number_of_processors(); //! Lower the priority of the calling thread by increasing its "niceness" (unix 0-19 'nice' scale used) extern void add_thread_niceness(uint); #endif evolvotron/libevolvotron/mutatable_image_computer.h0000644000175100017510000001360012100750252022742 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class MutatableImageComputer. */ #ifndef _mutatable_image_computer_h_ #define _mutatable_image_computer_h_ #include "mutatable_image.h" #include "random.h" class MutatableImageDisplay; class MutatableImageComputerFarm; class MutatableImageComputerTask; //! Class to handle computing of MutatableImages in a separate thread. /*! A compute task starts up and fetches work from it's parent farm. The parent farm thread can communicate when necessary using the public methods of the class. */ class MutatableImageComputer : public QThread #ifndef NDEBUG , public InstanceCounted #endif { protected: //! Pointer to compute farm of which this thread is part. MutatableImageComputerFarm*const _farm; //! Priority offset applied to compute threads. const int _niceness; //! The current task. Can't be a const MutatableImageComputerTask because the task holds the calculated result. boost::shared_ptr _task; //! Randomness for sampling jitter Random01 _r01; //! Class encapsulating mutex-protected flags used for communicating between farm and worker. /*! The Mutex is of dubious value (could certainly be eliminated for reads). */ class Communications { protected: //! Mutex protecting access to members (mutable to enable const-ness of accessors). mutable QMutex _mutex; //! Flag to indicate we should put our current task back on the todo queue and take another one. /*! volatile because used for inter-thread communication. */ volatile bool _defer; //! Flag to indicate we should abort the current compute. /*! volatile because used for inter-thread communication. */ volatile bool _abort; //! Flag to indicate the thread should shut down and exit. /*! volatile because used for inter-thread communication. */ volatile bool _kill; public: //! Constructor. /*! Mutex is recursive to allow nesting. */ Communications() :_mutex() ,_defer(false) ,_abort(false) ,_kill(false) {} //! Mutex-protected accessor. void defer(bool v) { QMutexLocker lock(&_mutex); _defer=v; } //! Mutex-protected accessor. bool defer() const { QMutexLocker lock(&_mutex); const bool ret=_defer; return ret; } //! Mutex-protected accessor. void abort(bool v) { QMutexLocker lock(&_mutex); _abort=v; } //! Mutex-protected accessor. bool abort() const { QMutexLocker lock(&_mutex); const bool ret=_abort; return ret; } //! Mutex-protected accessor. void kill(bool v) { QMutexLocker lock(&_mutex); _kill=v; } //! Mutex-protected accessor. bool kill() const { QMutexLocker lock(&_mutex); const bool ret=_kill; return ret; } //! Check union of all flags with only one mutex lock. bool kill_or_abort_or_defer() const { QMutexLocker lock(&_mutex); const bool ret=(_kill || _abort || _defer); return ret; } }; //! Instance of communications flags. Communications _communications; //! The actual compute code, launched by invoking start() in the constructor. virtual void run(); //! Accessor. Communications& communications() { return _communications; } //! Accessor. const Communications& communications() const { return _communications; } //! Accessor. const boost::shared_ptr& task() const { return _task; } //! Accessor. MutatableImageComputerFarm* farm() const { return _farm; } public: //! Constructor MutatableImageComputer(MutatableImageComputerFarm* frm,int niceness); //! Destructor ~MutatableImageComputer(); //! Defer the current task if it's priority is less important than specified. Returns true if deferrment occurred. bool defer_if_less_important_than(uint pri); //! This method called by an external threads to shut down the current task void abort(); //! This method called by an external threads to shut down the current task if it's for a particular display void abort_for(const MutatableImageDisplay* disp); //! This method called by external thread to kill the thread. void kill(); //! Return kill state. /*! Needs external visibility for deciding what to do when woken from wait for task. */ bool killed() const; //! Indicate whether computation us taking place (only intended for counting outstanding threads). bool active() const { return _task; } }; #endif evolvotron/libevolvotron/mutatable_image_computer_task.h0000644000175100017510000001564112100750277024002 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Interface for class MutatableImageComputerTask. */ #ifndef _mutatable_image_computer_task_h_ #define _mutatable_image_computer_task_h_ #include "mutatable_image.h" #include "mutatable_image_display.h" //! Class encapsulating all the parameters of, and output from, a single image generation run. class MutatableImageComputerTask #ifndef NDEBUG : public InstanceCounted #endif { protected: //! Flag indicating (to compute thread) that this task should be aborted. Also indicates to MutatableImageDisplay that it's a dud and shouldn't be displayed.. /*! \todo Think more about whether this needs to be mutex protected for sanity. */ bool _aborted; //! The display originating the task, and to which the output will be returned. MutatableImageDisplay*const _display; //! The root node of the image tree to be generated. /*! Constness of the MutatableImage referenced is important as the instance is shared between all tasks and the original display. */ const boost::shared_ptr _image_function; //! Task priority. /*! Low numbers go to the head of the queue. The total number of samples in the complete (non-fragmented) image is used, so small low resolution images which can be quickly completed are run first. */ const uint _priority; //! The origin (on the display) of the image being generated. const QSize _fragment_origin; //! The size of the image to be generated. const QSize _fragment_size; //! The full size of the image of which this is a fragment. const QSize _whole_image_size; //! Number of animation frames to be rendered const uint _frames; //! The resolution level of this image (0=1-for-1 pixels, 1=half res etc) /*! This is tracked because multiple compute threads could return the completed tasks out of order (Unlikely given the huge difference in the amount of compute between levels, but possible). */ const uint _level; //! The fragment number, used when a rendering job is split into multiple fragments. const uint _fragment; //! The number of fragments in the rendering job const uint _number_of_fragments; //! Whether samples should be jittered. const bool _jittered_samples; //! Multisampling grid resolution e.g 4 implies a 4x4 grid const uint _multisample_grid; //@{ //! Track pixels computed, so tasks can be restarted after defer. Row and column are relative to the fragment origin. uint _current_pixel; int _current_col; int _current_row; uint _current_frame; //@} //! The image data generated for the fragments. /*! This is lazily created to avoid multiple high resolution images (especially with multisampling) being unnecessarily concurrently allocated. */ mutable std::vector _images; //! Lazy allocator for _images (which is mutable) void allocate_images() const; //! Set true by pixel_advance when it advances off the last frame. bool _completed; //! Serial number, to fix some occasional out-of-order display problems unsigned long long int _serial; public: //! Constructor. MutatableImageComputerTask ( MutatableImageDisplay*const disp, const boost::shared_ptr& fn, uint pri, const QSize& fo, const QSize& fs, const QSize& wis, uint f, uint lev, uint frag, uint nfrag, bool j, uint ms, unsigned long long int n ); //! Destructor. ~MutatableImageComputerTask(); //! Accessor. bool aborted() const { return _aborted; } //! Mark task as aborted. void abort() { _aborted=true; } //! Accessor. MutatableImageDisplay* display() const { return _display; } //! Accessor. const boost::shared_ptr& image_function() const { return _image_function; } //! Accessor. const QSize& fragment_origin() const { return _fragment_origin; } //! Accessor. const QSize& fragment_size() const { return _fragment_size; } //! Accessor. const QSize& whole_image_size() const { return _whole_image_size; } //! Accessor. uint frames() const { return _frames; } //! Accessor. uint level() const { return _level; } //! Accessor. uint fragment() const { return _fragment; } //! Accessor. uint number_of_fragments() const { return _number_of_fragments; } //! Accessor. bool jittered_samples() const { return _jittered_samples; } //! Accessor. uint multisample_grid() const { return _multisample_grid; } //! Serial number unsigned long long int serial() const { return _serial; } //! Accessor. uint priority() const { return _priority; } //! Accessor, with lazy creation. std::vector& images() { if (_images.empty()) allocate_images(); return _images; } //! Accessor. const std::vector& images() const { if (_images.empty()) allocate_images(); return _images; } //! Accessor. uint current_col() const { return _current_col; } //! Accessor. uint current_row() const { return _current_row; } //! Accessor. uint current_frame() const { return _current_frame; } //! Accessor. uint current_pixel() const { return _current_pixel; } //!Accessor. bool completed() const { return _completed; } //! Increment pixel count, set completed flag if advanced off end of last frame. void pixel_advance(); }; #endif evolvotron/evolvotron_render/evolvotron_render.cpp0000644000175100017510000001517012100750300022661 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Standalone renderer for evolvotron function files. */ #include "evolvotron_render_precompiled.h" #include "function_registry.h" #include "mutatable_image.h" #include "random.h" //! Application code int main(int argc,char* argv[]) { { uint frames; bool help; bool jitter; int multisample; std::string output_filename; std::string size; bool verbose; boost::program_options::options_description options_desc("Options"); boost::program_options::positional_options_description pos_options_desc; { using namespace boost::program_options; options_desc.add_options() ("frames,f" ,value(&frames)->default_value(1) ,"Frames in an animation") ("help,h" ,bool_switch(&help) ,"Print command-line options help message and exit") ("jitter,j" ,bool_switch(&jitter) ,"Enable rendering jitter") ("multisample,m",value(&multisample)->default_value(1),"Multisampling grid (NxN)") ("output,o" ,value(&output_filename) ,"Output filename (.png or .ppm suffix). (Or use first positional argument.)") ("size,s" ,value(&size)->default_value("512x515"),"Generated image size") ("verbose,v" ,bool_switch(&verbose) ,"Log some details to stderr") ; pos_options_desc.add("output",1); } boost::program_options::variables_map options; boost::program_options::store ( boost::program_options::command_line_parser(argc,argv) .options(options_desc).positional(pos_options_desc).run() ,options ); boost::program_options::notify(options); if (help) { std::cerr << options_desc; return 0; } if (verbose) std::clog.rdbuf(std::cerr.rdbuf()); else std::clog.rdbuf(sink_ostream.rdbuf()); //! \todo Could be done better maybe (set 'x' as input separator) const std::string::size_type p=size.find("x"); if (p==std::string::npos || p==0 || p==size.size()-1) { std::cerr << "--size option argument isn't in x format\n"; return 1; } else { size[p]=' '; } int width=512; int height=512; std::stringstream(size) >> width >> height; if (frames<1) { std::cerr << "Must specify at least 1 frame (option: -f )\n"; return 1; } if (output_filename.empty()) { std::cerr << "Must specify an output filename\n"; return 1; } FunctionRegistry function_registry; std::string report; const boost::shared_ptr imagefn(MutatableImage::load_function(function_registry,std::cin,report)); if (imagefn.get()==0) { std::cerr << "evolvotron_render: Error: Function not loaded due to errors:\n" << report; return 1; } else if (!report.empty()) { std::cerr << "evolvotron_render: Warning: Function loaded with warnings:\n" << report; } // Seed value pretty unimportant; only used for sample jitter. Random01 r01(23); for (uint frame=0;frame image_data; image_data.reserve(width*height); uint pixels=0; uint report=1; const uint reports=20; for (int row=0;rowsampling_coordinate(col,row,frame,width,height,frames)); const XYZ colour(imagefn->get_rgb(col,row,frame,width,height,frames,(jitter ? &r01 : 0),multisample)); const uint col0=lrint(clamped(colour.x(),0.0,255.0)); const uint col1=lrint(clamped(colour.y(),0.0,255.0)); const uint col2=lrint(clamped(colour.z(),0.0,255.0)); image_data.push_back(((col0<<16)|(col1<<8)|(col2))); pixels++; if (pixels>=(report*width*height)/reports) { std::clog << "[" << (100*report)/reports << "%]"; report++; } } std::clog << "\n"; { //! \todo If filename is "-", write PPM to stdout (QImage save only supports write-to-a-filenames though) QString save_filename(QString::fromLocal8Bit(output_filename.c_str())); const char* save_format="PPM"; if (save_filename.toUpper().endsWith(".PPM")) { save_format="PPM"; } else if (save_filename.toUpper().endsWith(".PNG")) { save_format="PNG"; } else { std::cerr << "evolvotron_render: Warning: Unrecognised file suffix. File will be written in " << save_format << " format.\n"; } if (frames>1) { QString frame_component; frame_component.sprintf(".f%06d",frame); int insert_point=save_filename.lastIndexOf(QString(".")); if (insert_point==-1) { save_filename.append(frame_component); } else { save_filename.insert(insert_point,frame_component); } } QImage image ( reinterpret_cast(&(image_data[0])), width, height, QImage::Format_RGB32 ); if (!image.save(save_filename,save_format)) { std::cerr << "evolvotron_render: Error: Couldn't save file " << save_filename.toLocal8Bit().data() << "\n"; return 1; } std::clog << "Wrote file " << save_filename.toLocal8Bit().data() << "\n"; } } } #ifndef NDEBUG assert(InstanceCounted::is_clear()); #endif return 0; } evolvotron/evolvotron/evolvotron.cpp0000644000175100017510000002062012100750300017757 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Application code for evolvotron executable (contains "main"). */ /*! \mainpage Evolvotron : image evolver \author Tim Day \section introduction Introduction "Evolvotron" is an interactive tool for producing "generative art". Images are generated from function trees, which are then mutated and evolved through a process of user selection. \todo For new features to be added, see the TODO file. */ #include "evolvotron_precompiled.h" #include "platform_specific.h" #include "evolvotron_main.h" //! Application code int main(int argc,char* argv[]) { QApplication app(argc,argv); // General options bool autocool; bool fullscreen; std::string grid; bool help; bool jitter; bool menuhide; uint multisample; bool spheremap; std::vector startup; bool startup_shuffle; boost::program_options::options_description options_desc("General options"); { using namespace boost::program_options; options_desc.add_options() ("autocool,a" ,bool_switch(&autocool) ,"Enable autocooling") ("fullscreen,F" ,bool_switch(&fullscreen) ,"Fullscreen window") ("grid,g" ,value(&grid)->default_value("6x5"),"Columns x rows in image grid") ("help,h" ,bool_switch(&help) ,"Print command-line options help message and exit") ("jitter,j" ,bool_switch(&jitter) ,"Enable rendering jitter") ("multisample,m",value(&multisample)->default_value(1) ,"Multisampling grid (NxN)") ("menuhide,M" ,bool_switch(&menuhide) ,"Hide menus") ("spheremap,p" ,bool_switch(&spheremap) ,"Generate spheremaps") ("startup,S" ,value >(&startup) ,"Startup function (multiples allowed, or positional)") ("shuffle,U" ,bool_switch(&startup_shuffle) ,"Shuffle startup functions") ; } // Animation options int framerate; int frames; bool linear; boost::program_options::options_description animation_options_desc("Animation options"); { using namespace boost::program_options; animation_options_desc.add_options() ("frames,f" ,value(&frames)->default_value(1) ,"Frames in an animation") ("linear,l" ,bool_switch(&linear) ,"Sweep z linearly in animations") ("fps,s" ,value(&framerate)->default_value(8) ,"Animation speed (frames-per-second)") ; } // Advanced options bool debug; bool enlargement_threadpool; std::string favourite; int niceness_enlargement; int niceness_grid; uint threads; bool unwrapped; bool verbose; boost::program_options::options_description advanced_options_desc("Advanced options"); { using namespace boost::program_options; advanced_options_desc.add_options() ("debug,D" ,bool_switch(&debug) ,"Enable function debug mode") ("enlargement-threadpool,E",bool_switch(&enlargement_threadpool) ,"Enlargements computed using a separate threadpool") ("nice,n" ,value(&niceness_grid)->default_value(4) ,"Niceness of compute threads for image grid") ("Nice,N" ,value(&niceness_enlargement)->default_value(8) ,"Niceness of compute threads for enlargements (if separate pool)") ("threads,t" ,value(&threads)->default_value(get_number_of_processors()) ,"Number of threads in a thread pool") ("unwrapped,u" ,bool_switch(&unwrapped) ,"Don't wrap favourite function") ("verbose,v" ,bool_switch(&verbose) ,"Log some details to stderr") ("favourite,x" ,value(&favourite) ,"Favourite function") ; } boost::program_options::positional_options_description positional_options_desc; positional_options_desc.add("startup",-1); options_desc.add(animation_options_desc); options_desc.add(advanced_options_desc); boost::program_options::variables_map options; boost::program_options::store( boost::program_options::command_line_parser( argc,argv ).options( options_desc ).positional( positional_options_desc ).run() ,options ); boost::program_options::notify(options); if (help) { std::cerr << options_desc; return 0; } if (verbose) std::clog.rdbuf(std::cerr.rdbuf()); else std::clog.rdbuf(sink_ostream.rdbuf()); //! \todo Could be done better maybe (set 'x' as input separator) const std::string::size_type p=grid.find("x"); if (p==std::string::npos || p==0 || p==grid.size()-1) { std::cerr << "--grid option argument isn't in x format\n"; return 1; } else { grid[p]=' '; } int cols=6; int rows=5; std::stringstream(grid) >> cols >> rows; if (cols*rows<2) { std::cerr << "Must be at least 2 display grid cells\n"; return 1; } if (frames<1) { std::cerr << "Must specify at least 1 frame\n"; return 1; } if (framerate<1) { std::cerr << "Must specify framerate of at least 1\n"; return 1; } std::clog << "Evolvotron version " << stringify(EVOLVOTRON_BUILD) << " starting with " << cols << " by " << rows << " display cells and " << threads << " compute threads per farm (niceness " << niceness_grid << " and " << niceness_enlargement << ")\n"; if (!startup.empty()) { std::clog << "Startup functions to be loaded: "; for (size_t i=0;i0) std::clog << ", "; std::clog << startup[i]; } std::clog << "\n"; } EvolvotronMain*const main_widget=new EvolvotronMain ( 0, QSize(cols,rows), frames, framerate, threads, enlargement_threadpool, niceness_grid, niceness_enlargement, fullscreen, menuhide, autocool, jitter, multisample, debug, linear, spheremap, startup, startup_shuffle ); main_widget->mutation_parameters().function_registry().status(std::clog); if (!favourite.empty()) { std::clog << "Selected specific function: " << favourite << (unwrapped ? " (unwrapped)" : " (wrapped)") << "\n"; if (!main_widget->favourite_function(favourite)) { std::cerr << "Unrecognised function name specified for -x/-X option\n"; return 1; } main_widget->favourite_function_unwrapped(unwrapped); } main_widget->show(); // NB Do this here rather than in constructor so that compute threads aren't being fired off during general GUI set-up std::clog << "Resetting main widget...\n"; main_widget->reset_cold(); // NB No need to worry about deleting EvolvotronMain... QApplication seems to do it for us. std::clog << "Commencing main loop...\n"; return app.exec(); std::clog << "...returned from main loop\n"; return 0; } evolvotron/experiment/svg/svg.cpp0000644000175100017510000000255312100750225017116 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ evolvotron/experiment/program_options/pair.cpp0000644000175100017510000000444412100750225021676 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ #include #include namespace boost { namespace program_options { BOOST_PROGRAM_OPTIONS_DECL typed_value >* intpair(std::pair*); } } using namespace boost::program_options; int main(int argc,char** argv) { bool flag; int number; std::pair pair; options_description options_desc("General options"); options_desc.add_options() ("flag,f" ,bool_switch(&flag) ,"Control a bool") ("number,n" ,value(&number)->default_value(23) ,"Specify a number") ("pair,p" ,intpair(&pair)->default_value(std::make_pair(2,3)) ,"Specify 2 numbers") ; variables_map options; store(parse_command_line(argc,argv,options_desc),options); notify(options); std::cout << "Flag: " << flag << "\n" << "Number: " << number << "\n" << "Pair: " << pair.first << " " << pair.second << "\n"; return 0; } evolvotron/evolvotron_mutate/evolvotron_mutate.cpp0000644000175100017510000001015112100750250022717 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Standalone mutator for evolvotron function files. */ #include "evolvotron_mutate_precompiled.h" #include "mutatable_image.h" #include "mutation_parameters.h" #include "function_top.h" //! Application code int main(int argc,char* argv[]) { { bool genesis; bool help; bool linear; bool spheremap; bool verbose; boost::program_options::options_description options_desc("Options"); { using namespace boost::program_options; options_desc.add_options() ("genesis,g" ,bool_switch(&genesis) ,"Create a new function to stdout (without this option, a function will be read from stdin)") ("help,h" ,bool_switch(&help) ,"Print command-line options help message and exit") ("linear,l" ,bool_switch(&linear) ,"Sweep z linearly in animations") ("spheremap,p",bool_switch(&spheremap),"Generate spheremap") ("verbose,v" ,bool_switch(&verbose) ,"Log some details to stderr") ; } boost::program_options::variables_map options; boost::program_options::store(boost::program_options::parse_command_line(argc,argv,options_desc),options); boost::program_options::notify(options); if (help) { std::cerr << options_desc; return 0; } if (verbose) std::clog.rdbuf(std::cerr.rdbuf()); else std::clog.rdbuf(sink_ostream.rdbuf()); // Normally would use time(0) to seed random number generator // but can imagine several of these starting up virtually simultaneously // so need something with higher resolution. // Adding the process id too to keep things unique. QTime t(QTime::currentTime()); uint seed=getpid()+t.msec()+1000*t.second()+60000*t.minute()+3600000*t.hour(); std::clog << "Random seed is " << seed << "\n"; MutationParameters mutation_parameters(seed,false,false); std::string report; boost::shared_ptr imagefn_out; if (genesis) { std::auto_ptr fn_top(FunctionTop::initial(mutation_parameters)); imagefn_out=boost::shared_ptr(new MutatableImage(fn_top,!linear,spheremap,false)); } else { const boost::shared_ptr imagefn_in ( MutatableImage::load_function(mutation_parameters.function_registry(),std::cin,report) ); if (imagefn_in.get()==0) { std::cerr << "evolvotron_mutate: Error: Function not loaded due to errors:\n" << report; return 1; } else if (!report.empty()) { std::cerr << "evolvotron_mutate: Warning: Function loaded with warnings:\n" << report; } imagefn_out=imagefn_in->mutated(mutation_parameters); } imagefn_out->save_function(std::cout); } #ifndef NDEBUG assert(InstanceCounted::is_clear()); #endif return 0; } evolvotron/libfunction/function_transform.cpp0000644000175100017510000000314112100750300021560 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_transform.h" evolvotron/libfunction/functions_friezegroup_step.cpp0000644000175100017510000000315212100750300023326 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_friezegroup_step.h" evolvotron/libfunction/friezegroup.cpp0000644000175100017510000000275612100750300020214 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for friezegroup related code. */ #include "libfunction_precompiled.h" #include "friezegroup.h" evolvotron/libfunction/useful.cpp0000644000175100017510000000634112100750300017150 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ #include "libfunction_precompiled.h" #include "useful.h" /*! \file \brief Code for useful little helper functions.. */ void fatal_error(const char* msg) { std::cerr << "\n*** Fatal error: " << msg << " ***\n"; exit(1); } void fatal_internal_error(const char* src_file,uint src_line) { std::cerr << "\n*** Fatal internal error in " << src_file << " at line " << src_line << " ***\n"; exit(1); } void constraint_violation(const char* test,const char* src_file,uint src_line) { std::cerr << "\n*** Constraint \"" << test << "\" violated in file" << src_file << " at line " << src_line << " ***\n"; exit(1); } std::ofstream sink_ostream("/dev/null"); #ifndef NDEBUG InstanceCounted::InstanceCounted(const std::string& what,bool verbose) :_what(what) ,_verbose(verbose) { if (!_instance_counts.get()) _instance_counts=std::auto_ptr >(new std::map()); (*_instance_counts)[_what]++; if (_verbose) std::clog << "[+" << _what << ":" << (*_instance_counts)[_what] << "]"; } InstanceCounted::~InstanceCounted() { assert(_instance_counts.get()); assert((*_instance_counts)[_what]>0); (*_instance_counts)[_what]--; if (_verbose) std::clog << "[-" << _what << ":" << (*_instance_counts)[_what] << "]" << ( (*_instance_counts)[_what]==0 ? "\n" : ""); } bool InstanceCounted::is_clear() { bool ok=true; for (std::map::const_iterator it=(*_instance_counts).begin();it!=(*_instance_counts).end();it++) { if ((*it).second>0) { std::clog << "InstanceCounted::is_clear() violated by " << (*it).first << " (" << (*it).second << " instances)\n"; ok=false; } } if (ok) std::clog << "InstanceCounted::is_clear() - no remaining instances\n"; return ok; } std::auto_ptr > InstanceCounted::_instance_counts; #endif evolvotron/libfunction/function_compose_triple.cpp0000644000175100017510000000315112100750300022572 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of FunctionComposeTriple class. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_compose_triple.h" evolvotron/libfunction/functions_friezegroup_spinjump.cpp0000644000175100017510000000315612100750300024224 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_friezegroup_spinjump.h" evolvotron/libfunction/function_identity.cpp0000644000175100017510000000314012100750300021375 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_identity.h" evolvotron/libfunction/function_top.cpp0000644000175100017510000001653312100750300020360 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for FunctionTop */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_top.h" #include "mutation_parameters.h" #include "transform.h" const XYZ FunctionTop::evaluate(const XYZ& p) const { const Transform space_transform(params(),0); const XYZ sp(space_transform.transformed(p)); const XYZ v(arg(0)(sp)); const XYZ tv(tanh(0.5*v.x()),tanh(0.5*v.y()),tanh(0.5*v.z())); // ...each component of tv is in [-1,1] so the transform parameters define a rhomboid in colour space. const Transform colour_transform(params(),12); return colour_transform.transformed(tv); } std::auto_ptr FunctionTop::initial(const MutationParameters& parameters,const FunctionRegistration* specific_fn,bool unwrapped) { std::auto_ptr fn; do { if (specific_fn) { fn=(*(specific_fn->stubnew_fn()))(parameters,true); } else { // This one is crucial: we REALLY want something interesting to happen within here. fn=FunctionNode::stub(parameters,true); } assert(fn->ok()); if (fn->is_constant() && !(specific_fn && specific_fn->name()=="FunctionConstant")) { fn.reset(); } } while (!fn.get()); assert(fn->ok()); boost::ptr_vector a; a.push_back(fn.release()); const TransformIdentity ti; std::vector tiv=ti.get_columns(); std::vector p; p.insert(p.end(),tiv.begin(),tiv.end()); p.insert(p.end(),tiv.begin(),tiv.end()); std::auto_ptr fn_top(new FunctionTop(p,a,0)); if (unwrapped) { // For unwrapped just allow a scale factor and scramble colours fn_top->concatenate_pretransform_on_right(TransformScale(parameters.rnegexp())); fn_top->reset_posttransform_parameters(parameters); } else { fn_top->reset_pretransform_parameters(parameters); fn_top->reset_posttransform_parameters(parameters); } return fn_top; } void FunctionTop::mutate(const MutationParameters& parameters,bool mutate_own_parameters) { FunctionNode::mutate(parameters,false); if (mutate_own_parameters) { if (parameters.r01() p(t.get_columns()); for (uint i=0;i<11;i++) params()[i]=p[i]; } void FunctionTop::mutate_posttransform_parameters(const MutationParameters& parameters) { for (uint i=12;i<23;i++) params()[i]+=parameters.effective_magnitude_parameter_variation()*(parameters.r01()<0.5 ? -parameters.rnegexp() : parameters.rnegexp()); } void FunctionTop::reset_posttransform_parameters(const MutationParameters& parameters) { std::vector p; stubparams(p,parameters,12); for (uint i=0;i<11;i++) params()[12+i]=p[i]; } evolvotron/libfunction/functions_quantize.cpp0000644000175100017510000000314112100750300021570 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_quantize.h" evolvotron/libfunction/functions_arithmetic.cpp0000644000175100017510000000314312100750300022063 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_arithmetic.h" evolvotron/libfunction/functions_friezegroup_spinhop.cpp0000644000175100017510000000307212100750300024034 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for FunctionFriezeGroupSpinhop functions. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_friezegroup_spinhop.h" evolvotron/libfunction/functions_friezegroup_spinsidle.cpp0000644000175100017510000000315712100750300024352 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_friezegroup_spinsidle.h" evolvotron/libfunction/functions_friezegroup_sidle.cpp0000644000175100017510000000315312100750300023454 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_friezegroup_sidle.h" evolvotron/libfunction/function_post_transform.cpp0000644000175100017510000000314212100750300022626 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for FunctionPostTransform Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_post_transform.h" evolvotron/libfunction/mutation_parameters.cpp0000644000175100017510000001734512100750300021736 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutationParameters. */ #include "libfunction_precompiled.h" #include "mutation_parameters.h" #include "function_registration.h" #include "function_registry.h" #include "function_constant.h" #include "function_identity.h" #include "function_transform.h" MutationParameters::MutationParameters(uint seed,bool ac,bool debug_mode) :_function_registry(new FunctionRegistry()) ,_r01(seed) ,_r_negexp(seed,1.0) ,_autocool_reset_state(ac) ,_debug_mode(debug_mode) { reset(); } MutationParameters::~MutationParameters() {} void MutationParameters::reset() { _autocool_enable=_autocool_reset_state; _autocool_halflife=20; _autocool_generations=0; _base_magnitude_parameter_variation=0.25; _base_probability_parameter_reset=0.05; _base_probability_glitch=0.05; _base_probability_shuffle=0.05; _base_probability_insert=0.05; _base_probability_substitute=0.05; _proportion_basic=0.6; _proportion_constant=0.5; _identity_supression=1.0; //! \todo Could do with _max_initial_iterations being higher (64?) for fractal type things but it slows things down too much. _max_initial_iterations=16; _base_probability_iterations_change_step=0.25; _base_probability_iterations_change_jump=0.02; _function_weighting.clear(); for ( FunctionRegistry::Registrations::const_iterator it=_function_registry->registrations().begin(); it!=_function_registry->registrations().end(); it++ ) { if (_debug_mode) { const FunctionRegistration*const fn= #if BOOST_VERSION >= 103400 it->second; #else &*it; #endif real initial_weight=(fn->name()=="FunctionNoiseOneChannel" ? 1.0 : 1.0/1024.0); _function_weighting.insert(std::make_pair(fn,initial_weight)); } else { real initial_weight=1.0; const FunctionRegistration*const fn= #if BOOST_VERSION >= 103400 it->second; #else &*it; #endif if (fn->classification() & FnIterative) initial_weight=1.0/1024.0; // Ouch iterative functions are expensive if (fn->classification() & FnFractal) initial_weight=1.0/1024.0; // Yuk fractals are ugly _function_weighting.insert(std::make_pair(fn,initial_weight)); } } recalculate_function_stuff(); report_change(); } real MutationParameters::decay_factor() const { assert(_autocool_halflife!=0); return (_autocool_enable ? pow(0.5,_autocool_generations/static_cast(_autocool_halflife)) : 1.0); } void MutationParameters::general_cool(real f) { _base_magnitude_parameter_variation*=f; _base_probability_parameter_reset*=f; _base_probability_glitch*=f; _base_probability_shuffle*=f; _base_probability_insert*=f; _base_probability_substitute*=f; _base_probability_iterations_change_step*=f; _base_probability_iterations_change_jump*=f; report_change(); } /*! This returns a random bit of image tree. It needs to be capable of generating any sort of node we have. \warning Too much probability of highly branching nodes could result in infinite sized stubs. \todo Compute (statistically) the expected number of nodes in a stub. */ std::auto_ptr MutationParameters::random_function_stub(bool exciting) const { // Base mutations are Constant or Identity types. // (Identity can be Identity or PositionTransformed, proportions depending on identity_supression parameter) const real base=proportion_basic(); const real r=(exciting ? base+(1.0-base)*r01() : r01()); if (r<(1.0-proportion_constant())*identity_supression()*base) { return FunctionTransform::stubnew(*this,false); } else if (r<(1.0-proportion_constant())*base) { return FunctionIdentity::stubnew(*this,false); } else if (r MutationParameters::random_function() const { const FunctionRegistration* fn_reg=random_weighted_function_registration(); return (*(fn_reg->stubnew_fn()))(*this,false); } const FunctionRegistration* MutationParameters::random_weighted_function_registration() const { const real r=r01(); const std::map::const_iterator it=_function_pick.lower_bound(r); // Just in case last key isn't quite 1.0 if (it!=_function_pick.end()) { return (*it).second; } else { return (*(_function_pick.rbegin())).second; } } real MutationParameters::random_function_branching_ratio() const { real weighted_args=0.0; for ( std::map::const_iterator it=_function_weighting.begin(); it!=_function_weighting.end(); it++ ) { weighted_args+=(*it).second*(*it).first->args(); } return weighted_args/_function_weighting_total; } void MutationParameters::change_function_weighting(const FunctionRegistration* fn,real w) { _function_weighting[fn]=w; recalculate_function_stuff(); report_change(); } void MutationParameters::randomize_function_weightings_for_classifications(uint classification_mask) { for ( std::map::iterator it=_function_weighting.begin(); it!=_function_weighting.end(); it++ ) { if (classification_mask==0 || classification_mask==static_cast(-1) || ((*it).first->classification() & classification_mask)) { const int i=static_cast(floor(11.0*r01())); (*it).second=pow(2,-i); } } recalculate_function_stuff(); report_change(); } real MutationParameters::get_weighting(const FunctionRegistration* fn) { std::map::const_iterator it=_function_weighting.find(fn); assert(it!=_function_weighting.end()); return (*it).second; } void MutationParameters::recalculate_function_stuff() { _function_weighting_total=0.0; for ( std::map::const_iterator it=_function_weighting.begin(); it!=_function_weighting.end(); it++ ) _function_weighting_total+=(*it).second; real normalised=0.0; _function_pick.clear(); for ( std::map::const_iterator it=_function_weighting.begin(); it!=_function_weighting.end(); it++ ) { normalised+=(*it).second/_function_weighting_total; _function_pick.insert(std::make_pair(normalised,(*it).first)); } } void MutationParameters::report_change() {} evolvotron/libfunction/functions_noise.cpp0000644000175100017510000000370512100750300021053 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of noise related function classes. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_noise.h" Noise FunctionNoiseOneChannel::_noise(100); Noise FunctionMultiscaleNoiseOneChannel::_noise(101); Noise FunctionNoiseThreeChannel::_noise0(200); Noise FunctionNoiseThreeChannel::_noise1(300); Noise FunctionNoiseThreeChannel::_noise2(400); Noise FunctionMultiscaleNoiseThreeChannel::_noise0(201); Noise FunctionMultiscaleNoiseThreeChannel::_noise1(202); Noise FunctionMultiscaleNoiseThreeChannel::_noise2(203); evolvotron/libfunction/function_node.cpp0000644000175100017510000003251112100750300020475 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class FunctionNode and derived classes. */ #include "libfunction_precompiled.h" #include "function_node.h" #include "function_compose_pair.h" #include "function_constant.h" #include "function_node_info.h" #include "function_registry.h" #include "margin.h" #include "mutation_parameters.h" std::auto_ptr > FunctionNode::cloneargs() const { std::auto_ptr > ret(new boost::ptr_vector()); for (boost::ptr_vector::const_iterator it=args().begin();it!=args().end();it++) { ret->push_back(it->deepclone().release()); } return ret; } const std::vector FunctionNode::cloneparams() const { return params(); } //! Obtain some statistics about the image function void FunctionNode::get_stats(uint& total_nodes,uint& total_parameters,uint& depth,uint& width,real& proportion_constant) const { uint total_sub_nodes=0; uint total_sub_parameters=0; uint max_sub_depth=0; uint total_sub_width=0; real sub_constants=0.0; // Traverse child nodes. Need to reconstruct the actual numbers from the proportions for (boost::ptr_vector::const_iterator it=args().begin();it!=args().end();it++) { uint sub_nodes; uint sub_parameters; uint sub_depth; uint sub_width; real sub_proportion_constant; it->get_stats(sub_nodes,sub_parameters,sub_depth,sub_width,sub_proportion_constant); total_sub_nodes+=sub_nodes; total_sub_parameters+=sub_parameters; if (sub_depth>max_sub_depth) max_sub_depth=sub_depth; total_sub_width+=sub_width; sub_constants+=sub_nodes*sub_proportion_constant; } // And add our own details total_nodes=1+total_sub_nodes; total_parameters=params().size()+total_sub_parameters; depth=1+max_sub_depth; if (total_sub_width==0) { width=1; } else { width=total_sub_width; } if (is_constant()) { proportion_constant=1.0; } else { proportion_constant=sub_constants/(1+total_sub_nodes); } } bool FunctionNode::verify_info(const FunctionNodeInfo& info,unsigned int np,unsigned int na,bool it,std::string& report) { if (info.params().size()!=np) { std::stringstream msg; msg << "Error: For function " << info.type() << ": expected " << np << " parameters, but found " << info.params().size() << "\n"; report+=msg.str(); return false; } if (info.args().size()!=na) { std::stringstream msg; msg << "Error: For function " << info.type() << ": expected " << na << " arguments, but found " << info.args().size() << "\n"; report+=msg.str(); return false; } if (info.iterations()!=0 && !it) { std::stringstream msg; msg << "Error: For function " << info.type() << ": unexpected iteration count\n"; report+=msg.str(); return false; } if (info.iterations()==0 && it) { std::stringstream msg; msg << "Error: For function " << info.type() << ": expected iteration count but none found\n"; report+=msg.str(); return false; } return true; } bool FunctionNode::is_constant() const { if (args().empty()) return false; for (unsigned int i=0;i::const_iterator it=args().begin();good && it!=args().end();it++) { good=(*it).ok(); } return good; } bool FunctionNode::create_args(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,boost::ptr_vector& args,std::string& report) { for (boost::ptr_vector::const_iterator it=info.args().begin();it!=info.args().end();it++) { std::auto_ptr fn(FunctionNode::create(function_registry,*it,report)); // Check whether something has gone wrong. If it has, delete everything allocated so far and return false. if (!fn.get()) { args.clear(); return false; } args.push_back(fn.release()); } return true; } std::auto_ptr FunctionNode::stub(const MutationParameters& parameters,bool exciting) { return parameters.random_function_stub(exciting); } /*! This setus up a vector of random bits of stub, used for initialiing nodes with children. */ void FunctionNode::stubargs(boost::ptr_vector& v,const MutationParameters& parameters,uint n,bool exciting) { assert(v.empty()); for (uint i=0;i& v,const MutationParameters& parameters,uint n) { assert(v.empty()); for (uint i=0;i(floor(parameters.r01()*parameters.max_initial_iterations())); } FunctionNode::FunctionNode(const std::vector& p,boost::ptr_vector& a,uint iter) :_args(a.release()) ,_params(p) ,_iterations(iter) {} /*! Returns null ptr if there's a problem, in which case there will be an explanation in report. */ std::auto_ptr FunctionNode::create(const FunctionRegistry& function_registry,const FunctionNodeInfo& info,std::string& report) { const FunctionRegistration*const reg=function_registry.lookup(info.type()); if (reg) { return std::auto_ptr((*(reg->create_fn()))(function_registry,info,report)); } else { report+="Error: Unrecognised function name: "+info.type()+"\n"; return std::auto_ptr(); } } /*! Deletes all arguments. No one else should be referencing nodes except the root node of an image. */ FunctionNode::~FunctionNode() {} /*! There are 2 kinds of mutation: - random adjustments to constants - structural mutations (messing with the function tree) For structural mutations the obvious things to do are: - reordering argsuments - dropping argsuments and replacing them with new "stubs". - duplicating arguments - substituting nodes with other types (can't do this for ourself very easily, but we can do it for children) - inserting new nodes between children and ourself And of course all children have to be mutated too. */ void FunctionNode::mutate(const MutationParameters& parameters,bool mutate_own_parameters) { // First mutate all child nodes. for (boost::ptr_vector::iterator it=args().begin();it!=args().end();it++) it->mutate(parameters); // Perturb any parameters we have if (mutate_own_parameters) { if (parameters.r01() p; stubparams(p,parameters,params().size()); params(p); } else { for (std::vector::iterator it=params().begin();it!=params().end();it++) { (*it)+=parameters.effective_magnitude_parameter_variation()*(parameters.r01()<0.5 ? -parameters.rnegexp() : parameters.rnegexp()); } } } // Perturb iteration count if any if (_iterations) { if (parameters.r01()=2) _iterations--; } else { _iterations++; } if (parameters.r01()1) _iterations=(_iterations+1)/2; } else { _iterations*=2; } } // For safety but shouldn't happen if (_iterations==0) _iterations=1; } } // Then go to work on the argument structure... // Think about glitching some nodes. for (uint i=0;i > a(args()[i].deepclone_args()); std::vector p(args()[i].params()); // Replace the node with something interesting (maybe this should depend on how complex the original node was) args().replace(i,stub(parameters,false).release()); FunctionNode& it=args()[i]; // Do we need some extra arguments ? if (a->size() xa; stubargs(xa,parameters,it.args().size()-a->size()); a->transfer(a->end(),xa.begin(),xa.end(),xa); } // Shuffle them random_shuffle(*a,parameters.rng01()); // Have we got too many arguments ? while (a->size()>it.args().size()) { a->pop_back(); } // Do we need some extra parameters ? if (p.size() xp; stubparams(xp,parameters,it.params().size()-p.size()); p.insert(p.end(),xp.begin(),xp.end()); } // Shuffle them random_shuffle(p,parameters.rng01()); // Have we go too many arguments ? while (p.size()>it.params().size()) { p.pop_back(); } // Impose the new parameters and arguments on the new node (iterations not touched) it.args()=a; it.params()=p; } } // Think about randomising child order if (parameters.r01() a; a.transfer(a.begin(),args().begin()+i,args()); a.push_back(stub(parameters,false).release()); std::vector p; args().insert(args().begin()+i,new FunctionComposePair(p,a,0)); } } } void FunctionNode::simplify_constants() { for (uint i=0;i vp; vp.push_back(v.x()); vp.push_back(v.y()); vp.push_back(v.z()); boost::ptr_vector va; args().replace(i,new FunctionConstant(vp,va,0)); } else { args()[i].simplify_constants(); } } } std::auto_ptr > FunctionNode::deepclone_args() const { std::auto_ptr > ret(new boost::ptr_vector()); for (boost::ptr_vector::const_iterator it=args().begin();it!=args().end();it++) ret->push_back(it->deepclone().release()); return ret; } const FunctionTop* FunctionNode::is_a_FunctionTop() const { return 0; } FunctionTop* FunctionNode::is_a_FunctionTop() { return 0; } /*! This function only saves the parameters, iteration count if any and child nodes. It is intended to be called from save_function of subclasses which will write a function node wrapper. The indent number is just the level of recursion, incrementing by 1 each time. Outputting multiple spaces per level is handled by the Margin class. */ std::ostream& FunctionNode::save_function(std::ostream& out,uint indent,const std::string& function_name) const { out << Margin(indent) << "\n"; out << Margin(indent+1) << "" << function_name << "\n"; if (iterations()!=0) out << Margin(indent+1) << "" << iterations() << "\n"; for (std::vector::const_iterator it=params().begin();it!=params().end();it++) { out << Margin(indent+1) << "

" << (*it) << "

\n"; } for (boost::ptr_vector::const_iterator it=args().begin();it!=args().end();it++) { (*it).save_function(out,indent+1); } out << Margin(indent) << "\n"; return out; } evolvotron/libfunction/functions_transform.cpp0000644000175100017510000000314212100750300021744 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_transform.h" evolvotron/libfunction/functions_spiral.cpp0000644000175100017510000000313712100750300021227 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_spiral.h" evolvotron/libfunction/functions_magnitude.cpp0000644000175100017510000000314212100750300021706 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_magnitude.h" evolvotron/libfunction/function_constant.cpp0000644000175100017510000000314012100750300021375 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_constant.h" evolvotron/libfunction/function_boilerplate.cpp0000644000175100017510000000311512100750300022050 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's virtually nothing here because it's all in the header (templates). */ #include "libfunction_precompiled.h" #include "function_boilerplate.h" evolvotron/libfunction/xy.cpp0000644000175100017510000000314112100750300016300 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class XY. */ #include "libfunction_precompiled.h" #include "xy.h" /*! Outputs whitespace-separated co-ordinates. */ std::ostream& XY::write(std::ostream& out) const { return out << x() << " " << y(); } evolvotron/libfunction/function_registry.cpp0000644000175100017510000000523712100750300021425 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class FunctionRegistry and associated classes. */ #include "libfunction_precompiled.h" #include "function_registry.h" #include "register_all_functions.h" FunctionRegistry::FunctionRegistry() { register_all_functions(*this); std::clog << "FunctionRegistry created\n"; } FunctionRegistry::~FunctionRegistry() { _registry_by_name.clear(); std::clog << "FunctionRegistry destroyed\n"; } //! Return the registration for the function named (returns 0 if unknown) const FunctionRegistration* FunctionRegistry::lookup(const std::string& f) const { Registrations::const_iterator it=_registry_by_name.find(f); if (it==_registry_by_name.end()) return 0; else { #if BOOST_VERSION >= 103400 return it->second; #else return &*it; #endif } } std::ostream& FunctionRegistry::status(std::ostream& out) const { out << "Registered functions:\n"; for (Registrations::const_iterator it=_registry_by_name.begin();it!=_registry_by_name.end();it++) { out << " " #if BOOST_VERSION >= 103400 << it->first #else << it.key() #endif << "\n"; } return out; } void FunctionRegistry::register_function(const FunctionRegistration& r) { if (_registry_by_name.find(r.name())==_registry_by_name.end()) { _registry_by_name[r.name()]=r; } } evolvotron/libfunction/function_node_info.cpp0000644000175100017510000000276212100750300021515 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class FunctioNodeInfo. */ #include "libfunction_precompiled.h" #include "function_node_info.h" evolvotron/libfunction/xyz.cpp0000644000175100017510000000573012100750300016500 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class XYZ. */ #include "libfunction_precompiled.h" #include "xyz.h" #include "random.h" /*! Outputs whitespace-separated co-ordinates. */ std::ostream& XYZ::write(std::ostream& out) const { return out << x() << " " << y() << " " << z(); } RandomXYZInUnitCube::RandomXYZInUnitCube(Random01& rng) :XYZ() { x(rng()); y(rng()); z(rng()); } RandomXYZInBox::RandomXYZInBox(Random01& rng,const XYZ& bounds) :XYZ() { x(-bounds.x()+2.0*bounds.x()*rng()); y(-bounds.y()+2.0*bounds.y()*rng()); z(-bounds.z()+2.0*bounds.z()*rng()); } RandomXYZInSphere::RandomXYZInSphere(Random01& rng,real radius) :XYZ(0.0,0.0,0.0) { if (radius!=0.0) { do { x(2.0*rng()-1.0); y(2.0*rng()-1.0); z(2.0*rng()-1.0); } while (magnitude2()>1.0); (*this)*=radius; } } RandomXYZSphereNormal::RandomXYZSphereNormal(Random01& rng) :XYZ(0.0,0.0,0.0) { real m2; do { assign(RandomXYZInSphere(rng,1.0)); m2=magnitude2(); } while (m2==0.0); (*this)/=sqrt(m2); } /*! Must handle case of individual axes being zero. */ RandomXYZInEllipsoid::RandomXYZInEllipsoid(Random01& rng,const XYZ& axes) :XYZ() { do { assign(RandomXYZInBox(rng,axes)); } while ( (axes.x()==0.0 ? 0.0 : sqr(x()/axes.x())) +(axes.y()==0.0 ? 0.0 : sqr(y()/axes.y())) +(axes.z()==0.0 ? 0.0 : sqr(z()/axes.z())) >1.0 ); } RandomXYZInXYDisc::RandomXYZInXYDisc(Random01& rng,real radius) :XYZ(0.0,0.0,0.0) { if (radius!=0.0) { do { x(2.0*rng()-1.0); y(2.0*rng()-1.0); } while (magnitude2()>1.0); (*this)*=radius; } } evolvotron/libfunction/function_registration.cpp0000644000175100017510000000320312100750300022256 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class FunctionRegistration */ #include "libfunction_precompiled.h" #include "function_registration.h" const char*const function_classification_name[FnClassifications]= { "Core", "Structure", "Render", "Iterative", "Fractal" }; evolvotron/libfunction/functions_choose.cpp0000644000175100017510000000313712100750300021215 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_choose.h" evolvotron/libfunction/functions_kaleidoscope.cpp0000644000175100017510000000314512100750300022376 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_kaleidoscope.h" evolvotron/libfunction/margin.cpp0000644000175100017510000000312012100750300017112 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class Margin */ #include "libfunction_precompiled.h" #include "margin.h" std::ostream& Margin::write(std::ostream& out) const { for (uint i=0;i<_n;i++) out << " "; return out; } evolvotron/libfunction/functions_spherical.cpp0000644000175100017510000000314212100750300021703 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_spherical.h" evolvotron/libfunction/transform.cpp0000644000175100017510000000674012100750300017663 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class Transform. */ #include "libfunction_precompiled.h" #include "transform.h" Transform::Transform() {} Transform::Transform(const Transform& t) :_translate(t.translate()) ,_basis_x(t.basis_x()) ,_basis_y(t.basis_y()) ,_basis_z(t.basis_z()) {} Transform::Transform(const XYZ& t,const XYZ& x,const XYZ& y,const XYZ& z) :_translate(t) ,_basis_x(x) ,_basis_y(y) ,_basis_z(z) {} Transform::Transform(const std::vector& v,uint s) { _translate.x(v[s+ 0]);_translate.y(v[s+ 1]);_translate.z(v[s+ 2]); _basis_x.x( v[s+ 3]);_basis_x.y( v[s+ 4]);_basis_x.z( v[s+ 5]); _basis_y.x( v[s+ 6]);_basis_y.y( v[s+ 7]);_basis_y.z( v[s+ 8]); _basis_z.x( v[s+ 9]);_basis_z.y( v[s+10]);_basis_z.z( v[s+11]); } Transform::~Transform() {} const std::vector Transform::get_columns() const { std::vector ret(12); ret[ 0]=_translate.x();ret[ 1]=_translate.y();ret[ 2]=_translate.z(); ret[ 3]=_basis_x.x() ;ret[ 4]=_basis_x.y() ;ret[ 5]=_basis_x.z(); ret[ 6]=_basis_y.x() ;ret[ 7]=_basis_y.y() ;ret[ 8]=_basis_y.z(); ret[ 9]=_basis_z.x() ;ret[10]=_basis_z.y() ;ret[11]=_basis_z.z(); return ret; } const XYZ Transform::transformed(const XYZ& p) const { return _translate+_basis_x*p.x()+_basis_y*p.y()+_basis_z*p.z(); } const XYZ Transform::transformed_no_translate(const XYZ& p) const { return _basis_x*p.x()+_basis_y*p.y()+_basis_z*p.z(); } Transform& Transform::concatenate_on_right(const Transform& t) { const XYZ bx(transformed_no_translate(t.basis_x())); const XYZ by(transformed_no_translate(t.basis_y())); const XYZ bz(transformed_no_translate(t.basis_z())); const XYZ tr(transformed(t.translate())); translate(tr); basis_x(bx); basis_y(by); basis_z(bz); return *this; } Transform& Transform::concatenate_on_left(const Transform& t) { const XYZ bx(t.transformed_no_translate(basis_x())); const XYZ by(t.transformed_no_translate(basis_y())); const XYZ bz(t.transformed_no_translate(basis_z())); const XYZ tr(t.transformed(translate())); translate(tr); basis_x(bx); basis_y(by); basis_z(bz); return *this; } evolvotron/libfunction/functions_friezegroup_hop.cpp0000644000175100017510000000305012100750300023136 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for FunctionFriezeGroupHop */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_friezegroup_hop.h" evolvotron/libfunction/functions_misc.cpp0000644000175100017510000000313512100750300020666 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_misc.h" evolvotron/libfunction/functions_shadow.cpp0000644000175100017510000000313712100750300021222 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_shadow.h" evolvotron/libfunction/random.cpp0000644000175100017510000000324312100750300017123 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class Random and derived classes. */ #include "libfunction_precompiled.h" #include "random.h" Random01::Random01(uint seed) :Random() ,_rng(seed) ,_dist(0.0,1.0) ,_gen(_rng,_dist) {} Random01::~Random01() {} double Random01::operator()() { return _gen(); } evolvotron/libfunction/functions_tartan.cpp0000644000175100017510000000313712100750300021226 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_tartan.h" evolvotron/libfunction/function_transform_generalised.cpp0000644000175100017510000000316712100750300024132 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of FunctionTransformGeneralised class. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_transform_generalised.h" evolvotron/libfunction/functions_gradient.cpp0000644000175100017510000000314112100750300021525 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_gradient.h" evolvotron/libfunction/functions_filter.cpp0000644000175100017510000000313712100750300021222 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_filter.h" evolvotron/libfunction/functions_geometry.cpp0000644000175100017510000000314112100750300021563 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_geometry.h" evolvotron/libfunction/functions_friezegroup_jump.cpp0000644000175100017510000000315212100750300023326 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_friezegroup_jump.h" evolvotron/libfunction/hex.cpp0000644000175100017510000000437712100750300016440 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of helper functions for hexagons. */ //! Co-ordinates of hexagon with given hex-grid coords const XY hex_coord(int x,int y) { const real k=sqrt(3.0)/2.0; return XY( x*k, y+((x&1) ? 0.5 : 0.0) ); } const std::pair nearest_hex(real px,real py) { // Initial guess at which hex we're in: const real k=sqrt(3.0)/2.0; const int nx=static_cast(rintf(px/k)); const int ny=static_cast ( (nx&1) ? rintf(py-0.5) : rintf(py) ); int hx=nx; int hy=ny; const XY ph=hex_coord(nx,ny); real m2b=(XY(px,py)-ph).magnitude2(); for (int dy=-1;dy<=1;dy++) for (int dx=-1;dx<=1;dx++) if (!(dy==0 && dx==0)) { const real m2=(XY(px,py)-hex_coord(nx+dx,ny+dy)).magnitude2(); if (m2. */ /**************************************************************************/ /*! \file \brief Implementation of Noise class */ #include "libfunction_precompiled.h" #include "noise.h" #include "random.h" Noise::Noise(uint seed) { // We use our own random number generator so saved pictures will be the same when reloaded! // (Besides, one isn't actually conveniently available) Random01 r_01(seed); // Create an array of random gradient vectors uniformly on the unit sphere int i; for (i=0;i0;i-=2) { int j=((int)(r_01()*N)); int k=_p[i]; _p[i]=_p[j]; _p[j]=k; } // Extend g and p arrays to allow for faster indexing for (i=0;i. */ /**************************************************************************/ /*! \file \brief Implementation for FunctionPreTransform Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_pre_transform.h" evolvotron/libfunction/function_compose_pair.cpp0000644000175100017510000000314512100750300022231 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of FunctionComposePair class. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "function_compose_pair.h" evolvotron/libfunction/functions_render.cpp0000644000175100017510000000313712100750300021214 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_render.h" evolvotron/libfunction/register_all_functions.cpp0000644000175100017510000002475712100750300022424 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /* AUTO GENERATED FILE. DO NOT EDIT */ /* Should be updated by update_register_all_functions script when new functions are added */ #include "libfunction_precompiled.h" #include "register_all_functions.h" #include "function_boilerplate.h" REGISTER_DCL(FunctionComposePair); REGISTER_DCL(FunctionComposeTriple); REGISTER_DCL(FunctionConstant); REGISTER_DCL(FunctionIdentity); REGISTER_DCL(FunctionPostTransform); REGISTER_DCL(FunctionPreTransform); REGISTER_DCL(FunctionAdd); REGISTER_DCL(FunctionMultiply); REGISTER_DCL(FunctionDivide); REGISTER_DCL(FunctionMax); REGISTER_DCL(FunctionMin); REGISTER_DCL(FunctionModulus); REGISTER_DCL(FunctionExp); REGISTER_DCL(FunctionSin); REGISTER_DCL(FunctionCos); REGISTER_DCL(FunctionChooseStrip); REGISTER_DCL(FunctionChooseStripBlend); REGISTER_DCL(FunctionChooseSphere); REGISTER_DCL(FunctionChooseRect); REGISTER_DCL(FunctionChooseFrom2InCubeMesh); REGISTER_DCL(FunctionChooseFrom3InCubeMesh); REGISTER_DCL(FunctionChooseFrom2InSquareGrid); REGISTER_DCL(FunctionChooseFrom3InSquareGrid); REGISTER_DCL(FunctionChooseFrom2InTriangleGrid); REGISTER_DCL(FunctionChooseFrom3InTriangleGrid); REGISTER_DCL(FunctionChooseFrom3InDiamondGrid); REGISTER_DCL(FunctionChooseFrom3InHexagonGrid); REGISTER_DCL(FunctionChooseFrom2InBorderedHexagonGrid); REGISTER_DCL(FunctionFilter2D); REGISTER_DCL(FunctionFilter3D); REGISTER_DCL(FunctionAverageSamples); REGISTER_DCL(FunctionStreak); REGISTER_DCL(FunctionAverageRing); REGISTER_DCL(FunctionFilterRing); REGISTER_DCL(FunctionConvolveSamples); REGISTER_DCL(FunctionAccumulateOctaves); REGISTER_DCL(FunctionFriezeGroupHopFreeZ); REGISTER_DCL(FunctionFriezeGroupHopClampZ); REGISTER_DCL(FunctionFriezeGroupHopBlendClampZ); REGISTER_DCL(FunctionFriezeGroupHopBlendFreeZ); REGISTER_DCL(FunctionFriezeGroupJumpFreeZ); REGISTER_DCL(FunctionFriezeGroupJumpClampZ); REGISTER_DCL(FunctionFriezeGroupJumpBlendClampZ); REGISTER_DCL(FunctionFriezeGroupJumpBlendFreeZ); REGISTER_DCL(FunctionFriezeGroupSidleFreeZ); REGISTER_DCL(FunctionFriezeGroupSidleClampZ); REGISTER_DCL(FunctionFriezeGroupSpinhopFreeZ); REGISTER_DCL(FunctionFriezeGroupSpinhopClampZ); REGISTER_DCL(FunctionFriezeGroupSpinhopBlendClampZ); REGISTER_DCL(FunctionFriezeGroupSpinhopBlendFreeZ); REGISTER_DCL(FunctionFriezeGroupSpinjumpFreeZ); REGISTER_DCL(FunctionFriezeGroupSpinjumpClampZ); REGISTER_DCL(FunctionFriezeGroupSpinsidleFreeZ); REGISTER_DCL(FunctionFriezeGroupSpinsidleClampZ); REGISTER_DCL(FunctionFriezeGroupStepFreeZ); REGISTER_DCL(FunctionFriezeGroupStepClampZ); REGISTER_DCL(FunctionCross); REGISTER_DCL(FunctionGeometricInversion); REGISTER_DCL(FunctionReflect); REGISTER_DCL(FunctionDerivative); REGISTER_DCL(FunctionDerivativeGeneralised); REGISTER_DCL(FunctionGradient); REGISTER_DCL(FunctionGradientGeneralised); REGISTER_DCL(FunctionDivergence); REGISTER_DCL(FunctionCurl); REGISTER_DCL(FunctionScalarLaplacian); REGISTER_DCL(FunctionMandelbrotChoose); REGISTER_DCL(FunctionMandelbrotContour); REGISTER_DCL(FunctionJuliaChoose); REGISTER_DCL(FunctionJuliaContour); REGISTER_DCL(FunctionJuliabrotChoose); REGISTER_DCL(FunctionJuliabrotContour); REGISTER_DCL(FunctionKaleidoscope); REGISTER_DCL(FunctionKaleidoscopeZRotate); REGISTER_DCL(FunctionKaleidoscopeTwist); REGISTER_DCL(FunctionWindmill); REGISTER_DCL(FunctionWindmillZRotate); REGISTER_DCL(FunctionWindmillTwist); REGISTER_DCL(FunctionMagnitudes); REGISTER_DCL(FunctionMagnitude); REGISTER_DCL(FunctionCone); REGISTER_DCL(FunctionExpCone); REGISTER_DCL(FunctionSeparateZ); REGISTER_DCL(FunctionIterate); REGISTER_DCL(FunctionNoiseOneChannel); REGISTER_DCL(FunctionMultiscaleNoiseOneChannel); REGISTER_DCL(FunctionNoiseThreeChannel); REGISTER_DCL(FunctionMultiscaleNoiseThreeChannel); REGISTER_DCL(FunctionPixelize); REGISTER_DCL(FunctionPixelizeHex); REGISTER_DCL(FunctionVoxelize); REGISTER_DCL(FunctionOrthoSphereShaded); REGISTER_DCL(FunctionOrthoSphereShadedBumpMapped); REGISTER_DCL(FunctionOrthoSphereReflect); REGISTER_DCL(FunctionOrthoSphereReflectBumpMapped); REGISTER_DCL(FunctionShadow); REGISTER_DCL(FunctionShadowGeneralised); REGISTER_DCL(FunctionCartesianToSpherical); REGISTER_DCL(FunctionSphericalToCartesian); REGISTER_DCL(FunctionEvaluateInSpherical); REGISTER_DCL(FunctionSpiralLinear); REGISTER_DCL(FunctionSpiralLogarithmic); REGISTER_DCL(FunctionTartanSelectFree); REGISTER_DCL(FunctionTartanSelect); REGISTER_DCL(FunctionTartanSelectRepeat); REGISTER_DCL(FunctionTartanMixFree); REGISTER_DCL(FunctionTartanMixRepeat); REGISTER_DCL(FunctionIsotropicScale); REGISTER_DCL(FunctionPreTransformGeneralised); REGISTER_DCL(FunctionPostTransformGeneralised); REGISTER_DCL(FunctionTransformQuadratic); REGISTER_DCL(FunctionRotate); REGISTER_DCL(FunctionTop); REGISTER_DCL(FunctionTransformGeneralised); REGISTER_DCL(FunctionTransform); void register_all_functions(FunctionRegistry& r) { register_FunctionComposePair(r); register_FunctionComposeTriple(r); register_FunctionConstant(r); register_FunctionIdentity(r); register_FunctionPostTransform(r); register_FunctionPreTransform(r); register_FunctionAdd(r); register_FunctionMultiply(r); register_FunctionDivide(r); register_FunctionMax(r); register_FunctionMin(r); register_FunctionModulus(r); register_FunctionExp(r); register_FunctionSin(r); register_FunctionCos(r); register_FunctionChooseStrip(r); register_FunctionChooseStripBlend(r); register_FunctionChooseSphere(r); register_FunctionChooseRect(r); register_FunctionChooseFrom2InCubeMesh(r); register_FunctionChooseFrom3InCubeMesh(r); register_FunctionChooseFrom2InSquareGrid(r); register_FunctionChooseFrom3InSquareGrid(r); register_FunctionChooseFrom2InTriangleGrid(r); register_FunctionChooseFrom3InTriangleGrid(r); register_FunctionChooseFrom3InDiamondGrid(r); register_FunctionChooseFrom3InHexagonGrid(r); register_FunctionChooseFrom2InBorderedHexagonGrid(r); register_FunctionFilter2D(r); register_FunctionFilter3D(r); register_FunctionAverageSamples(r); register_FunctionStreak(r); register_FunctionAverageRing(r); register_FunctionFilterRing(r); register_FunctionConvolveSamples(r); register_FunctionAccumulateOctaves(r); register_FunctionFriezeGroupHopFreeZ(r); register_FunctionFriezeGroupHopClampZ(r); register_FunctionFriezeGroupHopBlendClampZ(r); register_FunctionFriezeGroupHopBlendFreeZ(r); register_FunctionFriezeGroupJumpFreeZ(r); register_FunctionFriezeGroupJumpClampZ(r); register_FunctionFriezeGroupJumpBlendClampZ(r); register_FunctionFriezeGroupJumpBlendFreeZ(r); register_FunctionFriezeGroupSidleFreeZ(r); register_FunctionFriezeGroupSidleClampZ(r); register_FunctionFriezeGroupSpinhopFreeZ(r); register_FunctionFriezeGroupSpinhopClampZ(r); register_FunctionFriezeGroupSpinhopBlendClampZ(r); register_FunctionFriezeGroupSpinhopBlendFreeZ(r); register_FunctionFriezeGroupSpinjumpFreeZ(r); register_FunctionFriezeGroupSpinjumpClampZ(r); register_FunctionFriezeGroupSpinsidleFreeZ(r); register_FunctionFriezeGroupSpinsidleClampZ(r); register_FunctionFriezeGroupStepFreeZ(r); register_FunctionFriezeGroupStepClampZ(r); register_FunctionCross(r); register_FunctionGeometricInversion(r); register_FunctionReflect(r); register_FunctionDerivative(r); register_FunctionDerivativeGeneralised(r); register_FunctionGradient(r); register_FunctionGradientGeneralised(r); register_FunctionDivergence(r); register_FunctionCurl(r); register_FunctionScalarLaplacian(r); register_FunctionMandelbrotChoose(r); register_FunctionMandelbrotContour(r); register_FunctionJuliaChoose(r); register_FunctionJuliaContour(r); register_FunctionJuliabrotChoose(r); register_FunctionJuliabrotContour(r); register_FunctionKaleidoscope(r); register_FunctionKaleidoscopeZRotate(r); register_FunctionKaleidoscopeTwist(r); register_FunctionWindmill(r); register_FunctionWindmillZRotate(r); register_FunctionWindmillTwist(r); register_FunctionMagnitudes(r); register_FunctionMagnitude(r); register_FunctionCone(r); register_FunctionExpCone(r); register_FunctionSeparateZ(r); register_FunctionIterate(r); register_FunctionNoiseOneChannel(r); register_FunctionMultiscaleNoiseOneChannel(r); register_FunctionNoiseThreeChannel(r); register_FunctionMultiscaleNoiseThreeChannel(r); register_FunctionPixelize(r); register_FunctionPixelizeHex(r); register_FunctionVoxelize(r); register_FunctionOrthoSphereShaded(r); register_FunctionOrthoSphereShadedBumpMapped(r); register_FunctionOrthoSphereReflect(r); register_FunctionOrthoSphereReflectBumpMapped(r); register_FunctionShadow(r); register_FunctionShadowGeneralised(r); register_FunctionCartesianToSpherical(r); register_FunctionSphericalToCartesian(r); register_FunctionEvaluateInSpherical(r); register_FunctionSpiralLinear(r); register_FunctionSpiralLogarithmic(r); register_FunctionTartanSelectFree(r); register_FunctionTartanSelect(r); register_FunctionTartanSelectRepeat(r); register_FunctionTartanMixFree(r); register_FunctionTartanMixRepeat(r); register_FunctionIsotropicScale(r); register_FunctionPreTransformGeneralised(r); register_FunctionPostTransformGeneralised(r); register_FunctionTransformQuadratic(r); register_FunctionRotate(r); register_FunctionTop(r); register_FunctionTransformGeneralised(r); register_FunctionTransform(r); } evolvotron/libfunction/functions_juliabrot.cpp0000644000175100017510000000314212100750300021724 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of specific Function classes. Except there's nothing here because it's all in the header. */ #include "libfunction_precompiled.h" #include "function_boilerplate_instantiate.h" #include "functions_juliabrot.h" evolvotron/libevolvotron/mutatable_image_display_big.cpp0000644000175100017510000000547712100750252023742 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutatableImageDisplayBig. */ #include "libevolvotron_precompiled.h" #include "mutatable_image_display_big.h" #include "evolvotron_main.h" MutatableImageDisplayBig::MutatableImageDisplayBig(EvolvotronMain* mn) :QWidget(mn,Qt::Window) // We're a window, but with a parent ,_main(mn) { setAttribute(Qt::WA_DeleteOnClose,true); setWindowTitle("Evolvotron"); setMinimumSize(256,256); //setSizeGripEnabled(true); // Only an option if we give the window a statusbar, or make it a dialog } /*! Don't think destructor needs to do anything to _display... Qt takes care of it */ MutatableImageDisplayBig::~MutatableImageDisplayBig() { std::clog << "An enlargement was deleted\n"; } /*! There's not much point in dropping back to normal mode (from fullscreen) if the main app is fullscreen because we'll just be hidden, so close instead under such circumstances. (However, on ctrl-f we put both into normal mode). */ void MutatableImageDisplayBig::keyPressEvent(QKeyEvent* e) { if (e->key()==Qt::Key_Escape) { if (main()->isFullScreen()) close(); else showNormal(); } else if (e->key()==Qt::Key_F && !e->modifiers()) { if (isFullScreen()) { if (main()->isFullScreen()) main()->toggle_fullscreen(); // Need to use this to maintain menu checkmarks showNormal(); } else showFullScreen(); } else { // Perhaps it's for someone else e->ignore(); } } evolvotron/libevolvotron/dialog_functions.cpp0000644000175100017510000002654512100750252021602 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class DialogFunctions. */ #include "libevolvotron_precompiled.h" #include "dialog_functions.h" #include "evolvotron_main.h" #include "function_registry.h" /*! Dialog controls function weightings and related parameters. */ DialogFunctions::DialogFunctions(EvolvotronMain* parent,MutationParametersQObject* mp) :QDialog(parent) ,_parent(parent) ,_mutation_parameters(mp) { assert(_parent!=0); setWindowTitle("Functions"); setMinimumSize(480,360); // Have to scroll through tabs if don't set this setSizeGripEnabled(true); setLayout(new QVBoxLayout); QTabWidget*const tabs=new QTabWidget; layout()->addWidget(tabs); QPushButton*const ok=new QPushButton("OK"); layout()->addWidget(ok); ok->setDefault(true); for (int c=-1;csetLayout(tab_content_layout); tabs->addTab(tab_content,(c==-1 ? "All" : function_classification_name[c])); QWidget*const buttons=new QWidget; buttons->setLayout(new QHBoxLayout); tab_content->layout()->addWidget(buttons); QPushButton*const button_less=new QPushButton("Less"); QPushButton*const button_rand=new QPushButton("Randomize"); QPushButton*const button_more=new QPushButton("More"); buttons->layout()->addWidget(button_less); buttons->layout()->addWidget(button_rand); buttons->layout()->addWidget(button_more); SignalExpanderClickedUint*const bx_rand=new SignalExpanderClickedUint(this,(c==-1 ? 0xffffffff : (1<setWidgetResizable(true); tab_content->layout()->addWidget(scrollarea); tab_content_layout->setStretchFactor(scrollarea,1); QWidget*const scrollcontent=new QWidget; scrollcontent->setLayout(new QVBoxLayout); scrollarea->setWidget(scrollcontent); for (FunctionRegistry::Registrations::const_iterator it=_parent->mutation_parameters().function_registry().registrations().begin(); it!=_parent->mutation_parameters().function_registry().registrations().end(); it++) { const FunctionRegistration& fn= #if BOOST_VERSION >= 103400 *(it->second); #else *it; #endif if (c==-1 || fn.classification()&(1<widget()->layout()->addWidget(g); g->setLayout(new QHBoxLayout); QSizePolicy spx(QSizePolicy::Expanding,QSizePolicy::Preferred); g->setSizePolicy(spx); g->layout()->addWidget(new QLabel("2^-10")); QSlider*const s=new QSlider(Qt::Horizontal); g->layout()->addWidget(s); s->setMinimum(-10); s->setMaximum(0); s->setValue(0); s->setTickInterval(1); s->setTickPosition(QSlider::TicksBothSides); s->setSizePolicy(spx); g->layout()->addWidget(new QLabel("1")); _slider_to_function.insert(std::make_pair(s,&fn)); SignalExpanderValueChangedQSlider*const sx=new SignalExpanderValueChangedQSlider(this,s); connect( s,SIGNAL(valueChanged(int)), sx,SLOT(valueChanged(int)) ); connect( sx,SIGNAL(valueChanged(QSlider*,int)), this,SLOT(changed_function_weighting(QSlider*,int)) ); // Wire up buttons connect( button_less,SIGNAL(clicked()), s,SLOT(subtractStep()) ); connect(button_more,SIGNAL(clicked()), s,SLOT(addStep()) ); } } } // And add another tab for all the branching-ratio/dilution controls { QWidget*const vbox=new QWidget; vbox->setLayout(new QVBoxLayout); tabs->addTab(vbox,"Dilution"); _branching_ratio=new QLabel; vbox->layout()->addWidget(_branching_ratio); QGroupBox*const c0=new QGroupBox("Required branching ratio after dilution"); c0->setLayout(new QHBoxLayout); vbox->layout()->addWidget(c0); c0->layout()->addWidget(new QLabel("0.1")); _slider_target_branching_ratio=new QSlider(Qt::Horizontal); c0->layout()->addWidget(_slider_target_branching_ratio); _slider_target_branching_ratio->setMinimum(10); _slider_target_branching_ratio->setMaximum(90); _slider_target_branching_ratio->setValue(50); _slider_target_branching_ratio->setTickInterval(10); _slider_target_branching_ratio->setTickPosition(QSlider::TicksBothSides); _slider_target_branching_ratio->setToolTip("The branching ratio must be diluted to <1.0 to prevent formation of infinitely large function-trees.\nWarning: setting a high value results in complex function trees taking a long time to compute.\nSetting a low value results in very simple images."); c0->layout()->addWidget(new QLabel("0.9")); QGroupBox*const c1=new QGroupBox("Of diluting nodes, proportion constant:"); c1->setLayout(new QHBoxLayout); vbox->layout()->addWidget(c1); c1->layout()->addWidget(new QLabel("0.0")); _slider_proportion_constant=new QSlider(Qt::Horizontal,c1); c1->layout()->addWidget(_slider_proportion_constant); _slider_proportion_constant->setMinimum(0); _slider_proportion_constant->setMaximum(100); _slider_proportion_constant->setValue(50); _slider_proportion_constant->setTickInterval(10); _slider_proportion_constant->setTickPosition(QSlider::TicksBothSides); _slider_proportion_constant->setToolTip("This specifies the proportion of diluting nodes which will be constant."); c1->layout()->addWidget(new QLabel("1.0")); QGroupBox*const c2=new QGroupBox("Of non-constant diluting nodes, proportion transforms"); c2->setLayout(new QHBoxLayout); vbox->layout()->addWidget(c2); c2->layout()->addWidget(new QLabel("0.0")); _slider_identity_supression=new QSlider(Qt::Horizontal,c2); c2->layout()->addWidget(_slider_identity_supression); _slider_identity_supression->setMinimum(0); _slider_identity_supression->setMaximum(100); _slider_identity_supression->setValue(50); _slider_identity_supression->setTickInterval(10); _slider_identity_supression->setTickPosition(QSlider::TicksBothSides); _slider_identity_supression->setToolTip("This specifies the proportion of non-constant diluting nodes which will be transforms (c.f identity nodes)."); c2->layout()->addWidget(new QLabel("1.0")); connect( _slider_target_branching_ratio,SIGNAL(valueChanged(int)), this,SLOT(changed_target_branching_ratio(int)) ); connect( ok,SIGNAL(clicked()), this,SLOT(hide()) ); connect( _slider_proportion_constant,SIGNAL(valueChanged(int)), this,SLOT(changed_proportion_constant(int)) ); connect( _slider_identity_supression,SIGNAL(valueChanged(int)), this,SLOT(changed_identity_supression(int)) ); } setup_from_mutation_parameters(); connect( _mutation_parameters,SIGNAL(changed()), this,SLOT(mutation_parameters_changed()) ); } DialogFunctions::~DialogFunctions() {} void DialogFunctions::setup_from_mutation_parameters() { const real b=_mutation_parameters->random_function_branching_ratio(); const real s=_mutation_parameters->proportion_basic(); const real br=(1.0-s)*b; std::stringstream msg; msg << "Undiluted random function branching ratio is " << b << "\n" << "Diluting in proportion " << s << " to obtain required branching ratio."; _branching_ratio->setText(msg.str().c_str()); _slider_target_branching_ratio->setValue(static_cast(100.0*br+0.5)); _slider_proportion_constant->setValue(static_cast(0.5+100.0*_mutation_parameters->proportion_constant())); _slider_identity_supression->setValue(static_cast(0.5+100.0*_mutation_parameters->identity_supression())); for (std::map::const_iterator it=_slider_to_function.begin(); it!=_slider_to_function.end(); it++ ) { const real w=_mutation_parameters->get_weighting((*it).second); const int iw=static_cast(floor(0.5+(log(w)*(1.0/M_LN2)))); if (iw!=(*it).first->value()) { (*it).first->setValue(iw); } } } void DialogFunctions::changed_target_branching_ratio(int v) { const real target_branching_ratio=v/100.0; // Want to solve tgt=proportion_basic*0.0+(1.0-proportion_basic)*random_function_branching_ratio const real proportion_basic=1.0-target_branching_ratio/_mutation_parameters->random_function_branching_ratio(); std::clog << "Basic-node dilution proportion set to " << proportion_basic << " giving a branching ratio of " << (1.0-proportion_basic)*_mutation_parameters->random_function_branching_ratio() << "\n"; _mutation_parameters->proportion_basic(proportion_basic); setup_from_mutation_parameters(); } void DialogFunctions::changed_proportion_constant(int v) { _mutation_parameters->proportion_constant(v/100.0); } void DialogFunctions::changed_identity_supression(int v) { _mutation_parameters->identity_supression(v/100.0); } void DialogFunctions::changed_function_weighting(QSlider* s,int v) { std::map::const_iterator it=_slider_to_function.find(s); if (it==_slider_to_function.end()) { std::clog << "DialogFunctions::changed_function_weighting : unknown source slider, ignoring\n"; } else { const FunctionRegistration* fn=(*it).second; const real w=pow(2,v); std::clog << fn->name() << " weighting changed to " << w << "\n"; _mutation_parameters->change_function_weighting(fn,w); } } void DialogFunctions::clicked_button_rand(uint mask) { std::clog << "Randomizing functions matching mask " << mask << "\n"; _mutation_parameters->randomize_function_weightings_for_classifications(mask); } void DialogFunctions::mutation_parameters_changed() { //std::clog << "[DialogFunctions::mutation_parameters_changed()]\n"; setup_from_mutation_parameters(); } evolvotron/libevolvotron/evolvotron_main.cpp0000644000175100017510000006047212100750277021500 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class EvolvotronMain. \todo Eliminate need to include function.h (and instantiate lots of stuff) by moving more into function_node.h/.cpp */ #include "libevolvotron_precompiled.h" #include "evolvotron_main.h" #include "dialog_about.h" #include "dialog_help.h" #include "dialog_mutation_parameters.h" #include "dialog_render_parameters.h" #include "dialog_functions.h" #include "dialog_favourite.h" #include "function_node.h" #include "function_post_transform.h" #include "function_pre_transform.h" #include "function_top.h" void EvolvotronMain::History::purge() { if (_archive.size()>0) _archive.pop_back(); } EvolvotronMain::History::History(EvolvotronMain* m) :_main(m) ,max_slots(32) { // Don't call _main->set_undoable because menus probably haven't been constructed yet. } EvolvotronMain::History::~History() {} void EvolvotronMain::History::log_status() const { std::clog << "[History: " << _archive.size() << " records ("; for (Archive::const_iterator it=_archive.begin();it!=_archive.end();it++) std::clog << (it!=_archive.begin() ? "," : "") << (*it).second.size(); std::clog << ")]\n"; } void EvolvotronMain::History::goodbye(MutatableImageDisplay* display) { // First pass to delete any individual items for that display. for (Archive::iterator it=_archive.begin();it!=_archive.end();it++) (*it).second.erase(display); // Second pass to delete any undo items which are now empty Archive::iterator it=_archive.begin(); while (it!=_archive.end()) { if ((*it).second.empty()) it=_archive.erase(it); it++; } // Set menu label again in case we've changed the topmost item const std::string action_name(_archive.empty() ? "" : _archive.front().first); _main->set_undoable(undoable(),action_name); } void EvolvotronMain::History::replacing(MutatableImageDisplay* display) { if (_archive.size()==0) { begin_action(""); } const boost::shared_ptr image_function=display->image_function(); if (image_function.get()) { const boost::shared_ptr saved_image_function(image_function->deepclone(image_function->locked())); _archive.front().second.insert(std::make_pair(display,saved_image_function)); } } /*! Only creates a new slot for display-image pairs if the current top one (if any) isn't empty. */ void EvolvotronMain::History::begin_action(const std::string& action_name) { if (_archive.size()==0 || _archive.front().second.size()!=0) { _archive.push_front(ArchiveRecord()); assert(_archive.front().second.size()==0); } _archive.front().first=action_name; while (_archive.size()>max_slots) { purge(); } } void EvolvotronMain::History::end_action() { const std::string action_name(_archive.empty() ? "" : _archive.front().first); _main->set_undoable(undoable(),action_name); log_status(); } bool EvolvotronMain::History::undoable() { if (_archive.size()==0) { return false; } else if (_archive.front().second.size()==0) { _archive.pop_front(); return undoable(); } else { return true; } } void EvolvotronMain::History::undo() { if (_archive.size()==0) { // Shouldn't ever see this if Undo menu item is correctly greyed out. QMessageBox::warning(_main,"Evolvotron","Sorry, cannot undo any further"); } else if (_archive.front().second.size()==0) { _archive.pop_front(); undo(); } else { for (ArchiveRecordEntries::iterator it=_archive.front().second.begin(); it!=_archive.front().second.end(); it++ ) { _main->restore((*it).first,(*it).second,_archive.size()>1); } _archive.pop_front(); } const std::string action_name(_archive.empty() ? "" : _archive.front().first); _main->set_undoable(undoable(),action_name); } void EvolvotronMain::last_spawned_image(const boost::shared_ptr& image,SpawnMemberFn method) { _last_spawned_image=image; _last_spawn_method=method; } /*! Constructor sets up GUI components and fires up QTimer. Initialises mutation parameters using time, so different every time. */ EvolvotronMain::EvolvotronMain ( QWidget* parent, const QSize& grid_size, uint frames, uint framerate, uint n_threads, bool separate_farm_for_enlargements, int niceness_grid, int niceness_enlargements, bool start_fullscreen, bool start_menuhidden, bool autocool, bool jitter, uint multisample_level, bool function_debug_mode, bool linear_zsweep, bool spheremap, const std::vector& startup_filenames, bool startup_shuffle ) :QMainWindow(parent) ,_history(new EvolvotronMain::History(this)) ,_linear_zsweep(linear_zsweep) ,_spheremap(spheremap) ,_startup_filenames(startup_filenames) ,_startup_shuffle(startup_shuffle) ,_mutation_parameters(time(0),autocool,function_debug_mode,this) ,_render_parameters(jitter,multisample_level,this) ,_statusbar_tasks_main(0) ,_statusbar_tasks_enlargement(0) ,_last_spawn_method(&EvolvotronMain::spawn_normal) { setAttribute(Qt::WA_DeleteOnClose,true); setAttribute(Qt::WA_QuitOnClose,true); setMinimumSize(640,480); // Need to create this first or DialogMutationParameters might cause one to be created too. _statusbar=new QStatusBar; _statusbar->setSizeGripEnabled(true); setStatusBar(_statusbar); _statusbar->addWidget(_statusbar_tasks_label=new QLabel("Ready")); _dialog_about=new DialogAbout(this,n_threads,separate_farm_for_enlargements); _dialog_help_short=new DialogHelp(this,false); _dialog_help_long=new DialogHelp(this,true); _dialog_mutation_parameters=new DialogMutationParameters(this,&_mutation_parameters); _dialog_render_parameters=new DialogRenderParameters(this,&_render_parameters); _dialog_functions=new DialogFunctions(this,&_mutation_parameters); _dialog_favourite=new DialogFavourite(this); _popupmenu_file=menuBar()->addMenu("&File"); _popupmenu_file->addAction("Reset (Reset mutation parameters, clear locks)",this,SLOT(reset_cold()),QKeySequence("r")); _popupmenu_file->addAction("Restart (Preserve mutation parameters and locks)",this,SLOT(reset_warm()),QKeySequence("t")); _popupmenu_file->addAction("Remix (Randomize function weights and restart)",this,SLOT(reset_randomized()),QKeySequence("x")); _popupmenu_file->addSeparator(); _popupmenu_file->addAction("Quit",qApp,SLOT(quit()),QKeySequence("q")); _popupmenu_edit=menuBar()->addMenu("&Edit"); _popupmenu_edit_undo_action=_popupmenu_edit->addAction("Undo",this,SLOT(undo()),QKeySequence("u")); _popupmenu_edit_undo_action->setEnabled(false); _popupmenu_edit->addSeparator(); _popupmenu_edit->addAction("Simplify all functions",this,SLOT(simplify_constants())); _popupmenu_settings=menuBar()->addMenu("Se&ttings"); _popupmenu_settings->addAction("Mutation parameters...",_dialog_mutation_parameters,SLOT(show())); _popupmenu_settings->addAction("Function weightings...",_dialog_functions,SLOT(show())); _popupmenu_settings->addAction("Favourite function...",_dialog_favourite,SLOT(show())); _popupmenu_settings->addSeparator(); _popupmenu_settings->addAction("Render parameters...",_dialog_render_parameters,SLOT(show())); _popupmenu_settings->addSeparator(); _menu_action_fullscreen=_popupmenu_settings->addAction("Fullscreen",this,SLOT(toggle_fullscreen()),QKeySequence("f")); _menu_action_fullscreen->setCheckable(true); _menu_action_fullscreen->setChecked(start_fullscreen); _menu_action_hide_menu=_popupmenu_settings->addAction("Hide menu and statusbar",this,SLOT(toggle_hide_menu()),QKeySequence("m")); _menu_action_hide_menu->setCheckable(true); _menu_action_hide_menu->setChecked(start_menuhidden); //! This doesn't seem to do anything (supposed to push help menu over to far end ?) menuBar()->addSeparator(); _popupmenu_help=menuBar()->addMenu("&Help"); _popupmenu_help->addAction("Quick Reference",_dialog_help_short,SLOT(show())); _popupmenu_help->addAction("User Manual",_dialog_help_long,SLOT(show())); _popupmenu_help->addSeparator(); _popupmenu_help->addAction("About",_dialog_about,SLOT(show())); _checkbox_autocool_enable=new QCheckBox("Autocool"); _checkbox_autocool_enable->setToolTip("Autocooling gradually reduces the chance and magnitude of mutations with time."); _label_autocool_enable=new QLabel(""); // Used to display generation count _button_autocool_reheat=new QPushButton("Reheat"); _button_autocool_reheat->setToolTip("Reheat restarts the autocooling generation count, restoring the full strength of mutations."); connect(_checkbox_autocool_enable,SIGNAL(stateChanged(int)),_dialog_mutation_parameters,SLOT(changed_autocool_enable(int))); connect(_button_autocool_reheat,SIGNAL(clicked()),_dialog_mutation_parameters,SLOT(reheat())); _statusbar->addPermanentWidget(_checkbox_autocool_enable); _statusbar->addPermanentWidget(_label_autocool_enable); _statusbar->addPermanentWidget(_button_autocool_reheat); connect( &_render_parameters,SIGNAL(changed()), this,SLOT(render_parameters_changed()) ); connect( &_mutation_parameters,SIGNAL(changed()), this,SLOT(mutation_parameters_changed()) ); _farm[0]=std::auto_ptr(new MutatableImageComputerFarm(n_threads,niceness_grid)); if (separate_farm_for_enlargements) { _farm[1]=std::auto_ptr(new MutatableImageComputerFarm(n_threads,niceness_enlargements)); } _grid=new QWidget; QGridLayout*const grid_layout=new QGridLayout; _grid->setLayout(grid_layout); setCentralWidget(_grid); //! \todo frames and framerate should be retained and modifiable from the GUI for (int r=0;raddWidget(d,r,c); displays().push_back(d); } _timer=new QTimer(this); connect( _timer,SIGNAL(timeout()), this, SLOT(tick()) ); // Run tick() at 100Hz _timer->start(10); if (start_fullscreen) { showFullScreen(); } if (start_menuhidden) { menuBar()->hide(); statusBar()->hide(); } } /*! If this is being destroyed then the whole application is going down. Could be ordering issues with the display destructors though. */ EvolvotronMain::~EvolvotronMain() { std::clog << "Evolvotron shut down begun...\n"; // Orphan any displays which outlived us (and clear their images) (look out: shutdown order is Qt-determined) std::clog << "(There are " << _known_displays.size() << " displays remaining)\n"; for (std::set::const_iterator it=_known_displays.begin();it!=_known_displays.end();it++) { (*it)->image_function(boost::shared_ptr(),true); (*it)->main(0); } std::clog << "...cleared displays, deleting farm...\n"; // Shut down the compute farms _farm[0].reset(); _farm[1].reset(); std::clog << "...deleted farm, deleting history...\n"; // Clean up records. _last_spawned_image.reset(); _history.reset(); std::clog << "...deleted history\n"; #ifndef NDEBUG assert(InstanceCounted::is_clear()); #endif std::clog << "...completed Evolvotron shutdown\n"; } bool EvolvotronMain::favourite_function(const std::string& f) { return _dialog_favourite->favourite_function(f); } void EvolvotronMain::favourite_function_unwrapped(bool v) { _dialog_favourite->favourite_function_unwrapped(v); } void EvolvotronMain::spawn_normal(const boost::shared_ptr& image_function,MutatableImageDisplay* display,bool one_of_many) { boost::shared_ptr new_image_function; do { new_image_function=image_function->mutated(mutation_parameters()); } while (new_image_function->is_constant()); history().replacing(display); display->image_function(new_image_function,one_of_many); } void EvolvotronMain::spawn_recoloured(const boost::shared_ptr& image_function,MutatableImageDisplay* display,bool one_of_many) { std::auto_ptr new_root(image_function->top().typed_deepclone()); new_root->reset_posttransform_parameters(mutation_parameters()); history().replacing(display); boost::shared_ptr it(new MutatableImage(new_root,image_function->sinusoidal_z(),image_function->spheremap(),false)); display->image_function(it,one_of_many); } void EvolvotronMain::spawn_warped(const boost::shared_ptr& image_function,MutatableImageDisplay* display,bool one_of_many) { std::auto_ptr new_root=std::auto_ptr(image_function->top().typed_deepclone()); // Get the transform from whatever factory is currently set const Transform transform(transform_factory()(mutation_parameters().rng01())); new_root->concatenate_pretransform_on_right(transform); history().replacing(display); boost::shared_ptr it(new MutatableImage(new_root,image_function->sinusoidal_z(),image_function->spheremap(),false)); display->image_function(it,one_of_many); } void EvolvotronMain::restore(MutatableImageDisplay* display,const boost::shared_ptr& image_function,bool one_of_many) { if (is_known(display)) display->image_function(image_function,one_of_many); } void EvolvotronMain::set_undoable(bool v,const std::string& action_name) { _popupmenu_edit_undo_action->setText(QString(("Undo "+action_name).c_str())); _popupmenu_edit_undo_action->setEnabled(v); } void EvolvotronMain::respawn(MutatableImageDisplay* display) { if (display->locked()) { QMessageBox::warning(this,"Evolvotron","Cannot respawn a locked image.\nUnlock and try again."); } else { history().begin_action("respawn"); if (last_spawned_image()==0) { reset(display); } else { (this->*last_spawn_method())(last_spawned_image(),display,false); } history().end_action(); } } void EvolvotronMain::spawn_all(MutatableImageDisplay* spawning_display,SpawnMemberFn method,const std::string& action_name) { // Spawn potentially a bit sluggish so set the hourglass cursor. QApplication::setOverrideCursor(Qt::WaitCursor); history().begin_action(action_name); // Issue new images (except to locked displays and to originator) // This will cause them to abort any running tasks const boost::shared_ptr spawning_image_function(spawning_display->image_function()); last_spawned_image(spawning_image_function,method); for (std::vector::iterator it=displays().begin();it!=displays().end();it++) { if ((*it)!=spawning_display && !(*it)->locked()) { (this->*method)(spawning_image_function,(*it),true); } } history().end_action(); _mutation_parameters.autocool_generations_increment(); QApplication::restoreOverrideCursor(); } /*! If one of our sub displays has spawned, distribute a mutated copy of its image to the other non-locked images in the mutation grid. */ void EvolvotronMain::spawn_normal(MutatableImageDisplay* spawning_display) { spawn_all( spawning_display, &EvolvotronMain::spawn_normal, "spawn" ); } /*! This is the similar to spawn_normal, except images ARE NOT MUTATED after deepclone and have a final transform applied to change their colour. */ void EvolvotronMain::spawn_recoloured(MutatableImageDisplay* spawning_display) { spawn_all( spawning_display, &EvolvotronMain::spawn_recoloured, "spawn recoloured" ); } /*! This is the similar to spawn_normal, except images ARE NOT MUTATED after deepclone and have an initial transform (obtained from the supplied TransformFactory) applied to spatially warp them. */ void EvolvotronMain::spawn_warped(MutatableImageDisplay* spawning_display,const TransformFactory& tfactory) { transform_factory(tfactory); spawn_all( spawning_display, &EvolvotronMain::spawn_warped, "spawn warped" ); } void EvolvotronMain::hello(MutatableImageDisplay* disp) { _known_displays.insert(disp); } void EvolvotronMain::goodbye(MutatableImageDisplay* disp) { _history->goodbye(disp); _known_displays.erase(disp); } bool EvolvotronMain::is_known(MutatableImageDisplay* disp) const { return (_known_displays.find(disp)!=_known_displays.end()); } void EvolvotronMain::list_known(std::ostream& out) const { for (std::set::const_iterator it=_known_displays.begin();it!=_known_displays.end();it++) { out << (*it) << " "; } out << "\n"; } /*! Periodically report number of remaining compute tasks and check farm's done queue for completed tasks. */ void EvolvotronMain::tick() { const uint tasks_main=_farm[0]->tasks(); const uint tasks_enlargement=(_farm[1].get() ? _farm[1]->tasks() : 0); if (tasks_main!=_statusbar_tasks_main || tasks_enlargement!=_statusbar_tasks_enlargement) { std::ostringstream msg; msg << ""; if (tasks_main+tasks_enlargement==0) { msg << "Ready"; } else { msg << tasks_main; if (tasks_enlargement) { msg << "+" << tasks_enlargement; } msg << " tasks remaining"; } _statusbar_tasks_label->setText(msg.str().c_str()); _statusbar_tasks_main=tasks_main; _statusbar_tasks_enlargement=tasks_enlargement; } boost::shared_ptr task; // If there are aborted jobs in the todo queue // shift them straight over to done queue so the compute threads don't have to worry about them. _farm[0]->fasttrack_aborted(); if (_farm[1].get()) _farm[1]->fasttrack_aborted(); QTime watchdog; watchdog.start(); for (int which_farm=0;which_farm<(_farm[1].get() ? 2 : 1);which_farm++) { while ((task=_farm[which_farm]->pop_done())!=0) { if (is_known(task->display())) { task->display()->deliver(task); } else { // If we don't know who owns it we just have to trash it // (probably a top level window which was closed with incomplete tasks). task.reset(); } // Timeout in case we're being swamped by incoming tasks (maintain app responsiveness). if (watchdog.elapsed()>20) break; } } } void EvolvotronMain::keyPressEvent(QKeyEvent* e) { if (e->key()==Qt::Key_Escape) { // Esc key used to back out of menu hide and full screen mode // Might rescue a few users who have got into those states accidentally showNormal(); menuBar()->show(); statusBar()->show(); _menu_action_fullscreen->setChecked(false); _menu_action_hide_menu->setChecked(false); } else if (e->key()==Qt::Key_Z && !(e->modifiers()^Qt::ControlModifier)) { //Ctrl-Z does an undo undo(); } else { // Perhaps it's for someone else e->ignore(); } } void EvolvotronMain::toggle_fullscreen() { if (isFullScreen()) { showNormal(); _menu_action_fullscreen->setChecked(false); } else { showFullScreen(); _menu_action_fullscreen->setChecked(true); } } void EvolvotronMain::toggle_hide_menu() { if (menuBar()->isHidden()) { menuBar()->show(); _menu_action_hide_menu->setChecked(false); } else if (menuBar()->isVisible()) { menuBar()->hide(); _menu_action_hide_menu->setChecked(true); } if (statusBar()->isHidden()) statusBar()->show(); else if (statusBar()->isVisible()) statusBar()->hide(); } /*! Set up an initial random image in the specified display. If a favourite function was specified then we use that as the top level node. */ void EvolvotronMain::reset(MutatableImageDisplay* display) { std::auto_ptr root; if (_dialog_favourite->favourite_function().empty()) { root=std::auto_ptr(FunctionTop::initial(mutation_parameters())); } else { root=std::auto_ptr ( FunctionTop::initial ( mutation_parameters(), mutation_parameters().function_registry().lookup(_dialog_favourite->favourite_function()), _dialog_favourite->favourite_function_unwrapped() ) ); } history().replacing(display); const boost::shared_ptr image_function(new MutatableImage(root,!_linear_zsweep,_spheremap,false)); display->image_function(image_function,true); } void EvolvotronMain::undo() { history().undo(); } void EvolvotronMain::simplify_constants() { history().begin_action("simplify all"); uint nodes_eliminated=0; for (std::vector::iterator it=_displays.begin();it!=_displays.end();it++) { nodes_eliminated+=(*it)->simplify_constants(false); } history().end_action(); std::stringstream msg; msg << "Eliminated " << nodes_eliminated << " redundant function nodes\n"; QMessageBox::information(this,"Evolvotron",msg.str().c_str(),QMessageBox::Ok); } /*! Reset each image in the grid, and the mutation parameters. */ void EvolvotronMain::reset(bool reset_mutation_parameters,bool clear_locks) { history().begin_action("reset/restart"); if (reset_mutation_parameters) { // Invoking reset on the 1st dialog actually resets the parameters _dialog_mutation_parameters->reset(); // This one just serves to setup the function dialog from the now reset parameters _dialog_functions->setup_from_mutation_parameters(); } else { // Seems odd if we don't restart the count. _mutation_parameters.autocool_generations(0); } for (size_t i=0;ilock(false,false); // lock method mustn't make it's own history recording } if (_startup_shuffle) { std::random_shuffle(_startup_filenames.begin(),_startup_filenames.end()); } for (size_t i=0;ilocked()) { if (i<_startup_filenames.size()) displays()[i]->load_function_file(_startup_filenames[i].c_str()); else reset(displays()[i]); } } last_spawned_image(boost::shared_ptr(),&EvolvotronMain::spawn_normal); history().end_action(); } void EvolvotronMain::reset_randomized() { _mutation_parameters.randomize_function_weightings_for_classifications(static_cast(-1)); reset(false,false); } void EvolvotronMain::reset_warm() { reset(false,false); } void EvolvotronMain::reset_cold() { reset(true,true); } void EvolvotronMain::mutation_parameters_changed() { _checkbox_autocool_enable->setChecked(_mutation_parameters.autocool_enable()); if (_mutation_parameters.autocool_enable()) { _label_autocool_enable->setText(QString("Generations:")+QString::number(_mutation_parameters.autocool_generations())); _label_autocool_enable->show(); if (_mutation_parameters.autocool_generations()>0) _button_autocool_reheat->show(); else _button_autocool_reheat->hide(); } else { _label_autocool_enable->hide(); _button_autocool_reheat->hide(); } } void EvolvotronMain::render_parameters_changed() { for (std::set::iterator it=_known_displays.begin();it!=_known_displays.end();it++) (*it)->image_function((*it)->image_function(),true); } evolvotron/libevolvotron/obsolete/tuple.cpp0000644000175100017510000000357512100750251021215 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class Tuple. No Tuple:: code because of usual template instantiation problem. */ #include "tuple.h" //! Test code void testtuple_eliminate(Tuple<2,float>& m_to,const Tuple<3,float>& m_from) { // Skip middle element of m_from TupleHelperCopyEliminate<1,1,2,float>::execute(m_to,m_from); } //! Test code void testtuple_doubleeliminate(Tuple<2,Tuple<2,float> >& m_to,const Tuple<3,Tuple<3,float> >& m_from) { TupleHelperDoubleCopyEliminate<1,1,1,2,2,float>::execute(m_to,m_from); } evolvotron/libevolvotron/obsolete/matrix.cpp0000644000175100017510000000576412100750251021372 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class Matrix. No Matrix:: code because of usual template instantiation problem. */ #include "matrix.h" #include "random.h" #include //! Test code void testmatrix_extract_runtime(Matrix<2,2,float>& m_out,const Matrix<3,3,float>& m_in) { m_in.extract_minor(1,1,m_out); } //! Test code void testmatrix_extract_compiletime(Matrix<2,2,float>& m_out,const Matrix<3,3,float>& m_in) { m_in.extract_minor<1,1>(m_out); } //! Test code float testmatrix_across(const Matrix<3,3,float>& m_in) { return MatrixHelperSumCofactorDeterminantProducts<2,3,3,float>::execute(m_in); } //! Test code void testmatrix_inverse(Matrix<3,3,float>& m_out,const Matrix<3,3,float>& m_in) { m_out=m_in.inverted(); } //! Test code float testmatrix_determinant(const Matrix<3,3,float>& m_in) { return m_in.determinant(); } //! Test code (uncomment out call from main to use) void testmatrix() { std::cout << "Testing matrix class:\n"; Random01 r01(time(0)); for (uint i=0;i<4;i++) { Matrix<3,3,float> m0; for (uint r=0;r m1(m0.inverted()); testmatrix_inverse(m1,m0); m1.write(std::cout); std::cout << "\n"; Matrix<3,3,float> m2=m0*m1; m2.write(std::cout); std::cout << "-----\n"; } } evolvotron/libevolvotron/mutatable_image_computer_task.cpp0000644000175100017510000000644512100750252024330 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutatableImageComputerTask */ #include "libevolvotron_precompiled.h" #include "mutatable_image_computer_task.h" MutatableImageComputerTask::MutatableImageComputerTask ( MutatableImageDisplay*const disp, const boost::shared_ptr& fn, uint pri, const QSize& fo, const QSize& fs, const QSize& wis, uint f, uint lev, uint frag, uint nfrag, bool j, uint ms, unsigned long long int n ) : #ifndef NDEBUG InstanceCounted(typeid(this).name(),false), #endif _aborted(false) ,_display(disp) ,_image_function(fn) ,_priority(pri) ,_fragment_origin(fo) ,_fragment_size(fs) ,_whole_image_size(wis) ,_frames(f) ,_level(lev) ,_fragment(frag) ,_number_of_fragments(nfrag) ,_jittered_samples(j) ,_multisample_grid(ms) ,_current_pixel(0) ,_current_col(0) ,_current_row(0) ,_current_frame(0) ,_completed(false) ,_serial(n) { /* std::cerr << "[" << _number_of_fragments << ":" << _fragment_size.width() << "x" << _fragment_size.height() << " in " << _whole_image_size.width() << "x" << _whole_image_size.height() << "]"; */ assert(_image_function->ok()); assert(_fragment<_number_of_fragments); assert(_number_of_fragments>1 || _whole_image_size==_fragment_size); assert(1<=_multisample_grid); } void MutatableImageComputerTask::allocate_images() const { for (uint f=0;fok()); } void MutatableImageComputerTask::pixel_advance() { _current_pixel++; _current_col++; if (_current_col==fragment_size().width()) { _current_col=0; _current_row++; if (_current_row==fragment_size().height()) { _current_row=0; _current_frame++; if (_current_frame==frames()) { _completed=true; } } } } evolvotron/libevolvotron/dialog_render_parameters.cpp0000644000175100017510000001032012100750277023263 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class DialogRenderParameters. */ #include "libevolvotron_precompiled.h" #include "dialog_render_parameters.h" DialogRenderParameters::DialogRenderParameters(QMainWindow* parent,RenderParameters* rp) :QDialog(parent) ,_render_parameters(rp) { setWindowTitle("Render Parameters"); setSizeGripEnabled(true); setLayout(new QVBoxLayout); layout()->addWidget(_checkbox_jittered_samples=new QCheckBox("Jittered samples")); _checkbox_jittered_samples->setToolTip("Jitter moves sampling positions randomly within a pixel. This helps to break up aliasing and moire patterns."); _buttonvbox=new QGroupBox("Oversampling (antialiasing)"); _buttonvbox->setLayout(new QVBoxLayout); layout()->addWidget(_buttonvbox); QRadioButton* button[4]; _buttonvbox->layout()->addWidget(button[0]=new QRadioButton("1x1")); _buttonvbox->layout()->addWidget(button[1]=new QRadioButton("2x2")); _buttonvbox->layout()->addWidget(button[2]=new QRadioButton("3x3")); _buttonvbox->layout()->addWidget(button[3]=new QRadioButton("4x4")); button[0]->setToolTip("No oversampling"); button[1]->setToolTip("Enables a final antialiased rendering with 4 samples per pixel"); button[2]->setToolTip("Enables a final antialiased rendering with 9 samples per pixel"); button[3]->setToolTip("Enables a final antialiased rendering with 16 samples per pixel"); _buttongroup=new QButtonGroup(_buttonvbox); _buttongroup->addButton(button[0],1); _buttongroup->addButton(button[1],2); _buttongroup->addButton(button[2],3); _buttongroup->addButton(button[3],4); setup_from_render_parameters(); connect(_checkbox_jittered_samples,SIGNAL(stateChanged(int)),this,SLOT(changed_jittered_samples(int))); connect(_buttongroup,SIGNAL(buttonClicked(int)),this,SLOT(changed_oversampling(int))); _ok=new QPushButton("OK"); _ok->setDefault(true); layout()->addWidget(_ok); connect( _ok,SIGNAL(clicked()), this,SLOT(hide()) ); connect( _render_parameters,SIGNAL(changed()), this,SLOT(render_parameters_changed()) ); } DialogRenderParameters::~DialogRenderParameters() {} void DialogRenderParameters::setup_from_render_parameters() { _checkbox_jittered_samples->setChecked(_render_parameters->jittered_samples()); QAbstractButton*const which_button=_buttongroup->button(_render_parameters->multisample_grid()); if (which_button) { which_button->click(); } } void DialogRenderParameters::changed_jittered_samples(int buttonstate) { if (buttonstate==Qt::Checked) _render_parameters->jittered_samples(true); else if (buttonstate==Qt::Unchecked) _render_parameters->jittered_samples(false); } void DialogRenderParameters::changed_oversampling(int id) { assert(1<=id && id<=4); _render_parameters->multisample_grid(id); } void DialogRenderParameters::render_parameters_changed() { setup_from_render_parameters(); } evolvotron/libevolvotron/mutatable_image_display.cpp0000644000175100017510000007633112100750252023116 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutatableImageDisplay. */ #include "libevolvotron_precompiled.h" #include "mutatable_image_display.h" #include "mutatable_image_display_big.h" #include "evolvotron_main.h" #include "mutatable_image_computer_task.h" #include "transform_factory.h" #include "function_pre_transform.h" #include "function_top.h" /*! The constructor is passed: - the owning widget (probably either a QGrid or null if top-level), - the EvolvotronMain providing spawn and farm services, - a flag to specify whether this is a fully functional display or a restricted one (e.g no spawning for a single top level display), - a flag to specify whether the offscreen buffer has fixed size (in which case scrollbars may be used), - and the size of the offscreen buffer (only used if fixed_size is true). Note that we use Qt's WDestructiveCode flag to ensure the destructor is called on close */ MutatableImageDisplay::MutatableImageDisplay(EvolvotronMain* mn,bool full_functionality,bool fixed_size,const QSize& sz,uint f,uint fr) :_main(mn) ,_full_functionality(full_functionality) ,_fixed_size(fixed_size) ,_image_size(sz) ,_frames(f) ,_framerate(fr) ,_current_frame(0) ,_animate_reverse(false) ,_timer(0) ,_resize_in_progress(false) ,_current_display_level(0) ,_current_display_multisample_grid(0) ,_icon_serial(0LL) ,_properties(0) ,_menu(0) ,_menu_big(0) ,_menu_item_action_lock(0) ,_serial(0LL) { setAttribute(Qt::WA_DeleteOnClose,true); setFocusPolicy(Qt::StrongFocus); _properties=new DialogMutatableImageDisplay(this); _menu=new QMenu(this); // Most items on the context menu aren't appropriate for a window displaying a single big image if (_full_functionality) { _menu->addAction("Respawn",this,SLOT(menupick_respawn())); _menu->addSeparator(); _menu->addAction("Spawn",this,SLOT(menupick_spawn())); _menu->addAction("Spawn recoloured",this,SLOT(menupick_spawn_recoloured())); _menu_warped=_menu->addMenu("Spawn warped"); _menu_warped->addAction("Random Mix",this,SLOT(menupick_spawn_warped_random()) ); _menu_warped->addAction("Zoom In" ,this,SLOT(menupick_spawn_warped_zoom_in()) ); _menu_warped->addAction("Zoom Out" ,this,SLOT(menupick_spawn_warped_zoom_out())); _menu_warped->addAction("Rotate" ,this,SLOT(menupick_spawn_warped_rotate()) ); _menu_warped->addAction("Pan XY" ,this,SLOT(menupick_spawn_warped_pan_xy()) ); _menu_warped->addAction("Pan X" ,this,SLOT(menupick_spawn_warped_pan_x()) ); _menu_warped->addAction("Pan Y" ,this,SLOT(menupick_spawn_warped_pan_y()) ); _menu_warped->addAction("Pan Z" ,this,SLOT(menupick_spawn_warped_pan_z()) ); _menu->addSeparator(); _menu_item_action_lock=_menu->addAction("Lock",this,SLOT(menupick_lock())); _menu_item_action_lock->setCheckable(true); _menu->addSeparator(); } _menu_big=_menu->addMenu("Enlarge"); _menu_big->addAction("Resizable",this,SLOT(menupick_big_resizable())); _menu_big->addSeparator(); _menu_big->addAction("256x256" ,this,SLOT(menupick_big_256x256())); _menu_big->addAction("512x512" ,this,SLOT(menupick_big_512x512()) ); _menu_big->addAction("768x768" ,this,SLOT(menupick_big_768x768()) ); _menu_big->addAction("1024x1024",this,SLOT(menupick_big_1024x1024())); _menu_big->addAction("2048x2048",this,SLOT(menupick_big_2048x2048())); _menu_big->addAction("4096x4096",this,SLOT(menupick_big_4096x4096())); _menu_big->addSeparator(); _menu_big->addAction("640x480" ,this,SLOT(menupick_big_640x480()) ); _menu_big->addAction("1024x768" ,this,SLOT(menupick_big_1024x768()) ); _menu_big->addAction("1280x960" ,this,SLOT(menupick_big_1280x960()) ); _menu_big->addAction("1600x1200",this,SLOT(menupick_big_1600x1200())); _menu->addSeparator(); _menu->addAction("Save image",this,SLOT(menupick_save_image())); _menu->addAction("Save function",this,SLOT(menupick_save_function())); if (_full_functionality) { _menu->addAction("Load function",this,SLOT(menupick_load_function())); } _menu->addSeparator(); _menu->addAction("Simplify function",this,SLOT(menupick_simplify())); _menu->addAction("Properties...",this,SLOT(menupick_properties())); main().hello(this); if (_fixed_size) { setGeometry(0,0,image_size().width(),image_size().height()); } for (uint f=0;f<_frames;f++) { _offscreen_pixmaps.push_back(QPixmap()); } _timer=new QTimer(this); connect ( _timer,SIGNAL(timeout()), this,SLOT(frame_advance()) ); if (_frames>1) _timer->start(1000/_framerate); } /*! Destructor signs off from EvolvotronMain to prevent further attempts at completed task delivery. */ MutatableImageDisplay::~MutatableImageDisplay() { assert(!_image_function.get() || _image_function->ok()); // During app shutdown EvolvotronMain might have already been destroyed so only call it if it's there. // Don't use main() because it asserts non-null. if (_main) { farm().abort_for(this); main().goodbye(this); } _image_function.reset(); _offscreen_pixmaps.clear(); _offscreen_images.clear(); } uint MutatableImageDisplay::simplify_constants(bool single_action) { if (single_action) main().history().begin_action("simplify"); uint old_nodes; uint old_parameters; uint old_depth; uint old_width; real old_const; _image_function->get_stats(old_nodes,old_parameters,old_depth,old_width,old_const); main().history().replacing(this); image_function(_image_function->simplified(),!single_action); uint new_nodes; uint new_parameters; uint new_depth; uint new_width; real new_const; _image_function->get_stats(new_nodes,new_parameters,new_depth,new_width,new_const); const uint nodes_eliminated=old_nodes-new_nodes; if (single_action) main().history().end_action(); if (single_action) { if (_icon.get()) _main->setWindowIcon(*_icon); std::stringstream msg; msg << "Eliminated " << nodes_eliminated << " redundant function nodes\n"; QMessageBox::information(this,"Evolvotron",msg.str().c_str(),QMessageBox::Ok); } return nodes_eliminated; } void MutatableImageDisplay::frame_advance() { assert(!(_current_frame==0 && _animate_reverse==true)); assert(!(_current_frame==_frames-1 && _animate_reverse==false)); if (_animate_reverse) { _current_frame--; if (_current_frame==0) { _animate_reverse=false; } } else { _current_frame++; if (_current_frame==_frames-1) { _animate_reverse=true; } } repaint(); // Use repaint rather than update because we really do want this to happen immediately. } void MutatableImageDisplay::image_function(const boost::shared_ptr& i,bool one_of_many) { assert(_image_function.get()==0 || _image_function->ok()); assert(i.get()==0 || i->ok()); // New image, so increment serial number so any old incoming stuff which somehow avoids abort is ignored. _serial++; // This might have already been done (e.g by resizeEvent), but it can't hurt to be sure. farm().abort_for(this); // Careful: we could be passed our own existing (and already owned) image // (a trick used by resize to trigger recompute & redisplay) if (i.get()==0 || _image_function.get()==0 || i->serial()!=_image_function->serial()) { _image_function=i; // If we're part of a fullscale change then better to display back rather than something misleading // but for one-offs (e.g middle mouse drag) is better not to clear. if (one_of_many) { // Clear any existing image data - stops old animations continuing to play for (uint f=0;f<_offscreen_pixmaps.size();f++) _offscreen_pixmaps[f].fill(QColor(0,0,0)); // Queue a redraw update(); } } // If we start recomputing again we need to accept any delivered images. _current_display_level=static_cast(-1); _current_display_multisample_grid=static_cast(-1); // Clear up staging area... its contents are now useless _offscreen_images_inbox.clear(); // Update lock status displayed in menu if (_menu_item_action_lock) _menu_item_action_lock->setChecked(_image_function.get() ? _image_function->locked() : false); if (_image_function.get()) { // Allow for displays up to 4096 pixels high or wide for (int level=12;level>=0;level--) { const int s=(1<=4 && render_size.height()>=4) || level==0) { const int fragments =( one_of_many ? 1 : std::min ( 2*farm().num_threads(), static_cast(render_size.height()) ) ); std::vector multisample_grid; multisample_grid.push_back(1); if (level==0) { // Only the final full resolution level gets an additional multisampling task. // For 4x4 sampling, do an initial 2x2 too. if (main().render_parameters().multisample_grid()==4) multisample_grid.push_back(2); if (main().render_parameters().multisample_grid()>1) multisample_grid.push_back(main().render_parameters().multisample_grid()); } for (std::vector::const_iterator multisample_it=multisample_grid.begin();multisample_it!=multisample_grid.end();multisample_it++) { //! \todo Should computed animation frames be constant or reduced c.f spatial resolution ? (Do full z resolution for now) const boost::shared_ptr task_image(_image_function); assert(task_image->ok()); // Use number of samples in unfragmented image as priority const uint task_priority=render_size.width()*render_size.height()*(*multisample_it)*(*multisample_it); int fragment_start_row=0; for (int f=0;f task ( new MutatableImageComputerTask ( this, task_image, task_priority, QSize(0,fragment_start_row), QSize(render_size.width(),fragment_end_row-fragment_start_row), render_size, _frames, level, f, fragments, main().render_parameters().jittered_samples(), (*multisample_it), _serial ) ); farm().push_todo(task); fragment_start_row=fragment_end_row; } } } } } } void MutatableImageDisplay::deliver(const boost::shared_ptr& task) { // Ignore tasks which were aborted or which have somehow got out of order // (entirely possible with multiple compute threads). if ( task->aborted() || task->serial()!=_serial || task->level()>_current_display_level || (task->level()==_current_display_level && task->multisample_grid()<=_current_display_multisample_grid) ) return; // Record the fragment in the inbox const OffscreenImageInbox::key_type inbox_key(task->level(),task->multisample_grid()); OffscreenImageInbox::mapped_type& inbox_level=_offscreen_images_inbox[inbox_key]; assert(inbox_level.find(task->fragment())==inbox_level.end()); inbox_level[task->fragment()]=task; if (inbox_level.size()!=task->number_of_fragments()) return; // If the level is complete, we can proceed to displaying it // Note that obsolete levels will never complete once a better one is displayed. // So clear up previous levels; they're now irrelevant _offscreen_images_inbox.erase ( _offscreen_images_inbox.upper_bound(inbox_key), // upper_bound is the NEXT key from the one we're about to display _offscreen_images_inbox.end() ); const QSize render_size(task->whole_image_size()); if (task->number_of_fragments()==1) { // If there's only one fragment in the task, just use it _offscreen_images=task->images(); } else { // Otherwise we need to assemble the fragments together _offscreen_images.resize(0); for (uint f=0;f<_frames;f++) { _offscreen_images.push_back(QImage(render_size,QImage::Format_RGB32)); for (OffscreenImageInbox::mapped_type::const_iterator it=inbox_level.begin();it!=inbox_level.end();++it) { QPainter painter(&_offscreen_images.back()); painter.drawImage ( QPoint((*it).second->fragment_origin().width(),(*it).second->fragment_origin().height()), (*it).second->images()[f] ); } } } for (uint f=0;f<_frames;f++) { //! \todo Pick a scaling mode: Qt::SmoothTransformation vs Qt::FastTransformation (default) (and put it under GUI control). //! \todo Expose dither mode control: Qt::DiffuseDither vs Qt::ThresholdDither _offscreen_pixmaps[f]=QPixmap::fromImage(_offscreen_images[f].scaled(image_size()),(Qt::ColorOnly|Qt::ThresholdDither)); } //! Note the resolution we've displayed so out-of-order low resolution images are dropped _current_display_level=task->level(); _current_display_multisample_grid=task->multisample_grid(); // For an icon, take the first image big enough to (hopefully) be filtered down nicely. // The (Qt3) converter seems to auto-create an alpha mask sometimes (images with const-color areas), which is quite cool. const QSize icon_size(32,32); if (task->serial()!=_icon_serial && (task->level()==0 || (render_size.width()>=2*icon_size.width() && render_size.height()>=2*icon_size.height()))) { const QImage icon_image(_offscreen_images[_offscreen_images.size()/2].scaled(icon_size)); if (!_icon.get()) _icon=std::auto_ptr(new QPixmap(icon_size)); (*_icon)=QPixmap::fromImage(icon_image,Qt::ColorOnly); _icon_serial=task->serial(); } // Update what's on the screen. update(); } void MutatableImageDisplay::lock(bool l,bool record_in_history) { // This might be called (with l=false) with null _image during start-up reset. if (_image_function && _image_function->locked()!=l) { if (record_in_history) { main().history().begin_action(l ? "lock" : "unlock"); main().history().replacing(this); } const boost::shared_ptr new_image_function(_image_function->deepclone(l)); image_function(new_image_function,false); if (record_in_history) { main().history().end_action(); } } _menu_item_action_lock->setChecked(l); } /*! Enlargements are implied by a non-full-functionality displays. */ MutatableImageComputerFarm& MutatableImageDisplay::farm() const { return main().farm(!_full_functionality); } void MutatableImageDisplay::paintEvent(QPaintEvent*) { // Repaint the screen from the offscreen pixmaps QPainter painter(this); painter.drawPixmap(0,0,_offscreen_pixmaps[_current_frame]); // If this is the first paint event after a resize we can start computing images for the new size. if (_resize_in_progress) { image_function(_image_function,false); // A resize should really be considered one-of-many, but because the image doesn't change we seem to be able to get away with it _resize_in_progress=false; } } /*! In the resize event we just focus on shutting down existing compute threads because they'll all have to be restarted. NB Multiple resize events can be received before a repaint occurs. NB There's nothing to be done for fixed size images (not even setting _resize_in_progress). */ void MutatableImageDisplay::resizeEvent(QResizeEvent* event) { // Fixed size images don't need anything doing here. We don't even set _resize_in_progress. if (!_fixed_size) { _image_size=event->size(); // Abort all current tasks because they'll be the wrong size. farm().abort_for(this); // Resize and reset our offscreen pixmap (something to do while we wait) for (uint f=0;f<_offscreen_pixmaps.size();f++) { _offscreen_pixmaps[f]=QPixmap(image_size()); _offscreen_pixmaps[f].fill(QColor(0,0,0)); } // Flag for the next paintEvent to tell it a recompute can be started now. _resize_in_progress=true; } } void MutatableImageDisplay::mousePressEvent(QMouseEvent* event) { if (event->button()==Qt::RightButton) { _menu->exec(QCursor::pos()); } else if (event->button()==Qt::MidButton) { // Take a snapshot to undo back to. main().history().begin_action("middle-button drag"); main().history().replacing(this); main().history().end_action(); _mid_button_adjust_start_pos=event->pos(); _mid_button_adjust_last_pos=event->pos(); } else if (_full_functionality && event->button()==Qt::LeftButton) { if (_icon.get()) _main->setWindowIcon(*_icon); menupick_spawn(); } } void MutatableImageDisplay::mouseMoveEvent(QMouseEvent* event) { if (event->buttons()&Qt::MidButton) { if (locked()) { QMessageBox::warning(this,"Evolvotron","Cannot middle-mouse adjust a locked image.\nUnlock and try again."); } else { const QPoint pixel_delta(event->pos()-_mid_button_adjust_last_pos); // Build the transform caused by the adjustment Transform transform=TransformIdentity(); // Shift button (no ctrl) is various zooms if (event->modifiers()&Qt::ShiftModifier && !(event->modifiers()&Qt::ControlModifier)) { // Alt-Shift is anisotropic if (event->modifiers()&Qt::AltModifier) { // Only scale in non-degenerate cases if ( event->pos().x()!=image_size().width()/2 && event->pos().y()!=image_size().height()/2 && _mid_button_adjust_last_pos.x()!=image_size().width()/2 && _mid_button_adjust_last_pos.y()!=image_size().height()/2 ) { XYZ scale( (event->pos().x()-image_size().width() /2) / static_cast(_mid_button_adjust_last_pos.x()-image_size().width() /2), (event->pos().y()-image_size().height()/2) / static_cast(_mid_button_adjust_last_pos.y()-image_size().height()/2), 0.0 ); transform.basis_x(XYZ(1.0/scale.x(), 0.0,0.0)); transform.basis_y(XYZ( 0.0,1.0/scale.y(),0.0)); std::clog << "[Anisotropic scale]"; } } // Shift button alone is isotropic zoom else { const real cx=image_size().width()/2.0; const real cy=image_size().width()/2.0; const real dx=event->pos().x()-cx; const real dy=event->pos().y()-cy; const real last_dx=_mid_button_adjust_last_pos.x()-cx; const real last_dy=_mid_button_adjust_last_pos.y()-cy; const real radius=sqrt(dx*dx+dy*dy); const real last_radius=sqrt(last_dx*last_dx+last_dy*last_dy); // Only scale in non-degenerate cases if (radius!=0.0 && last_radius!=0.0) { const real scale=radius/last_radius; transform.basis_x(XYZ(1.0/scale, 0.0,0.0)); transform.basis_y(XYZ( 0.0,1.0/scale,0.0)); std::clog << "[Isotropic scale]"; } } } else if (event->modifiers()&Qt::ControlModifier) { // Control-alt is shear if (event->modifiers()&Qt::AltModifier) { const real cx=image_size().width()/2.0; const real cy=image_size().width()/2.0; const real dx=(event->pos().x()-_mid_button_adjust_last_pos.x())/cx; const real dy=(event->pos().y()-_mid_button_adjust_last_pos.y())/cy; transform.basis_x(XYZ(1.0, -dy,0.0)); transform.basis_y(XYZ( dx,1.0,0.0)); std::clog << "[Shear]"; } // Control button only is rotate else { const real cx=image_size().width()/2.0; const real cy=image_size().width()/2.0; const real dx=event->pos().x()-cx; const real dy=event->pos().y()-cy; const real last_dx=_mid_button_adjust_last_pos.x()-cx; const real last_dy=_mid_button_adjust_last_pos.y()-cy; const real a=atan2(dy,dx); const real last_a=atan2(last_dy,last_dx); const real rot=a-last_a; const real sr=sin(rot); const real cr=cos(rot); transform.basis_x(XYZ( cr,sr,0.0)); transform.basis_y(XYZ(-sr,cr,0.0)); std::clog << "[Rotate]"; } } // Default (no interesting modifier keys detected) is panning around else { XYZ translate( (-2.0*pixel_delta.x())/image_size().width(), ( 2.0*pixel_delta.y())/image_size().height(), 0.0 ); transform.translate(translate); std::clog << "[Pan]"; } std::auto_ptr new_root(image_function()->top().typed_deepclone()); new_root->concatenate_pretransform_on_right(transform); // Install new image (triggers recompute). const boost::shared_ptr new_image_function(new MutatableImage(new_root,image_function()->sinusoidal_z(),image_function()->spheremap(),false)); image_function(new_image_function,false); // Finally, record position of this event as last event _mid_button_adjust_last_pos=event->pos(); } } } /*! This slot is called by selecting the "Respawn" context menu item */ void MutatableImageDisplay::menupick_respawn() { main().respawn(this); } /*! This slot is called by selecting the "Spawn" context menu item, or by clicking the image */ void MutatableImageDisplay::menupick_spawn() { main().spawn_normal(this); } /*! This slot is called by selecting the "Spawn Recoloured" context menu item */ void MutatableImageDisplay::menupick_spawn_recoloured() { main().spawn_recoloured(this); } /*! This slot is called by selecting the "Spawn Warped/Random" context menu item */ void MutatableImageDisplay::menupick_spawn_warped_random() { TransformFactoryRandomWarpXY transform_factory; main().spawn_warped(this,transform_factory); } void MutatableImageDisplay::menupick_spawn_warped_zoom_in() { TransformFactoryRandomScaleXY transform_factory(-2.0,0.0); main().spawn_warped(this,transform_factory); } void MutatableImageDisplay::menupick_spawn_warped_zoom_out() { TransformFactoryRandomScaleXY transform_factory(0.0,2.0); main().spawn_warped(this,transform_factory); } void MutatableImageDisplay::menupick_spawn_warped_rotate() { TransformFactoryRandomRotateZ transform_factory; main().spawn_warped(this,transform_factory); } void MutatableImageDisplay::menupick_spawn_warped_pan_xy() { TransformFactoryRandomTranslateXYZ transform_factory(XYZ(0.0,0.0,0.0),XYZ(1.0,1.0,0.0)); main().spawn_warped(this,transform_factory); } void MutatableImageDisplay::menupick_spawn_warped_pan_x() { TransformFactoryRandomTranslateXYZ transform_factory(XYZ(0.0,0.0,0.0),XYZ(1.0,0.0,0.0)); main().spawn_warped(this,transform_factory); } void MutatableImageDisplay::menupick_spawn_warped_pan_y() { TransformFactoryRandomTranslateXYZ transform_factory(XYZ(0.0,0.0,0.0),XYZ(0.0,1.0,0.0)); main().spawn_warped(this,transform_factory); } void MutatableImageDisplay::menupick_spawn_warped_pan_z() { TransformFactoryRandomTranslateXYZ transform_factory(XYZ(0.0,0.0,0.0),XYZ(0.0,0.0,1.0)); main().spawn_warped(this,transform_factory); } /*! This slot is called by selecting the "Lock" context menu item. It stops the image from being overwritten by a new image. */ void MutatableImageDisplay::menupick_lock() { lock(!_image_function->locked(),true); } void MutatableImageDisplay::menupick_simplify() { simplify_constants(true); } /*! Saves image (unless the image is not full resolution yet, in which case an informative dialog is generated. */ void MutatableImageDisplay::menupick_save_image() { if (_icon.get()) _main->setWindowIcon(*_icon); std::clog << "Save requested...\n"; if (_current_display_level!=0 || _current_display_multisample_grid!=main().render_parameters().multisample_grid()) { QMessageBox::information(this,"Evolvotron","The selected image has not yet been generated at maximum resolution.\nPlease try again later."); } else { const QString save_filename=QFileDialog::getSaveFileName ( this, "Save image to a PNG or PPM file", ".", "Images (*.png *.ppm)" ); if (!save_filename.isEmpty()) { QString save_format="PNG"; if (save_filename.toUpper().endsWith(".PPM")) { save_format="PPM"; } else if (save_filename.toUpper().endsWith(".PNG")) { save_format="PNG"; } else { QMessageBox::warning ( this, "Evolvotron", QString("Unrecognised file suffix.\nFile will be written in ")+save_format+QString(" format.") ); } for (uint f=0;f<_offscreen_images.size();f++) { QString actual_save_filename(save_filename); if (_offscreen_images.size()>1) { QString frame_component; frame_component.sprintf(".f%06d",f); int insert_point=save_filename.lastIndexOf(QString(".")); if (insert_point==-1) { actual_save_filename.append(frame_component); } else { actual_save_filename.insert(insert_point,frame_component); } } if (!_offscreen_images[f].save(actual_save_filename,save_format.toLocal8Bit())) { QMessageBox::critical(this,"Evolvotron","Failed to write file "+actual_save_filename); if (f<_offscreen_images.size()-1) { QMessageBox::critical(this,"Evolvotron","Not attempting to save remaining images in animation"); } break; } } } } std::clog << "...save done\n"; } void MutatableImageDisplay::menupick_save_function() { if (_icon.get()) _main->setWindowIcon(*_icon); const QString save_filename=QFileDialog::getSaveFileName ( this, "Save image function to an XML file", ".", "Functions (*.xml)" ); if (!save_filename.isEmpty()) { std::ofstream file(save_filename.toLocal8Bit()); _image_function->save_function(file); file.flush(); if (!file) { QMessageBox::critical(this,"Evolvotron","File write failed"); } } } void MutatableImageDisplay::load_function_file(const QString& load_filename) { const std::string filename(load_filename.toLocal8Bit()); std::ifstream file(filename.c_str()); if (!file) { QMessageBox::critical( this, "Evolvotron", ("Filename '"+filename+"' could not be opened\n").c_str() ); } else { std::string report; boost::shared_ptr new_image_function(MutatableImage::load_function(_main->mutation_parameters().function_registry(),file,report)); if (new_image_function.get()==0) { QMessageBox::critical( this, "Evolvotron", ("Function in filename '"+filename+"' not loaded due to errors:\n"+report).c_str() ); } else { if (!report.empty()) { QMessageBox::warning( this, "Evolvotron", ("Function in filename '"+filename+"' +loaded with warnings:\n"+report).c_str(), QMessageBox::Ok, QMessageBox::NoButton ); } main().history().begin_action("load"); main().history().replacing(this); main().history().end_action(); image_function(new_image_function,false); } } } void MutatableImageDisplay::menupick_load_function() { const QString load_filename=QFileDialog::getOpenFileName ( this, "Load image function from an XML file", ".", "Functions (*.xml)" ); if (!load_filename.isEmpty()) { load_function_file(load_filename); } } void MutatableImageDisplay::menupick_big_resizable() { spawn_big(false,QSize(0,0)); } void MutatableImageDisplay::menupick_big_640x480() { spawn_big(true,QSize(640,480)); } void MutatableImageDisplay::menupick_big_1024x768() { spawn_big(true,QSize(1024,768)); } void MutatableImageDisplay::menupick_big_1280x960() { spawn_big(true,QSize(1280,960)); } void MutatableImageDisplay::menupick_big_1600x1200() { spawn_big(true,QSize(1600,1200)); } void MutatableImageDisplay::menupick_big_256x256() { spawn_big(true,QSize(256,256)); } void MutatableImageDisplay::menupick_big_512x512() { spawn_big(true,QSize(512,512)); } void MutatableImageDisplay::menupick_big_768x768() { spawn_big(true,QSize(768,768)); } void MutatableImageDisplay::menupick_big_1024x1024() { spawn_big(true,QSize(1024,1024)); } void MutatableImageDisplay::menupick_big_2048x2048() { spawn_big(true,QSize(2048,2048)); } void MutatableImageDisplay::menupick_big_4096x4096() { spawn_big(true,QSize(4096,4096)); } void MutatableImageDisplay::menupick_properties() { uint total_nodes; uint total_parameters; uint depth; uint width; real proportion_constant; image_function()->get_stats(total_nodes,total_parameters,depth,width,proportion_constant); std::stringstream msg; msg << " " << total_nodes << "\t function nodes\n"; msg << " " << total_parameters << "\t parameters\n"; msg << " " << depth << "\t maximum depth\n"; msg << " " << width << "\t width\n"; msg << " " << std::setprecision(3) << 100.0*proportion_constant << "%\t constant\n"; std::stringstream xml; image_function()->save_function(xml); _properties->set_content(msg.str(),xml.str()); if (_icon.get()) _properties->setWindowIcon(*_icon); _properties->exec(); } /*! Create an image display with no parent: becomes a top level window Disable full menu functionality because there's less we can do with a single image (e.g no spawn_target) */ void MutatableImageDisplay::spawn_big(bool scrollable,const QSize& sz) { MutatableImageDisplayBig*const top_level_widget=new MutatableImageDisplayBig(&main()); top_level_widget->setLayout(new QVBoxLayout); if (_icon.get()) top_level_widget->setWindowIcon(*_icon); MutatableImageDisplay* display=0; if (scrollable) { QScrollArea*const scrollview=new QScrollArea; top_level_widget->layout()->addWidget(scrollview); display=new MutatableImageDisplay(&main(),false,true,sz,_frames,_framerate); scrollview->setWidget(display); } else { display=new MutatableImageDisplay(&main(),false,false,QSize(0,0),_frames,_framerate); top_level_widget->layout()->addWidget(display); } top_level_widget->show(); //Propagate full screen mode if (main().isFullScreen()) top_level_widget->showFullScreen(); // Fire up image calculation display->image_function(_image_function,false); } evolvotron/libevolvotron/dialog_help.cpp0000644000175100017510000000674112100750252020516 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class DialogHelp. */ #include "libevolvotron_precompiled.h" #include "dialog_help.h" #include "license.h" //! The text to be displayed /*! \todo Should obtain this from processing external (X)HTML docs, if there were any. */ static const char*const helptext_short= "" "

Evolvotron Quick Reference

" "

Keyboard

" "
    " "
  • " " F - Toggle fullscreen mode" "
  • " "
  • " " M - Hide menu and status bars" "
  • " "
  • " " Esc - Returns to normal mode from full-screen/menu-hidden mode." "
  • " "
  • " " R - Reset (reset mutation paramters and locks)" "
  • " "
  • " " T - Restart (preserve mutation paramters and locks)" "
  • " "
  • " " X - Remix (randomize function weights and restart)" "
  • " "
  • " " Ctrl-Z or U - Undo" "
  • " "
" "

Mouse

" "

Left-click

" "

Spawns mutant offspring.

" "

Middle-drag

" "
    " "
  • " " Unmodified - pan" "
  • " "
  • " " Shift - isotropic zoom" "
  • " "
  • " " Alt-Shift - anisotropic zoom" "
  • " "
  • " " Ctrl - rotate about centre" "
  • " "
  • " " Ctrl-Alt - shear" "
  • " "
" "

Right-click

" "

Brings up context menu.

" "

Command Line Options

" "

" "Command line options are described in the user manual." "A short summary can be obtained by invoking evolvotron with the -h or --help option" "

" "
" ; static const char*const helptext_long= #include "usage_text.h" ; DialogHelp::DialogHelp(QWidget* parent,bool full) :QDialog(parent) { setWindowTitle(full ? "Evolvotron User Manual" : "Evolvotron Quick Reference"); setMinimumSize(480,360); setSizeGripEnabled(true); setLayout(new QVBoxLayout); QTextBrowser*const browser=new QTextBrowser; layout()->addWidget(browser); browser->setText(full ? helptext_long : helptext_short); QPushButton*const ok=new QPushButton("OK"); layout()->addWidget(ok); ok->setDefault(true); connect ( ok,SIGNAL(clicked()), this,SLOT(hide()) ); } DialogHelp::~DialogHelp() {} evolvotron/libevolvotron/dialog_mutatable_image_display.cpp0000644000175100017510000000461512100750277024440 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class DialogMutatableImageDisplay. */ #include "libevolvotron_precompiled.h" #include "dialog_mutatable_image_display.h" DialogMutatableImageDisplay::DialogMutatableImageDisplay(QWidget* parent) :QDialog(parent) { setWindowTitle("Image Properties"); setSizeGripEnabled(true); setLayout(new QVBoxLayout); _tabs=new QTabWidget; layout()->addWidget(_tabs); _label_info=new QLabel(QString("")); _tabs->addTab(_label_info,"Summary"); _textedit_xml=new QTextEdit; _textedit_xml->setReadOnly(true); _tabs->addTab(_textedit_xml,"Detail"); _ok=new QPushButton("OK"); _ok->setDefault(true); layout()->addWidget(_ok); connect( _ok,SIGNAL(clicked()), this,SLOT(hide()) ); } DialogMutatableImageDisplay::~DialogMutatableImageDisplay() {} void DialogMutatableImageDisplay::set_content(const std::string& m,const std::string& x) { _label_info->setText(QString(m.c_str())); _label_info->adjustSize(); _textedit_xml->setPlainText(x.c_str()); adjustSize(); updateGeometry(); } evolvotron/libevolvotron/mutatable_image_computer.cpp0000644000175100017510000001155312100750252023302 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutatableImageComputer. */ #include "libevolvotron_precompiled.h" #include "mutatable_image_computer.h" #include "mutatable_image.h" #include "mutatable_image_computer_farm.h" #include "mutatable_image_computer_task.h" #include "platform_specific.h" MutatableImageComputer::MutatableImageComputer(MutatableImageComputerFarm* frm,int niceness) : #ifndef NDEBUG InstanceCounted(typeid(this).name(),false), #endif _farm(frm), _niceness(niceness), _r01(23) // Seed pretty unimportant; only used for sample jitter { start(); } MutatableImageComputer::~MutatableImageComputer() { std::clog << "Deleting a computer...\n"; kill(); wait(); _task.reset(); std::clog << "...deleted a computer\n"; } /*! Compute threads run this method until killed (probably by the destructor being invoked by the original spawning thread. */ void MutatableImageComputer::run() { std::clog << "Thread starting\n"; // Lower compute thread priority slightly; computing yet more stuff // is less important than displaying the results we've got so far. add_thread_niceness(_niceness); // Run until something sets the kill flag while(!communications().kill()) { // If we don't have a task try and get one. This will block or return null. if (task()==0) { _task=farm()->pop_todo(*this); } if (task()) { // Careful, we could be given an already aborted task if (!task()->aborted()) { while (!communications().kill_or_abort_or_defer() && !task()->completed()) { XYZ accumulated_colour=task()->image_function()->get_rgb ( task()->fragment_origin().width()+task()->current_col(), task()->fragment_origin().height()+task()->current_row(), task()->current_frame(), task()->whole_image_size().width(), task()->whole_image_size().height(), task()->frames(), (task()->jittered_samples() ? &_r01 : 0), task()->multisample_grid() ); const uint col0=lrint(accumulated_colour.x()); const uint col1=lrint(accumulated_colour.y()); const uint col2=lrint(accumulated_colour.z()); task()->images()[task()->current_frame()].setPixel(task()->current_col(),task()->current_row(),((col0<<16)|(col1<<8)|(col2))); task()->pixel_advance(); } } // Maybe should capture copies of the flags for use here if (!communications().kill()) { if (communications().defer() && !communications().abort()) { farm()->push_todo(task()); communications().defer(false); _task.reset(); } else { if (communications().abort()) { task()->abort(); } communications().defer(false); communications().abort(false); farm()->push_done(task()); _task.reset(); } } } } std::clog << "Thread shutting down\n"; } bool MutatableImageComputer::defer_if_less_important_than(uint pri) { const boost::shared_ptr task_tmp=_task; if (task_tmp && task_tmp->priority()>pri) { communications().defer(true); return true; } else { return false; } } void MutatableImageComputer::abort() { communications().abort(true); } void MutatableImageComputer::abort_for(const MutatableImageDisplay* disp) { if (task()!=0 && task()->display()==disp) { communications().abort(true); } } void MutatableImageComputer::kill() { communications().kill(true); } bool MutatableImageComputer::killed() const { return communications().kill(); } evolvotron/libevolvotron/platform_specific.cpp0000644000175100017510000000705212100750277021743 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of platform specific functions. */ #include "libevolvotron_precompiled.h" #include "platform_specific.h" #ifdef PLATFORM_LINUX #include // for CPU count #include // for getpriority/setprioirty #endif #ifdef PLATFORM_BSD #include // for CPU count #include // for CPU count #include // for getpriority/setprioirty #endif uint get_number_of_processors() { boost::optional num_processors; #ifdef PLATFORM_LINUX { cpu_set_t cpus; if (sched_getaffinity(0,sizeof(cpu_set_t),&cpus)==0) { uint bits=0; for (int i=0;i. */ /**************************************************************************/ /*! \file \brief Implementation of class DialogFavourite. */ #include "libevolvotron_precompiled.h" #include "dialog_favourite.h" #include "function_registry.h" #include "evolvotron_main.h" DialogFavourite::DialogFavourite(EvolvotronMain* parent) :QDialog(parent) ,_parent(parent) ,_favourite_function_unwrapped(false) { setWindowTitle("Favourite"); setSizeGripEnabled(true); setLayout(new QVBoxLayout); QGroupBox*const group0=new QGroupBox("Function"); group0->setLayout(new QVBoxLayout); layout()->addWidget(group0); group0->layout()->addWidget(new QLabel("Root node for new image functions:")); _favourite=new QComboBox; group0->layout()->addWidget(_favourite); _favourite_fn_to_index[""]=_favourite->count(); _index_to_favourite_fn[_favourite->count()]=""; _favourite->addItem("- No preference -"); for (FunctionRegistry::Registrations::const_iterator it=_parent->mutation_parameters().function_registry().registrations().begin(); it!=_parent->mutation_parameters().function_registry().registrations().end(); it++ ) { const FunctionRegistration& fn= #if BOOST_VERSION >= 103400 *(it->second); #else *it; #endif _favourite_fn_to_index[fn.name()]=_favourite->count(); _index_to_favourite_fn[_favourite->count()]=fn.name(); _favourite->addItem(fn.name().c_str()); } QGroupBox*const group1=new QGroupBox("Wrapping"); group1->setLayout(new QVBoxLayout); layout()->addWidget(group1); _unwrapped=new QCheckBox("Disable additional space/colour transforms"); group1->layout()->addWidget(_unwrapped); //! \todo: Add OK & reset/restart versions ? QPushButton*const ok=new QPushButton("OK"); layout()->addWidget(ok); ok->setDefault(true); update_gui_from_state(); connect(_favourite,SIGNAL(activated(int)),this,SLOT(changed_favourite(int))); connect(_unwrapped,SIGNAL(toggled(bool)),this,SLOT(changed_unwrapped(bool))); connect(ok,SIGNAL(clicked()),this,SLOT(hide())); } DialogFavourite::~DialogFavourite() {} void DialogFavourite::changed_favourite(int i) { const std::map::const_iterator it=_index_to_favourite_fn.find(i); if (it!=_index_to_favourite_fn.end()) { _favourite_function=(*it).second; } update_gui_from_state(); } void DialogFavourite::changed_unwrapped(bool b) { _favourite_function_unwrapped=b; update_gui_from_state(); } void DialogFavourite::update_gui_from_state() { const std::map::const_iterator it=_favourite_fn_to_index.find(_favourite_function); if (it!=_favourite_fn_to_index.end()) _favourite->setCurrentIndex((*it).second); else _favourite->setCurrentIndex(0); _unwrapped->setChecked(_favourite_function_unwrapped); _unwrapped->setEnabled(!_favourite_function.empty()); } bool DialogFavourite::favourite_function(const std::string& f) { if (_parent->mutation_parameters().function_registry().lookup(f)) { _favourite_function=f; update_gui_from_state(); return true; } else return false; } void DialogFavourite::favourite_function_unwrapped(bool v) { _favourite_function_unwrapped=v; update_gui_from_state(); } evolvotron/libevolvotron/mutation_parameters_qobject.cpp0000644000175100017510000000347612100750252024043 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutationParametersQObject. */ #include "libevolvotron_precompiled.h" #include "mutation_parameters_qobject.h" MutationParametersQObject::MutationParametersQObject(uint seed,bool autocool,bool debug_mode,QObject* parent) :QObject(parent) ,MutationParameters(seed,autocool,debug_mode) {} MutationParametersQObject::~MutationParametersQObject() {} void MutationParametersQObject::report_change() { emit changed(); } evolvotron/libevolvotron/dialog_about.cpp0000644000175100017510000000612512100750252020674 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class DialogAbout. */ #include "libevolvotron_precompiled.h" #include "dialog_about.h" #include "license.h" DialogAbout::DialogAbout(QWidget* parent,int n_threads,bool separate_farm_for_enlargements) :QDialog(parent) { assert(parent!=0); setWindowTitle("About evolvotron"); setMinimumSize(480,360); setSizeGripEnabled(true); setLayout(new QVBoxLayout); QTabWidget*const tabs=new QTabWidget; layout()->addWidget(tabs); QWidget*const tab_info=new QWidget; tab_info->setLayout(new QVBoxLayout); tabs->addTab(tab_info,"Info"); QWidget*const tab_license=new QWidget; tab_license->setLayout(new QVBoxLayout); tabs->addTab(tab_license,"License"); std::ostringstream about_string; about_string << "Evolvotron " << stringify(EVOLVOTRON_BUILD) << "\n\n" << "Using " << (separate_farm_for_enlargements ? "2 pools" : "1 pool") << " of " << n_threads << " compute thread" << (n_threads>1 ? "s" : "") << "\n\n" << "Author: timday@timday.com\n\n" << "Home page: http://evolvotron.sourceforge.net\n" << "Project page: http://sourceforge.net/projects/evolvotron\n"; QLabel*const label=new QLabel(about_string.str().c_str()); tab_info->layout()->addWidget(label); label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter|label->alignment()); QTextEdit*const license=new QTextEdit; tab_license->layout()->addWidget(license); license->setReadOnly(true); license->setPlainText((std::string("License:\n")+std::string(license_string)).c_str()); QPushButton* ok=new QPushButton("OK"); layout()->addWidget(ok); ok->setDefault(true); connect ( ok,SIGNAL(clicked()), this,SLOT(hide()) ); } DialogAbout::~DialogAbout() {} evolvotron/libevolvotron/mutatable_image_computer_farm.cpp0000644000175100017510000001627112100750252024311 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutatableImageComputerFarm. */ #include "libevolvotron_precompiled.h" #include "mutatable_image_computer_farm.h" #include "mutatable_image_computer.h" /*! Creates the specified number of threads and store pointers to them. */ MutatableImageComputerFarm::MutatableImageComputerFarm(uint n_threads,int niceness) { _done_position=_done.end(); for (uint i=0;i::iterator it=_computers.begin();it!=_computers.end();it++) (*it).kill(); _wait_condition.wakeAll(); _computers.clear(); // Clear all the tasks in queues { QMutexLocker lock(&_mutex); _todo.clear(); _done.clear(); } std::clog << "...completed compute farm shut down\n"; } //! Predicate function to test whether a task has been aborted static bool predicate_aborted(const boost::shared_ptr t) { return t->aborted(); } void MutatableImageComputerFarm::fasttrack_aborted() { QMutexLocker lock(&_mutex); // \todo: Inefficient starting search again each time. Some problem with erase otherwise though, but might have been task abort mem leak. TodoQueue::iterator it; while ( ( it=std::find_if(_todo.begin(),_todo.end(),predicate_aborted) ) != _todo.end() ) { _done[(*it)->display()].insert(*it); _todo.erase(it); } } void MutatableImageComputerFarm::push_todo(const boost::shared_ptr& task) { { QMutexLocker lock(&_mutex); // We could be in a situation where there are tasks with lower priority which should be defered in favour of this one. // Currently we simply defer everything with a lower priority and let the queue sort them out. //! \todo: It would be better to just defer the lowest priority task if there's any less than the queued task. bool any_deferred=false; for (boost::ptr_vector::iterator it=_computers.begin();it!=_computers.end();it++) { if ((*it).defer_if_less_important_than(task->priority())) { any_deferred=true; } } _todo.insert(task); } // If there any threads waiting, we should wake one up. _wait_condition.wakeOne(); } const boost::shared_ptr MutatableImageComputerFarm::pop_todo(MutatableImageComputer& requester) { _mutex.lock(); boost::shared_ptr ret; while (!ret) { TodoQueue::iterator it=_todo.begin(); if (it!=_todo.end()) { ret=(*it); _todo.erase(it); } else { std::clog << "Thread waiting\n"; _wait_condition.wait(&_mutex); std::clog << "Thread woken\n"; if (requester.killed()) break; } } _mutex.unlock(); return ret; } void MutatableImageComputerFarm::push_done(const boost::shared_ptr& task) { QMutexLocker lock(&_mutex); _done[task->display()].insert(task); } const boost::shared_ptr MutatableImageComputerFarm::pop_done() { QMutexLocker lock(&_mutex); boost::shared_ptr ret; if (_done_position==_done.end()) { _done_position=_done.begin(); } if (_done_position!=_done.end()) { DoneQueue& q=(*_done_position).second; DoneQueue::iterator it=q.begin(); if (it!=q.end()) { ret=(*it); q.erase(it); } if (q.empty()) { DoneQueueByDisplay::iterator advanced_done_position=_done_position; advanced_done_position++; _done.erase(_done_position); _done_position=advanced_done_position; } else { _done_position++; } } return ret; } void MutatableImageComputerFarm::abort_all() { QMutexLocker lock(&_mutex); for (TodoQueue::iterator it=_todo.begin();it!=_todo.end();it++) { (*it)->abort(); } _todo.clear(); for (boost::ptr_vector::iterator it=_computers.begin();it!=_computers.end();it++) { (*it).abort(); } for (DoneQueueByDisplay::iterator it0=_done.begin();it0!=_done.end();it0++) { DoneQueue& q=(*it0).second; for (DoneQueue::iterator it1=q.begin();it1!=q.end();it1++) { (*it1)->abort(); } } _done.clear(); } void MutatableImageComputerFarm::abort_for(const MutatableImageDisplay* disp) { QMutexLocker lock(&_mutex); for (TodoQueue::iterator it=_todo.begin();it!=_todo.end();it++) { if ((*it)->display()==disp) { (*it)->abort(); _todo.erase(it); } } for (boost::ptr_vector::iterator it=_computers.begin();it!=_computers.end();it++) { (*it).abort_for(disp); } DoneQueueByDisplay::iterator it0=_done.find(disp); if (it0!=_done.end()) { DoneQueue& q=(*it0).second; //! \todo It would be pretty odd if display didn't match the queue bin: change to assert for (DoneQueue::iterator it1=q.begin();it1!=q.end();it1++) { if ((*it1)->display()==disp) { (*it1)->abort(); q.erase(it1); } } } } uint MutatableImageComputerFarm::tasks() const { uint ret=0; for (boost::ptr_vector::const_iterator it=_computers.begin();it!=_computers.end();it++) { if ((*it).active()) { ret++; } } QMutexLocker lock(&_mutex); ret+=_todo.size(); for (DoneQueueByDisplay::const_iterator it=_done.begin();it!=_done.end();it++) ret+=(*it).second.size(); return ret; } evolvotron/libevolvotron/transform_factory.cpp0000644000175100017510000000611712100750252022006 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation for class TransformFactory. */ #include "libevolvotron_precompiled.h" #include "transform_factory.h" #include "random.h" #include "transform.h" const Transform TransformFactoryRandomWarpXY::operator()(Random01& r01) const { // Gives a scale between 0.5 and 2, average 1. const real r=pow(2.0,2.0*r01()-1.0); // Random rotation const real a=(2.0*M_PI)*r01(); const XYZ basis_x( r*cos(a), r*sin(a),0.0); const XYZ basis_y(-r*sin(a), r*cos(a),0.0); const XYZ basis_z(0.0,0.0,1.0); // Random translation const real tx=2.0*r01()-1.0; const real ty=2.0*r01()-1.0; const XYZ translate(tx,ty,0.0); return Transform(translate,basis_x,basis_y,basis_z); } const Transform TransformFactoryRandomScaleXY::operator()(Random01& rng) const { const XYZ translate(0.0,0.0,0.0); const real p=rng(); const real s=pow(2.0,_lopow2+p*(_hipow2-_lopow2)); const XYZ basis_x( s,0.0,0.0); const XYZ basis_y(0.0, s,0.0); const XYZ basis_z(0.0,0.0,1.0); return Transform(translate,basis_x,basis_y,basis_z); } const Transform TransformFactoryRandomRotateZ::operator()(Random01& r01) const { // Random rotation const real a=(2.0*M_PI)*r01(); const real ca=cos(a); const real sa=sin(a); const XYZ basis_x( ca, sa,0.0); const XYZ basis_y( -sa, ca,0.0); const XYZ basis_z(0.0,0.0,1.0); const XYZ translate(0.0,0.0,0.0); return Transform(translate,basis_x,basis_y,basis_z); } const Transform TransformFactoryRandomTranslateXYZ::operator()(Random01& r01) const { const XYZ translate(_origin+RandomXYZInBox(r01,_range)); const XYZ basis_x(1.0,0.0,0.0); const XYZ basis_y(0.0,1.0,0.0); const XYZ basis_z(1.0,0.0,1.0); return Transform(translate,basis_x,basis_y,basis_z); } evolvotron/libevolvotron/license.cpp0000644000175100017510000004757412100750277017711 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief License string boilerplate. */ #include "libevolvotron_precompiled.h" #include "license.h" const char*const license_string= "This program 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 2 of the License, or (at your option) any later version.\n" "\n" "This program 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.\n" "\n" "GNU GENERAL PUBLIC LICENSE\n" "Version 2, June 1991\n" "\n" " Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" " Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\n" "\n" "Preamble\n" "\n" " The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.\n" " When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.\n" "\n" " To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.\n" "\n" " For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\n" "\n" " We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy,distribute and/or modify the software.\n" "\n" " Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.\n" "\n" " Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.\n" "\n" " The precise terms and conditions for copying, distribution and\n" "modification follow.\n" "\n" "GNU GENERAL PUBLIC LICENSE\n" "TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n" "\n" " 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The \"Program\", below, refers to any such program or work, and a \"work based on the Program\" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term \"modification\".) Each licensee is addressed as \"you\".\n" "\n" "Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.\n" "\n" " 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.\n" "\n" "You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.\n" " 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:\n" "\n" " a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.\n" "\n" " b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.\n" "\n" " c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)\n" "\n" "These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.\n" "\n" "Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.\n" "\n" "In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.\n" "\n" " 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:\n" "\n" " a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\n" "\n" " b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\n" "\n" " c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)\n" "\n" "The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.\n" "\n" "If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.\n" "\n" " 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.\n" "\n" " 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.\n" "\n" " 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.\n" "\n" " 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.\n" "\n" "If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.\n" "\n" "It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.\n" "\n" "This section is intended to make thoroughly clear what is believed tobe a consequence of the rest of this License.\n" "\n" " 8. If the distribution and/or use of the Program is restricted incertain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.\n" "\n" " 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\n" "\n" "Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and \"any later version\", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.\n" "\n" " 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.\n" "\n" "NO WARRANTY\n" "\n" " 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSEDOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n" "\n" " 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n" "\n" "END OF TERMS AND CONDITIONS\n" "\n" "How to Apply These Terms to Your New Programs\n" "\n" " If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.\n" "\n" " To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the \"copyright\" line and a pointer to where the full notice is found.\n" "\n" " \n" " Copyright (C) \n" "\n" " This program 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 2 of the License, or (at your option) any later version.\n" "\n" " This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n" "\n" " You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" "\n" "Also add information on how to contact you by electronic and paper mail.\n" "\n" "If the program is interactive, make it output a short notice like this when it starts in an interactive mode:\n" "\n" " Gnomovision version 69, Copyright (C) year name of author\n" " Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n" " This is free software, and you are welcome to redistribute it\n" " under certain conditions; type `show c' for details.\n" "\n" "The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.\n" "\n" "You should also get your employer (if you work as a programmer) or your school, if any, to sign a \"copyright disclaimer\" for the program, if necessary. Here is a sample; alter the names:\n" "\n" " Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n" " `Gnomovision' (which makes passes at compilers) written by James Hacker.\n" "\n" " , 1 April 1989\n" " Ty Coon, President of Vice\n" "\n" "This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.\n" ; evolvotron/libevolvotron/mutatable_image.cpp0000644000175100017510000003563512100750252021373 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutatableImage. */ #include "libevolvotron_precompiled.h" #include "mutatable_image.h" #include "function_node_info.h" #include "function_top.h" #include "mutatable_image_display_big.h" #include "random.h" #include "transform.h" unsigned long long MutatableImage::_count=0; MutatableImage::MutatableImage(std::auto_ptr& r,bool sinz,bool sm,bool lock) : #ifndef NDEBUG InstanceCounted(typeid(this).name(),false), #endif _top(r) ,_sinusoidal_z(sinz) ,_spheremap(sm) ,_locked(lock) ,_serial(_count++) { assert(_top.get()!=0); } MutatableImage::MutatableImage(const MutationParameters& parameters,bool exciting,bool sinz,bool sm) : #ifndef NDEBUG InstanceCounted(typeid(this).name(),false), #endif _sinusoidal_z(sinz) ,_spheremap(sm) ,_locked(false) ,_serial(_count++) { std::vector pv; FunctionNode::stubparams(pv,parameters,12); boost::ptr_vector av; av.push_back(FunctionNode::stub(parameters,exciting).release()); _top=std::auto_ptr(new FunctionTop(pv,av,0)); //! \todo _sinusoidal_z should be obtained from AnimationParameters when it exists } MutatableImage::~MutatableImage() {} //! Accessor. const FunctionTop& MutatableImage::top() const { return *_top; } boost::shared_ptr MutatableImage::deepclone() const { return deepclone(false); } boost::shared_ptr MutatableImage::deepclone(bool lock) const { std::auto_ptr root(top().typed_deepclone()); return boost::shared_ptr(new MutatableImage(root,sinusoidal_z(),spheremap(),lock)); } bool MutatableImage::is_constant() const { return top().is_constant(); } bool MutatableImage::ok() const { return top().ok(); } const XYZ MutatableImage::sampling_coordinate(real x,real y,uint z,uint sx,uint sy,uint sz) const { if (spheremap()) { const real longitude=-M_PI+2.0*M_PI*x/sx; const real latitude=0.5*M_PI-M_PI*y/sy; const real r=( sinusoidal_z() ? 0.5+cos(M_PI*z/sz) : 0.5+(z+0.5)/sz ); return XYZ ( r*sin(longitude)*cos(latitude), r*cos(longitude)*cos(latitude), r*sin(latitude) ); } else { return XYZ ( -1.0+2.0*x/sx, 1.0-2.0*y/sy, ( sinusoidal_z() ? cos(M_PI*(z+0.5)/sz) : -1.0+2.0*(z+0.5)/sz ) ); } } boost::shared_ptr MutatableImage::mutated(const MutationParameters& p) const { std::auto_ptr c(top().typed_deepclone()); c->mutate(p); return boost::shared_ptr(new MutatableImage(c,sinusoidal_z(),spheremap(),false)); } boost::shared_ptr MutatableImage::simplified() const { std::auto_ptr c(top().typed_deepclone()); c->simplify_constants(); return boost::shared_ptr(new MutatableImage(c,sinusoidal_z(),spheremap(),false)); } const XYZ MutatableImage::get_rgb(const XYZ& p) const { // Actually calculate a pixel value from the image. // negexp distribution on colour-space parameters probably means the nominal range is something like -4.0 to 4.0 const XYZ pv(top()(p)); // Scale a nominal -2.0 to 2.0 range to 0-255 return 127.5*(0.5*pv+XYZ(1.0,1.0,1.0)); } const XYZ MutatableImage::get_rgb(uint x,uint y,uint f,uint width,uint height,uint frames,Random01* r01,uint multisample) const { XYZ accumulated_colour(0.0,0.0,0.0); for (uint sy=0;sy\n" << "\n"; top().save_function(out,1); out << "\n"; return out; } //! LoadHandler class overrides default handler's null methods. /*! Expect to see an followed by nested ... wrapping ..., ...,

...

and more declarations. */ class LoadHandler : public QXmlDefaultHandler { protected: std::string _report; std::auto_ptr& _root; bool* _ret_sinusoidal_z; bool* _ret_spheremap; //! Stack just used to track our progress through the nested ... declarations. /*! Ownership is entirely under _root and the pointr-container in FunctionNodeInfo. */ std::stack _stack; bool _expect_top_level_element; bool _expect_characters; bool _expect_characters_type; bool _expect_characters_iterations; bool _expect_characters_parameter; public: LoadHandler(std::auto_ptr& root,bool* sinz,bool* smap) :_root(root) ,_ret_sinusoidal_z(sinz) ,_ret_spheremap(smap) ,_expect_top_level_element(true) ,_expect_characters(false) ,_expect_characters_type(false) ,_expect_characters_iterations(false) ,_expect_characters_parameter(false) { _root.reset(); } bool startDocument() { std::clog << "Reading document...\n"; return true; } bool endDocument() { std::clog << "...completed document\n"; if (_root.get()==0) { _report+="Error: No root function node found\n"; return false; } return true; } //! Called for start elements. /*! Don't know anything about namespaces - parameters ignored. */ bool startElement(const QString&,const QString& localName,const QString&,const QXmlAttributes& atts) { const std::string element(localName.toLocal8Bit().data()); if (_expect_characters) { _report+="Error: Expected character data but got start element \""+element+"\"\n"; return false; } if (_expect_top_level_element) { if (element=="evolvotron-image-function") { _expect_top_level_element=false; int idx; if ((idx=atts.index("version"))==-1) { _report+="Warning: File does not include evolvotron version\n"; } else { const QString version=atts.value(idx); if (version!=QString(stringify(EVOLVOTRON_VERSION))) { QString tmp; tmp="Warning: File saved from a different evolvotron version: "+version+"\n(This is version "+QString(stringify(EVOLVOTRON_VERSION))+")\n"; _report+=tmp.toLocal8Bit().data(); } } if ((idx=atts.index("zsweep"))==-1) { _report+="Warning: zsweep attribute not found\nDefaulting to sinusoidal\n"; *_ret_sinusoidal_z=true; } else { const QString zsweep=atts.value(idx); if (zsweep==QString("sinusoidal")) *_ret_sinusoidal_z=true; else if (zsweep==QString("linear")) *_ret_sinusoidal_z=false; else { QString tmp; tmp="Error: zsweep attribute expected \"sinusoidal\" or \"linear\", but got \""+zsweep+"\"\n"; _report+=tmp.toLocal8Bit().data(); return false; } } if ((idx=atts.index("projection"))==-1) { _report+="Warning: projection attribute not found\nDefaulting to planar\n"; *_ret_spheremap=false; } else { const QString projection=atts.value(idx); if (projection==QString("spheremap")) *_ret_spheremap=true; else if (projection==QString("planar")) *_ret_spheremap=false; else { QString tmp; tmp="Error: projection attribute expected \"spheremap\" or \"planar\", but got \""+projection+"\"\n"; _report+=tmp.toLocal8Bit().data(); return false; } } } else { _report+="Error: Expected but got \""+element+"\"\n"; return false; } } else { if (element=="f") { std::auto_ptr f(new FunctionNodeInfo()); if (_stack.empty()) { if (_root.get()==0) { _stack.push(f.get()); _root=f; } else { _report+="Error: Multiple top level elements encountered\n"; return false; } } else { FunctionNodeInfo*const it=f.get(); _stack.top()->args().push_back(f.release()); _stack.push(it); } } else if (element=="type") { _expect_characters=true; _expect_characters_type=true; } else if (element=="i") { _expect_characters=true; _expect_characters_iterations=true; } else if (element=="p") { _expect_characters=true; _expect_characters_parameter=true; } else { _report+="Error: Expected , , or

but got \""+element+"\"\n"; return false; } } return true; } //! We don't need to check this matches startElement /*! Don't know anything about namespaces - parameter ignored. */ bool endElement(const QString&, const QString& localName, const QString&) { const std::string element(localName.toLocal8Bit().data()); if (_expect_characters) { _report+="Error: Expected character data but got end element \""+element+"\"\n"; return false; } if (element=="f") { _stack.pop(); } return true; } bool characters(const QString& s) { QString stripped=s.simplified(); if (stripped.isEmpty()) { // Just keep going and hope something good turns up (maybe next line ?) return true; } else { if (!_expect_characters) { QString tmp; tmp = "Error: Unexpected character data : \""+s+"\"\n"; _report += tmp.toLocal8Bit().data(); return false; } } //std::clog << "Non-blank expected character data\n"; if (_expect_characters_type) { _stack.top()->type(s.toLocal8Bit().data()); _expect_characters_type=false; } else if (_expect_characters_iterations) { bool ok; _stack.top()->iterations(s.toUInt(&ok)); _expect_characters_iterations=false; if (!ok) { QString tmp; tmp = "Error: Couldn't parse \""+s+"\" as an integer\n"; _report += tmp.toLocal8Bit().data(); return false; } } else if (_expect_characters_parameter) { bool ok; _stack.top()->params().push_back(s.toFloat(&ok)); _expect_characters_parameter=false; if (!ok) { QString tmp; tmp = "Error: Couldn't parse \""+s+"\" as a real\n"; _report+=tmp.toLocal8Bit().data(); return false; } } _expect_characters=false; return true; } QString errorString() { return QString(_report.c_str()); } }; /*! If NULL is returned, then the import failed: error message in report. If an image is returned then report contains warning messages (probably version mismatch). */ boost::shared_ptr MutatableImage::load_function(const FunctionRegistry& function_registry,std::istream& in,std::string& report) { // Don't want to faff with Qt's file classes so just read everything into a string. std::string in_data; char c; while (in.get(c)) in_data+=c; QXmlInputSource xml_source; xml_source.setData(QString(in_data.c_str())); // The LoadHandler will set this to point at the root node. std::auto_ptr info; bool sinusoidal_z; bool spheremap; LoadHandler load_handler(info,&sinusoidal_z,&spheremap); QXmlSimpleReader xml_reader; xml_reader.setContentHandler(&load_handler); const bool ok=xml_reader.parse(&xml_source,false); if (ok) { // Might be a warning message in there. report=load_handler.errorString().toLocal8Bit().data(); assert(info.get()); std::auto_ptr root(FunctionNode::create(function_registry,*info,report)); info.reset(); if (root.get()) { if (!root->is_a_FunctionTop()) { // Build a FunctionTop wrapper for compataibility with old .xml files boost::ptr_vector a; a.push_back(root.release()); const TransformIdentity ti; std::vector tiv=ti.get_columns(); std::vector p; p.insert(p.end(),tiv.begin(),tiv.end()); p.insert(p.end(),tiv.begin(),tiv.end()); root=std::auto_ptr(new FunctionTop(p,a,0)); } assert(root->is_a_FunctionTop()); std::auto_ptr root_as_top(root.release()->is_a_FunctionTop()); // Interestingly, if is_a_FunctionTop threw, the root would be leaked. return boost::shared_ptr(new MutatableImage(root_as_top,sinusoidal_z,spheremap,false)); } else { return boost::shared_ptr(); } } else { QString tmp; tmp = "Parse error: "+load_handler.errorString()+"\n"; report=tmp.toLocal8Bit().data(); return boost::shared_ptr(); } } evolvotron/libevolvotron/render_parameters.cpp0000644000175100017510000000337412100750252021750 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class MutationParametersQObject. */ #include "libevolvotron_precompiled.h" #include "render_parameters.h" RenderParameters::RenderParameters(bool j,uint m,QObject* parent) :QObject(parent) ,_jittered_samples(j) ,_multisample_grid(clamped(m,1u,4u)) {} RenderParameters::~RenderParameters() {} void RenderParameters::report_change() { emit changed(); } evolvotron/libevolvotron/dialog_mutation_parameters.cpp0000644000175100017510000002710012100750252023641 0ustar timdaytimday/**************************************************************************/ /* Copyright 2012 Tim Day */ /* */ /* This file is part of Evolvotron */ /* */ /* Evolvotron 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. */ /* */ /* Evolvotron 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 Evolvotron. If not, see . */ /**************************************************************************/ /*! \file \brief Implementation of class DialogMutationParameters. */ #include "libevolvotron_precompiled.h" #include "dialog_mutation_parameters.h" DialogMutationParameters::DialogMutationParameters(QMainWindow* parent,MutationParametersQObject* mp) :QDialog(parent) ,_scale(100) ,_parent(parent) ,_mutation_parameters(mp) { assert(_parent!=0); setWindowTitle("Mutation Parameters"); setSizeGripEnabled(true); setLayout(new QVBoxLayout); _tabs=new QTabWidget(); layout()->addWidget(_tabs); _vbox_base_mutation=new QWidget; _vbox_base_mutation->setLayout(new QVBoxLayout); _tabs->addTab(_vbox_base_mutation,"Base"); _grid_buttons=new QWidget; _vbox_base_mutation->layout()->addWidget(_grid_buttons); QGridLayout*const grid_buttons_layout=new QGridLayout(); _grid_buttons->setLayout(grid_buttons_layout); grid_buttons_layout->addWidget(_button_reset=new QPushButton("&Reset",_grid_buttons),0,0); grid_buttons_layout->addWidget(_button_cool=new QPushButton("&Cool",_grid_buttons),0,1); grid_buttons_layout->addWidget(_button_shield=new QPushButton("&Shield",_grid_buttons),0,2); grid_buttons_layout->addWidget(_button_heat=new QPushButton("&Heat",_grid_buttons),0,3); grid_buttons_layout->addWidget(_button_irradiate=new QPushButton("&Irradiate",_grid_buttons),0,4); _button_cool->setToolTip("Decrease size of constant perturbations during mutation."); _button_heat->setToolTip("Increase size of constant perturbations during mutation."); _button_shield->setToolTip("Decrease probability of function tree structural mutations."); _button_irradiate->setToolTip("Increase probability of function tree structural mutations."); connect(_button_reset, SIGNAL(clicked()),this,SLOT(reset())); connect(_button_cool, SIGNAL(clicked()),this,SLOT(cool())); connect(_button_heat, SIGNAL(clicked()),this,SLOT(heat())); connect(_button_shield, SIGNAL(clicked()),this,SLOT(shield())); connect(_button_irradiate,SIGNAL(clicked()),this,SLOT(irradiate())); _vbox_autocool=new QWidget; _vbox_autocool->setLayout(new QVBoxLayout); _tabs->addTab(_vbox_autocool,"Autocool"); _grid_base_mutation=new QWidget; _vbox_base_mutation->layout()->addWidget(_grid_base_mutation); QGridLayout*const grid_base_mutation_layout=new QGridLayout(); _grid_base_mutation->setLayout(grid_base_mutation_layout); grid_base_mutation_layout->addWidget(new QLabel("Perturbation magnitude:"),0,0); grid_base_mutation_layout->addWidget(_spinbox_magnitude=new QSpinBox,0,1); _spinbox_magnitude->setRange(0,_scale); _spinbox_magnitude->setSingleStep(maximum(1,_scale/1000)); _spinbox_magnitude->setSuffix(QString("/%1").arg(_scale)); _spinbox_magnitude->setToolTip("Scale of function parameter perturbations."); grid_base_mutation_layout->addWidget(new QLabel("p(Parameter reset)"),1,0); grid_base_mutation_layout->addWidget(_spinbox_parameter_reset=new QSpinBox,1,1); _spinbox_parameter_reset->setRange(0,_scale); _spinbox_parameter_reset->setSingleStep(maximum(1,_scale/1000)); _spinbox_parameter_reset->setSuffix(QString("/%1").arg(_scale)); _spinbox_parameter_reset->setToolTip("Probability of function parameters being completely reset."); grid_base_mutation_layout->addWidget(new QLabel("p(Glitch)"),2,0); grid_base_mutation_layout->addWidget(_spinbox_glitch=new QSpinBox,2,1); _spinbox_glitch->setRange(0,_scale); _spinbox_glitch->setSingleStep(maximum(1,_scale/1000)); _spinbox_glitch->setSuffix(QString("/%1").arg(_scale)); _spinbox_glitch->setToolTip("Probability of function branch being replaced by new random stub."); grid_base_mutation_layout->addWidget(new QLabel("p(Shuffle)"),3,0); grid_base_mutation_layout->addWidget(_spinbox_shuffle=new QSpinBox,3,1); _spinbox_shuffle->setRange(0,_scale); _spinbox_shuffle->setSingleStep(maximum(1,_scale/1000)); _spinbox_shuffle->setSuffix(QString("/%1").arg(_scale)); _spinbox_shuffle->setToolTip("Probability of function branches being reordered."); grid_base_mutation_layout->addWidget(new QLabel("p(Insert)"),4,0); grid_base_mutation_layout->addWidget(_spinbox_insert=new QSpinBox,4,1); _spinbox_insert->setRange(0,_scale); _spinbox_insert->setSingleStep(maximum(1,_scale/1000)); _spinbox_insert->setSuffix(QString("/%1").arg(_scale)); _spinbox_insert->setToolTip("Probability of function branch having random stub inserted."); grid_base_mutation_layout->addWidget(new QLabel("p(Substitute)"),5,0); grid_base_mutation_layout->addWidget(_spinbox_substitute=new QSpinBox,5,1); _spinbox_substitute->setRange(0,_scale); _spinbox_substitute->setSingleStep(maximum(1,_scale/1000)); _spinbox_substitute->setSuffix(QString("/%1").arg(_scale)); _spinbox_substitute->setToolTip("Probability of function node's type being changed."); _grid_autocool=new QWidget; _vbox_autocool->layout()->addWidget(_grid_autocool); QGridLayout*const grid_autocool_layout=new QGridLayout(); _grid_autocool->setLayout(grid_autocool_layout); grid_autocool_layout->addWidget(_checkbox_autocool_enable=new QCheckBox("Enable autocool"),0,1); _checkbox_autocool_enable->setToolTip("Autocooling reduces the strength and probablility of mutations with increasing numbers of generations."); grid_autocool_layout->addWidget(new QLabel("Half-life"),1,0); grid_autocool_layout->addWidget(_spinbox_autocool_halflife=new QSpinBox,1,1); _spinbox_autocool_halflife->setRange(1,1000); _spinbox_autocool_halflife->setSingleStep(1); _spinbox_autocool_halflife->setToolTip("Number of generations needed to halve mutation influence when autocooling."); grid_autocool_layout->addWidget(_label_autocool_generations=new QLabel(""),2,0); grid_autocool_layout->addWidget(_button_autocool_reheat=new QPushButton("Reheat"),2,1); connect(_button_autocool_reheat,SIGNAL(clicked()),this,SLOT(reheat())); setup_from_mutation_parameters(); // Do this AFTER setup connect(_spinbox_magnitude,SIGNAL(valueChanged(int)),this,SLOT(changed_magnitude(int))); connect(_spinbox_parameter_reset,SIGNAL(valueChanged(int)),this,SLOT(changed_parameter_reset(int))); connect(_spinbox_glitch,SIGNAL(valueChanged(int)),this,SLOT(changed_glitch(int))); connect(_spinbox_shuffle,SIGNAL(valueChanged(int)),this,SLOT(changed_shuffle(int))); connect(_spinbox_insert,SIGNAL(valueChanged(int)),this,SLOT(changed_insert(int))); connect(_spinbox_substitute,SIGNAL(valueChanged(int)),this,SLOT(changed_substitute(int))); connect(_checkbox_autocool_enable,SIGNAL(stateChanged(int)),this,SLOT(changed_autocool_enable(int))); connect(_spinbox_autocool_halflife,SIGNAL(valueChanged(int)),this,SLOT(changed_autocool_halflife(int))); _ok=new QPushButton("OK"); layout()->addWidget(_ok); _ok->setDefault(true); connect( _ok,SIGNAL(clicked()), this,SLOT(hide()) ); connect( _mutation_parameters,SIGNAL(changed()), this,SLOT(mutation_parameters_changed()) ); } DialogMutationParameters::~DialogMutationParameters() {} void DialogMutationParameters::setup_from_mutation_parameters() { _spinbox_magnitude ->setValue(static_cast(0.5+_scale*_mutation_parameters->base_magnitude_parameter_variation())); _spinbox_parameter_reset ->setValue(static_cast(0.5+_scale*_mutation_parameters->base_probability_parameter_reset())); _spinbox_glitch ->setValue(static_cast(0.5+_scale*_mutation_parameters->base_probability_glitch())); _spinbox_shuffle ->setValue(static_cast(0.5+_scale*_mutation_parameters->base_probability_shuffle())); _spinbox_insert ->setValue(static_cast(0.5+_scale*_mutation_parameters->base_probability_insert())); _spinbox_substitute ->setValue(static_cast(0.5+_scale*_mutation_parameters->base_probability_substitute())); _checkbox_autocool_enable->setChecked(_mutation_parameters->autocool_enable()); _spinbox_autocool_halflife->setValue(_mutation_parameters->autocool_halflife()); _label_autocool_generations->setText(QString("Generations: ")+QString::number(_mutation_parameters->autocool_generations())); // Grey-out any irrelevant settings _spinbox_autocool_halflife->setEnabled(_mutation_parameters->autocool_enable()); _button_autocool_reheat->setEnabled(_mutation_parameters->autocool_enable() && _mutation_parameters->autocool_generations()>0); } void DialogMutationParameters::reset() { _mutation_parameters->reset(); setup_from_mutation_parameters(); } void DialogMutationParameters::heat() { _spinbox_magnitude->stepUp(); } void DialogMutationParameters::cool() { _spinbox_magnitude->stepDown(); } void DialogMutationParameters::irradiate() { _spinbox_parameter_reset->stepUp(); _spinbox_glitch->stepUp(); _spinbox_shuffle->stepUp(); _spinbox_insert->stepUp(); _spinbox_substitute->stepUp(); } void DialogMutationParameters::shield() { _spinbox_parameter_reset->stepDown(); _spinbox_glitch->stepDown(); _spinbox_shuffle->stepDown(); _spinbox_insert->stepDown(); _spinbox_substitute->stepDown(); } void DialogMutationParameters::reheat() { _mutation_parameters->autocool_generations(0); } void DialogMutationParameters::changed_autocool_enable(int buttonstate) { if (buttonstate==Qt::Checked) _mutation_parameters->autocool_enable(true); else if (buttonstate==Qt::Unchecked) _mutation_parameters->autocool_enable(false); } void DialogMutationParameters::changed_magnitude(int v) { _mutation_parameters->base_magnitude_parameter_variation(v/static_cast(_scale)); } void DialogMutationParameters::changed_parameter_reset(int v) { _mutation_parameters->base_probability_parameter_reset(v/static_cast(_scale)); } void DialogMutationParameters::changed_glitch(int v) { _mutation_parameters->base_probability_glitch(v/static_cast(_scale)); } void DialogMutationParameters::changed_shuffle(int v) { _mutation_parameters->base_probability_shuffle(v/static_cast(_scale)); } void DialogMutationParameters::changed_insert(int v) { _mutation_parameters->base_probability_insert(v/static_cast(_scale)); } void DialogMutationParameters::changed_substitute(int v) { _mutation_parameters->base_probability_substitute(v/static_cast(_scale)); } void DialogMutationParameters::changed_autocool_halflife(int v) { _mutation_parameters->autocool_halflife(v); } void DialogMutationParameters::mutation_parameters_changed() { setup_from_mutation_parameters(); } evolvotron/main.pro0000644000175100017510000000015011221142700014265 0ustar timdaytimdayTEMPLATE = subdirs SUBDIRS = libfunction libevolvotron evolvotron evolvotron_render evolvotron_mutate evolvotron/evolvotron_render/evolvotron_render.pro0000644000175100017510000000061411267025132022707 0ustar timdaytimdayTEMPLATE = app include (../common.pro) PRECOMPILED_HEADER = evolvotron_render_precompiled.h SOURCES += $$system(ls *.cpp) DEPENDPATH += ../libevolvotron ../libfunction INCLUDEPATH += ../libevolvotron ../libfunction TARGETDEPS += ../libevolvotron/libevolvotron.a ../libfunction/libfunction.a LIBS += ../libevolvotron/libevolvotron.a ../libfunction/libfunction.a -lboost_program_options evolvotron/evolvotron/evolvotron.pro0000644000175100017510000000060711267025132020013 0ustar timdaytimdayTEMPLATE = app include (../common.pro) PRECOMPILED_HEADER = evolvotron_precompiled.h SOURCES += $$system(ls *.cpp) DEPENDPATH += ../libevolvotron ../libfunction INCLUDEPATH += ../libevolvotron ../libfunction TARGETDEPS += ../libevolvotron/libevolvotron.a ../libfunction/libfunction.a LIBS += ../libevolvotron/libevolvotron.a ../libfunction/libfunction.a -lboost_program_options evolvotron/experiment/svg/svg.pro0000644000175100017510000000106211235643414017137 0ustar timdaytimdayTEMPLATE = app CONFIG+= qt opengl stl exceptions release # release debug QT += opengl svg SOURCES += svg.cpp ####################################### # Disable assertions in release version QMAKE_CXXFLAGS_RELEASE += -DNDEBUG QMAKE_CFLAGS_RELEASE += -DNDEBUG ###################################### # Other stuff: # Disable implicit cast from QString to char* QMAKE_CXXFLAGS_RELEASE += -DQT_NO_ASCII_CAST QMAKE_CXXFLAGS_DEBUG += -DQT_NO_ASCII_CAST ###################################### # Hide those crufty moc_ files away MOC_DIR = moc OBJECTS_DIR = obj evolvotron/evolvotron_mutate/evolvotron_mutate.pro0000644000175100017510000000061411267025131022746 0ustar timdaytimdayTEMPLATE = app include (../common.pro) PRECOMPILED_HEADER = evolvotron_mutate_precompiled.h SOURCES += $$system(ls *.cpp) DEPENDPATH += ../libevolvotron ../libfunction INCLUDEPATH += ../libevolvotron ../libfunction TARGETDEPS += ../libevolvotron/libevolvotron.a ../libfunction/libfunction.a LIBS += ../libevolvotron/libevolvotron.a ../libfunction/libfunction.a -lboost_program_options evolvotron/common.pro0000644000175100017510000000521011267025132014644 0ustar timdaytimday# Shared definitions included by the other .pro files # qmake should NOT be executed on this file directly # append debug or release CONFIG+= qt thread stl precompile_header exceptions release #release #debug QT += xml ####################################### # Control platform specific code # (the Qt platform scopes don't seem that useful; might be easier to just add DEFINES+=... explicitly unix { DEFINES+=PLATFORM_LINUX # of course PLATFORM_BSD is more appropriate to some unices } macx { # NB This doesn't actually seem to be selected on Fink builds # (presumably it applies to Quartz builds instead) # Fink does seem to have a useful __DARWIN_X11__ define though, # which is used to set PLATFORM_BSD in libevolvotron/platform_specific.cpp DEFINES+=PLATFORM_BSD } win32 { # You might want to add some appropriate code to libevolvotron/platform_specific.cpp # and set a #define here to select it } ####################################### # Version numbering. VERSION_NUMBER should have been set on the qmake command line (see .configure script) QMAKE_CXXFLAGS_RELEASE += '-DEVOLVOTRON_VERSION="$$VERSION_NUMBER"' QMAKE_CXXFLAGS_DEBUG += '-DEVOLVOTRON_VERSION="$$VERSION_NUMBER"' QMAKE_CXXFLAGS_RELEASE += '-DEVOLVOTRON_BUILD="$$VERSION_NUMBER (Build options: $$BUILD_INFO Release)"' QMAKE_CXXFLAGS_DEBUG += '-DEVOLVOTRON_BUILD="$$VERSION_NUMBER (Build options: $$BUILD_INFO Debug)"' # qmake's library code can use this too (but only for shared libraries which we don't use) VERSION=$$VERSION_NUMBER ####################################### # Disable assertions in release version QMAKE_CXXFLAGS_RELEASE += -DNDEBUG QMAKE_CFLAGS_RELEASE += -DNDEBUG ###################################### # Other stuff: # Disable implicit cast from QString to/from char* - we should be using .local8Bit and ::fromLocal8Bit # NB We don't use the corresponding -DQT_NO_CAST_ASCII because it breaks QString("...") which is used all over the place # This probably wouldn't be usable until all the strings were moved out of the app - see Qt I18N docs. # Also add gcc threading option (not entirely clear whether this is needed but it doesn't seem to hurt) # Used to use -pthread -DBOOST_SP_USE_PTHREADS as a workround for debian bug 485434 (maybe only needed on sparc?) # but it seemed to cause problems with app not quitting once boost::program_options started being used. QMAKE_CXXFLAGS_RELEASE += -DQT_NO_ASCII_CAST QMAKE_CXXFLAGS_DEBUG += -DQT_NO_ASCII_CAST ###################################### # Hide those crufty moc_ files away MOC_DIR = moc ################## # OPTION: Enable these options for profiling # #QMAKE_LFLAGS_RELEASE += -pg #QMAKE_CXXFLAGS_RELEASE += -pg evolvotron/libfunction/libfunction.pro0000644000175100017510000000100011267025132020175 0ustar timdaytimdayTEMPLATE = lib TARGET = function # Have to override this or we get "liblibfunction" include (../common.pro) CONFIG += staticlib PRECOMPILED_HEADER = libfunction_precompiled.h HEADERS += $$system(ls *.h) SOURCES += $$system(ls *.cpp) ######################### # Target to build assembler listings for specific files of interest # asm.target = asm asm.commands = $(CXX) -S $(CXXFLAGS) $(INCPATH) $^ asm.depends = functions_friezegroup_jump.cpp functions_friezegroup_hop.cpp QMAKE_EXTRA_UNIX_TARGETS += asm evolvotron/libevolvotron/libevolvotron.pro0000644000175100017510000000046111267025131021166 0ustar timdaytimdayTEMPLATE = lib TARGET = evolvotron # Have to override this or we get "liblibevolvotron" include (../common.pro) CONFIG += staticlib PRECOMPILED_HEADER = libevolvotron_precompiled.h INCLUDEPATH += ../libfunction DEPENDPATH += ../libfunction HEADERS += $$system(ls *.h) SOURCES += $$system(ls *.cpp) evolvotron/man/man1/evolvotron.10000644000175100017510000001277012013776726016565 0ustar timdaytimday.TH EVOLVOTRON 1 "16 Oct 2009" "www.timday.com" "Evolvotron" .SH NAME evolvotron \- Creates generative art by an interactive evolutionary process. .SH SYNOPSIS evolvotron [Qt options] [options] .SH DESCRIPTION .B evolvotron is interactive "generative art" software to evolve images/textures/patterns through an iterative process of random mutation and user-selection driven evolution. Basically it displays a grid of random images; you click on one you like and the rest of the grid is refilled with variants of the one you picked. This man page describes only the command line options. A more complete manual fully describing usage via the application's GUI is accessible from the application's "Help" menu once it is running. .SH GENERAL OPTIONS .TP 0.5i .B \-a, \-\-autocool Enable autocooling by default. .TP 0.5i .B \-F, \-\-fullscreen Start in "fullscreen" mode (window manager permitting). [Press "Esc" key to revert to normal windowed mode]. .TP 0.5i .B \-g, \-\-grid .I colsxrows Number of columns in image display grid (defaults to 5x6). .TP 0.5i .B \-h, \-\-help Display a summary of command-line options and exit. .TP 0.5i .B \-j, \-\-jitter Enable sample jittering. .TP 0.5i .B \-m, \-\-multisample .I multisample Enables antialiased rendering. Valid values are 1,2,3,4. This specifies the size of the sub-pixel sampling grid, so 1 provides the default one-sample-per-pixel behaviour, while 4 provides 16 samples per pixel on a 4x4 grid. .TP .B \-M, \-\-menuhide Start with menu and status bars supressed. [Press "Esc" key to display them]. .TP 0.5i .B \-p, \-spheremap Create spheremaps instead of planar textures. NB The middle-mouse adjustments will not behave as expected in this mode. .TP 0.5i .B \-S, \-\-startup .I filename Specify a function file to be loaded on startup. This option can be used multiple times, and any positional arguments will also be interpreted as such. Loaded functions are placed on the grid from left to right, top to bottom; if multiple functions in excess of what is needed to fill the grid cells are provided, the extras will be ignored. If the grid is not fully filled with startup functions, the remaining cells are filled at random normally. Note that resetting the application will reload the specified function files again. Also note that using this option multiple times has the potential to generate a lot of loading error dialogs if e.g the path to all the files is wrong. .TP 0.5i .B \-U, \-\-shuffle Use in conjunction with \-S / \-\-startup options, randomly shuffles the order the specified startup images are displayed in. A fresh shuffle will be also be used when the application is reset. .SH ANIMATION OPTIONS .TP 0.5i .B \-f, \-\-frames .I frames Number of frames to animate (defaults to 1 i.e no animaton) .TP 0.5i .B \-l, \-\-linear Vary z linearly with time rather than sinusoidally over animation period. .TP 0.5i .B \-s, \-\-fps .I framerate Specify rate at which animations are displayed (as an integer number of frames per second). Defaults to 8. .SH POWER-USER / DEBUG OPTIONS .TP 0.5i .B \-D, \-\-debug Debug mode. Currently simply sets function weightings so virtually all function nodes are FunctionNoiseOneChannel. This is really only useful to developers in conjunction with the \-F/\-u options. .TP 0.5i .B \-E, \-\-enlarement-threadpool Use a separate thread pool for computing enlargements. Using this option ensures computation of enlargements continue to make some progress even while the main grid is being actively worked on. However, this will be at the expense of main grid rendering performance. Without this option, enlargements' final high-resolution renderings are invariably lower priority than computation for images in the main grid. See also the \-N option to control the priority of threads in this pool. .TP 0.5i .B \-n, \-\-nice .I niceness Niceness of compute threads relative to the main application thread (defaults to 4). .TP 0.5i .B \-N, \-\-Nice .I niceness Niceness (relative to the main application thread) of compute threads dealing with enlargements (defaults to 8). Only effective in conjunction with a separate enlargement threadool (\-\-E option). .TP 0.5i .I QtOptions The Qt GUI system recognizes an number of additional options (for example, standard X11 things like \-geometry x; consult the Qt documentation for more information). Note that these don't use the Gnu "double minus" option style used for evolvotron options. .TP 0.5i .B \-t, \-\-threads .I threads Number of compute threads in a thread pool (defaults to number of CPUs) .TP 0.5i .B \-u, \-\-unwrapped Use with the \-F option to stop the specified function from being wrapped by a random colouring and spatial transform node. .TP 0.5i .B \-v, \-\-verbose Verbose mode. Probably most useful for getting a list of supported function names for use with the \-\-F option. .TP 0.5i .B \-x, \-\-favourite .I functionname Force a specific function type to be used at the top level of all new image function trees (wrapped by random colour and spatial transforms, unless the \-\-unwrapped option is also specified). This can also be controlled from the "Favourite" dialog. .SH EXAMPLES evolvotron \-F FunctionSpiralLinear evolvotron \-F FunctionKaleidoscope \-u .SH AUTHOR .B evolvotron was written by Tim Day (www.timday.com) and is released under the conditions of the GNU General Public License. For further details see the application's "About" dialog (accessible from the "Help" menu), or the file LICENSE supplied with the source code. .SH SEE ALSO evolvotron_mutate(1), evolvotron_render(1) evolvotron/man/man1/evolvotron_render.10000644000175100017510000000417711267025132020112 0ustar timdaytimday.TH EVOLVOTRON_RENDER 1 "16 Oct 2009" "www.timday.com" "Evolvotron" .SH NAME evolvotron_render \- Render an evolvotron function tree to an image. .SH SYNOPSIS evolvotron_render [options] .I imagefile.[png|ppm] .SH DESCRIPTION .B evolvotron_render reads an evolvotron image function from its standard input and renders it to an image in the file specified (suffix determines type, defaults to ppm if not recognised). Image functions can be obtained by saving them from the evolvotron applicaiton, or using evolvotron_mutate. See the evolvotron manual (accessible from the evolvotron application's Help menu) for more information on image functions. .SH COMMAND-LINE OPTIONS .TP 0.5i .B \-f, \-\-frames .I frames Generates multi-frame animations. .fnnnnnn is inserted into the specified filename (before the filetype suffix, if any). You can use this on functions which weren't evolved in animation mode, but there's no guarantee they have any interesting time/z variation. .TP 0.5i .B \-h, \-\-help Display a summary of command-line options and exit. .TP 0.5i .B \-j, \-\-jitter Enable sample jittering. .TP 0.5i .B \-m, \-\-multisample .I multisample Enables antialiased rendering. This specifies the size of the sub-pixel sampling grid, so 1 provides the default one-sample-per-pixel behaviour, while 4 provides 16 samples per pixel on a 4x4 grid. Unlike the main evolvotron application, there is no upper limit, but of course rendering time increases as the square of this number. .TP 0.5i .B \-o, \-\-output .I imagefile.[ppm|png] This option is an alternative to specifying the output filename as a positional argument. .TP 0.5i .B \-s, \-\-size .I widthxheight Specify resolution of output image. Defaults to 512x512. .TP 0.5i .B \-v, \-\-verbose Verbose mode; useful for monitoring progress of large renders. .SH EXAMPLES evolvotron_mutate \-g | evolvotron_render \-s 1024x1024 function.ppm .SH AUTHOR .B evolvotron_render was written by Tim Day (www.timday.com) and is released under the conditions of the GNU General Public License. See the file LICENSE supplied with the source code for details. .SH SEE ALSO evolvotron(1), evolvotron_mutate(1) evolvotron/man/man1/evolvotron_mutate.10000644000175100017510000000322112013776726020133 0ustar timdaytimday.TH EVOLVOTRON_MUTATE 1 "16 Oct 2009" "www.timday.com" "Evolvotron" .SH NAME evolvotron_mutate \- Render an evolvotron function tree to an image. .SH SYNOPSIS evolvotron_mutate < function_in.xml > function_out.xml evolvotron_mutate \-g > function_out.xml .SH DESCRIPTION .B evolvotron_mutate either mutates an existing image function read from standard input, or (with the \-g option) creates a new image function. In either case the output image function is written to standard output. The mutation parameters and function weightings are the same as used by .B evolvotron in its default reset state. See the evolvotron user manual (accessible from the evolvotron application's Help menu) for more information on image functions. .SH COMMANDLINE OPTIONS .TP 0.5i .B \-g, \-\-genesis Specifies that no function should be read from standard input. The output function is created at random. .TP 0.5i .B \-h, \-\-help Display information on command line arguments and exit. .TP 0.5i .B \-l, \-\-linear Created functions (if they are rendered as animations) will sweep z linearly (rather than sinusoidally). .TP 0.5i .B \-p, \-\-spheremap Created functions will be tagged as spheremaps. .TP 0.5i .B \-v, \-\-verbose Enables some additional logging to standard error. .SH EXAMPLES evolvotron_mutate \-g | tee function0.xml | evolvotron_render function0.ppm evolvtron_mutate < function0.xml > function1.xml .SH AUTHOR .B evolvotron_mutate was written by Tim Day (www.timday.com) and is released under the conditions of the GNU General Public License. See the file LICENSE supplied with the source code for details. .SH SEE ALSO evolvotron(1), evolvotron_render(1)