MRaster examples 21.0.0.0
Image Processing Library
Loading...
Searching...
No Matches
attracting_torus_shadowM.cpp
Go to the documentation of this file.
1// -*- Mode:C++; Coding:us-ascii-unix; fill-column:158 -*-
2/*******************************************************************************************************************************************************.H.S.**/
3/**
4 @file attracting_torus_shadowM.cpp
5 @author Mitch Richling <https://www.mitchr.me>
6 @brief Draw the intersection of the Attracting Torus Attractor with coordinate plains.@EOL
7 @std C++20
8 @see attracting_torus_shadow.cpp
9 @copyright
10 @parblock
11 Copyright (c) 1988-2015, Mitchell Jay Richling <https://www.mitchr.me> All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
14
15 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.
16
17 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software
21 without specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28 DAMAGE.
29 @endparblock
30 @filedetails
31
32 I first came across this strange attractor in Sprott's book "Elegant Automation" where it is the topic of chapter 43 starting on page 311. In that chapter,
33 on page 315, he has an image of the intersection of the attractor with the z=0 plain. This program reproduces that image along with the intersections of
34 the x=0 & y=0 plain. As a bonus we produce projections of the curve as well.
35
36 Reference:
37 Sprott, Julien C. Elegant Automation: Robotic Analysis of Chaotic Systems. New Jersey: World Scientific, 2023.
38
39 Create a gif like this:
40 time convert -delay 1 -loop 0 -dispose previous attracting_torus_shadowM_???.tiff attracting_torus_shadowM.gif
41 time convert attracting_torus_shadowM.gif -resize 50% attracting_torus_shadowM_50.gif
42 time convert attracting_torus_shadowM_50.gif -resize 50% attracting_torus_shadowM_25.gif
43
44 Convert color images to BW:
45 magick attracting_torus_shadowZ0.tiff -alpha off -auto-threshold otsu attracting_torus_shadowZ0_BW.tiff
46 magick attracting_torus_shadowY0.tiff -alpha off -auto-threshold otsu attracting_torus_shadowY0_BW.tiff
47 magick attracting_torus_shadowX0.tiff -alpha off -auto-threshold otsu attracting_torus_shadowX0_BW.tiff
48
49 Build and load images in eshell on Windows:
50 rm -f attracting_torus_shadow*.tiff; make attracting_torus_shadowM && { ./attracting_torus_shadow.exe ; for f in attracting_torus_shadow*.tiff { start $f } }
51*/
52/*******************************************************************************************************************************************************.H.E.**/
53/** @cond exj */
54
55//--------------------------------------------------------------------------------------------------------------------------------------------------------------
56#include "ramCanvas.hpp"
57
58//--------------------------------------------------------------------------------------------------------------------------------------------------------------
59int main(void) {
60 std::chrono::time_point<std::chrono::system_clock> startTime = std::chrono::system_clock::now();
61 const int XSIZ = 7680/4;
62 const int YSIZ = 4320/4;
63
64 const int NUMFRM = 120; /* Number of movie frames */
65
66 const double zLevStart = -4.0;
67 const double zLevEnd = 4.0;
68
69 const double isectDistToGo = 5e7; /* How long should the curve be for Z0 ? */
70
71 const double a = 4.0; /* Equation paramaters */
72 const double b = 0.1; /* Equation paramaters */
73
74 const double x0 = 0.0; /* Initial conditions */
75 const double y0 = 2.0; /* Initial conditions */
76 const double z0 = 1.0; /* Initial conditions */
77
78 const double targetDist = 0.025; /* Size of each step on curve */
79 const int maxNumUpBisect = 5; /* Max times we double tDelta to get > targetDist. */
80 const int maxNumDownBisect = 10; /* Max times we half tDelta to get < targetDist. */
81
82# pragma omp parallel for schedule(static,1)
83 for(int frame=0; frame<NUMFRM; frame++) {
84 std::chrono::time_point<std::chrono::system_clock> frameStartTime = std::chrono::system_clock::now();
85 mjr::ramCanvas3c8b theRamCanvas(XSIZ, YSIZ, -10, 10, -10, 10);
86 double zLev = zLevStart + frame*(zLevEnd-zLevStart)/(NUMFRM-1);
87
88 /* Solve the equations..... */
89 double x = x0;
90 double y = y0;
91 double z = z0;
92 double tDelta = 1.0;
93 double dist = 0.0;
94 double xOld = x;
95 double yOld = y;
96 double zOld = z;
97 double Xdelta, Ydelta, Zdelta, movDist;
98 while (dist < isectDistToGo) {
99 /* Find tDelta that gets us bigger than targetDist */
100 int numUpBisect = 0;
101 do {
102 tDelta += (2 * tDelta);
103 Xdelta = (y) * tDelta;
104 Ydelta = (-x-z*y) * tDelta;
105 Zdelta = (y*y-a+b*z) * tDelta;
106 movDist = sqrt (fabs (Xdelta * Xdelta + Ydelta * Ydelta + Zdelta * Zdelta));
107 numUpBisect++;
108 } while ((numUpBisect < maxNumUpBisect) && (movDist < targetDist));
109
110 /* Find tDelta that gets us a jump of <targetDist. */
111 int numDownBisect = 0;
112 do {
113 tDelta = tDelta / 2;
114 Xdelta = (y) * tDelta;
115 Ydelta = (-x-z*y) * tDelta;
116 Zdelta = (y*y-a+b*z) * tDelta;
117 movDist = sqrt (fabs (Xdelta * Xdelta + Ydelta * Ydelta + Zdelta * Zdelta));
118 numDownBisect++;
119 } while ((numDownBisect < maxNumDownBisect) && (movDist > targetDist));
120
121 /* Update and draw */
122 dist += movDist;
123 x = x + Xdelta;
124 y = y + Ydelta;
125 z = z + Zdelta;
126 if((z-zLev)*(zOld-zLev)<=0.0)
127 theRamCanvas.drawPoint((x+xOld)/2.0, (y+yOld)/2.0, mjr::ramCanvas3c8b::colorType::cornerColorEnum::WHITE);
128 xOld = x;
129 yOld = y;
130 zOld = z;
131 }
132
133 theRamCanvas.writeTIFFfile("attracting_torus_shadowM_" + mjr::math::str::fmt_int(frame, 3, '0') + ".tiff");
134 std::chrono::duration<double> frameRunTime = std::chrono::system_clock::now() - frameStartTime;
135# pragma omp critical
136 std::cout << "Frame " << frame << " of " << NUMFRM << " Runtime " << frameRunTime.count() << " sec" << std::endl;
137 }
138
139 std::chrono::duration<double> runTime = std::chrono::system_clock::now() - startTime;
140 std::cout << "Total Runtime " << runTime.count() << " sec" << std::endl;
141
142 return 0;
143}
144/** @endcond */
int main(int argc, char *argv[])