📄 fract_gen.cpp
字号:
/* general routines for calculating fractals */#include <stdio.h>#include <stdlib.h>#include <math.h>#include "pmandel.h"#include "fract_gen.h"static NUM rmin, rmax, imin, imax;static int xmin, xmax, ymin, ymax;static int mbrotrep_maxiter = 200, mbrotrep_miniter = 100;static int mbrotrep_longestCycle = 10;static double mbrotrep_boundary_sq = 16, mbrotrep_fudgeFactor=.001;typedef NUM two_NUM[2];static two_NUM *mbrotrep_lastMoves;static Mbrot_settings mbrot_settings;static Julia_settings julia_settings;static Newton_settings newton_settings;void Fract_SetRegion(NUM newrmin, NUM newrmax, NUM newimin, NUM newimax, int newxmin, int newxmax, int newymin, int newymax){ rmin = newrmin; rmax = newrmax; imin = newimin; imax = newimax; xmin = newxmin; xmax = newxmax; ymin = newymin; ymax = newymax;}void Mbrot_Settings(double boundary_sq, int maxiter){ mbrot_settings.boundary_sq = boundary_sq; mbrot_settings.maxiter = maxiter;}void Newton_Settings(double epsilon, int *coeff, int nterms){ newton_settings.epsilon = epsilon; newton_settings.coeff = coeff; newton_settings.nterms = nterms;}void Julia_Settings(double boundary_sq, int maxiter, NUM real, NUM imag){ julia_settings.boundary_sq = boundary_sq; julia_settings.maxiter = maxiter; NUM_ASSIGN(julia_settings.r, real); NUM_ASSIGN(julia_settings.i, imag);}void Mbrotrep_Settings(double boundary, int maxiter, int miniter, int longestCycle, double fudgeFactor)/* When performing the Mandelbrot transformation on points that are in theset, eventually the sequence of numbers will reach fall into a repetativecycle. Mbrotrep plots the length of these cycles. Points near the centerof the set should have very short cycles--1 or 2 iterations long. Pointson the fringes of the set will have longer cycles, and points outside theset will not have cycles. Their cycle length will be denoted as 0. boundary - if the sequence exceeds 'boundary', it is assumed not to be in the set, and its cycle length is set to 0 maxiter - maximum number of iterations to compute, looking for a cycle longestCycle - maximum length of cycle to look for; should be <= maxiter fudgeFactor - it will be faster and more accurate (I think) to give some leeway in considering two elements in the sequence identical. For example, {1.1235, .03452, 1.1231, .03456,...} is close enough to a cycle length of 2, if we set the fudgeFactor to <.0004. As we zoom into a narrower range of points in the complex plane, we should scale down the fudgeFactor accordingly. */{ mbrotrep_boundary_sq = boundary*boundary; mbrotrep_maxiter = maxiter; mbrotrep_miniter = miniter; mbrotrep_longestCycle = longestCycle; mbrotrep_fudgeFactor = fudgeFactor; mbrotrep_lastMoves = (two_NUM *)malloc(sizeof(NUM[2])*longestCycle);}int MbrotCalcIter (NUM re, NUM im){ register NUM zr, zi, temp; register int k; /* set initial value - Z[0] = c */ k = 0; zr = re; zi = im; while (k<mbrot_settings.maxiter && COMPLEX_MAGNITUDE_SQ(zr, zi)<mbrot_settings.boundary_sq) { COMPLEX_SQUARE(zr, zi, temp); COMPLEX_ADD(zr, zi, re, im); k++; } return k;}int JuliaCalcIter (NUM re, NUM im){ register NUM zr, zi, temp, jr, ji; register int k; /* set initial value - Z[0] = c */ k = 0; zr = re; zi = im; NUM_ASSIGN(jr, julia_settings.r); NUM_ASSIGN(ji, julia_settings.i); while (k<julia_settings.maxiter && COMPLEX_MAGNITUDE_SQ(zr, zi)<julia_settings.boundary_sq) { COMPLEX_SQUARE(zr, zi, temp); COMPLEX_ADD(zr, zi, jr, ji); k++; } return k;}int MbrotrepCalcIter (NUM re, NUM im){ register NUM zr, zi, temp; register int k, lmi, j; int len; /* lmi - lastMove index */ for (lmi = 0; lmi<mbrotrep_longestCycle; lmi++) { mbrotrep_lastMoves[lmi][0] = mbrotrep_lastMoves[lmi][1] = 0; } /* set initial value - Z[0] = c */ k = lmi = 0; zr = re; zi = im; while (k<mbrotrep_maxiter && COMPLEX_MAGNITUDE_SQ(zr, zi)<mbrotrep_boundary_sq) { COMPLEX_SQUARE(zr, zi, temp); COMPLEX_ADD(zr, zi, re, im); k++; if (k>mbrotrep_miniter) { j = lmi; do { j--; if (j<0) j = mbrotrep_longestCycle-1; if (fabs(mbrotrep_lastMoves[j][0]-zr)<mbrotrep_fudgeFactor && fabs(mbrotrep_lastMoves[j][1]-zi)<mbrotrep_fudgeFactor) { len = lmi-j; if (len<1) len += mbrotrep_longestCycle; return len; } } while (j != lmi); } mbrotrep_lastMoves[lmi][0] = zr; mbrotrep_lastMoves[lmi][1] = zi; lmi++; if (lmi == mbrotrep_longestCycle) lmi = 0; } return 0;}void CalcField (Fractal_type fn, int *fieldVal, int xstart, int xend, int ystart, int yend){ int height, width, i, j; register NUM rstep, istep, real, imag, rstart, rend, istart, iend; height = yend-ystart + 1; width = xend-xstart + 1; /* get the bounding coordinates in the complex plane */ NUM_ASSIGN(rstart, COORD2CMPLX(rmin, rmax, xmin, xmax, xstart)); NUM_ASSIGN(real, rstart); NUM_ASSIGN(rend, COORD2CMPLX(rmin, rmax, xmin, xmax, xend)); NUM_ASSIGN(istart, COORD2CMPLX(imax, imin, ymin, ymax, ystart)); NUM_ASSIGN(iend, COORD2CMPLX(imax, imin, ymin, ymax, yend)); NUM_ASSIGN(imag, istart); NUM_ASSIGN(rstep, NUM_DIV(NUM_SUB(rend, rstart), INT2NUM(width-1))); NUM_ASSIGN(istep, NUM_DIV(NUM_SUB(iend, istart), INT2NUM(height-1))); switch (fn) { case MBROT: for (j = 0; j<height; j++) { for (i = 0; i<width; i++) { *fieldVal = MbrotCalcIter(real, imag); fieldVal++; NUM_ASSIGN(real, NUM_ADD(real, rstep)); } NUM_ASSIGN(real, rstart); NUM_ASSIGN(imag, NUM_ADD(imag, istep)); } break; case JULIA: for (j = 0; j<height; j++) { for (i = 0; i<width; i++) { fieldVal[j*width + i] = JuliaCalcIter(real, imag); NUM_ASSIGN(real, NUM_ADD(real, rstep)); } NUM_ASSIGN(real, rstart); NUM_ASSIGN(imag, NUM_ADD(imag, istep)); } break; case NEWTON: /* NOTE: Visualization of Newton's approximmation is not implemented yet. Sorry for the inconvenience */ for (j = 0; j<height; j++) { for (i = 0; i<width; i++) { fieldVal[j*width + i] = MbrotCalcIter(real, imag); NUM_ASSIGN(real, NUM_ADD(real, rstep)); } NUM_ASSIGN(real, rstart); NUM_ASSIGN(imag, NUM_ADD(imag, istep)); } break; } /* end switch */}void CopySub2DArray (int *mainArray, int *subArray, int mainWidth, int mainHeight, int subWidth, int subHeight, int xpos, int ypos) /* CopySub2DArray copies one 2d array of ints stored as a 1d array into another 2d array of ints stored as a 1d array. For example: mainArray = 10x10 array, all 0's subArray = 5x3 array, all 1's copy subArray to 2, 3 within mainArray CopySub2DArray(mainArray, subArray, 10, 10, 5, 3, 2, 3); 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 + 1 1 1 1 1 = 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 If the copy goes outside the bounds of the mainArray, none of the copy is performed */{ int i, j, *fromPtr, *toPtr; if (mainWidth<subWidth + xpos || mainHeight<subHeight + ypos) { /* make sure we don't overrun */ return; } fromPtr = subArray; /* set read location at upper left corner of subArray */ toPtr = mainArray + ypos*mainWidth + xpos; /* set write location at upper left corner in mainArray */ for (j = 0; j<subHeight; j++) { for (i = 0; i<subWidth; i++) { *toPtr++ = *fromPtr++; } toPtr += mainWidth-subWidth; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -