diff options
| author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-05-02 22:57:13 -0400 |
|---|---|---|
| committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-05-02 22:57:13 -0400 |
| commit | 330f75e663c22e1198a92fd134865ada98c3957b (patch) | |
| tree | b78f8aa762fcc93c14a0905546b694cddaaa3041 /fractal.cpp | |
| download | infinite-330f75e663c22e1198a92fd134865ada98c3957b.tar.gz infinite-330f75e663c22e1198a92fd134865ada98c3957b.tar.bz2 infinite-330f75e663c22e1198a92fd134865ada98c3957b.zip | |
Initial commit
Diffstat (limited to 'fractal.cpp')
| -rw-r--r-- | fractal.cpp | 602 |
1 files changed, 602 insertions, 0 deletions
| diff --git a/fractal.cpp b/fractal.cpp new file mode 100644 index 0000000..145886a --- /dev/null +++ b/fractal.cpp | |||
| @@ -0,0 +1,602 @@ | |||
| 1 | #include "tinyxml2.h" | ||
| 2 | #include "fractal.h" | ||
| 3 | #include <iostream> | ||
| 4 | #include <fstream> | ||
| 5 | #include "triangle.h" | ||
| 6 | |||
| 7 | Variation::Variation(Type _type, double _weight, std::vector<double> _params) : type(_type), weight(_weight), params(_params) | ||
| 8 | { | ||
| 9 | |||
| 10 | } | ||
| 11 | |||
| 12 | void Fractal::set_palette(std::string colors) | ||
| 13 | { | ||
| 14 | for (int i=0; i<256; i++) | ||
| 15 | { | ||
| 16 | std::string hexstr = colors.substr(i*6, 6); | ||
| 17 | palette.push_back(Color::fromHex(hexstr.c_str())); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | void Fractal::add_transform(double weight, Matrix3x3 transform, double color, std::vector<Variation> variations) | ||
| 22 | { | ||
| 23 | max += weight; | ||
| 24 | transforms[max] = Transform(transform, color, variations); | ||
| 25 | } | ||
| 26 | |||
| 27 | void Fractal::sample(double& x, double& y, double& c) const | ||
| 28 | { | ||
| 29 | double rtran = (double)rand()/RAND_MAX*max; | ||
| 30 | const Transform& transform = transforms.upper_bound(rtran)->second; | ||
| 31 | Vector3D in = transform.transform * Vector3D(x, y, 1.0); | ||
| 32 | double r2 = pow(in.x,2.0)+pow(in.y,2.0); | ||
| 33 | double r = sqrt(r2); | ||
| 34 | |||
| 35 | double tx, ty; | ||
| 36 | x = 0.0; | ||
| 37 | y = 0.0; | ||
| 38 | for (auto& variation : transform.variations) | ||
| 39 | { | ||
| 40 | switch (variation.type) | ||
| 41 | { | ||
| 42 | case Variation::Type::linear: | ||
| 43 | { | ||
| 44 | tx = in.x; | ||
| 45 | ty = in.y; | ||
| 46 | |||
| 47 | break; | ||
| 48 | } | ||
| 49 | |||
| 50 | case Variation::Type::sinusoidal: | ||
| 51 | { | ||
| 52 | tx = sin(in.x); | ||
| 53 | ty = sin(in.y); | ||
| 54 | |||
| 55 | break; | ||
| 56 | } | ||
| 57 | |||
| 58 | case Variation::Type::spherical: | ||
| 59 | { | ||
| 60 | tx = in.x/r2; | ||
| 61 | ty = in.y/r2; | ||
| 62 | |||
| 63 | break; | ||
| 64 | } | ||
| 65 | |||
| 66 | case Variation::Type::eyefish: | ||
| 67 | { | ||
| 68 | double xp = 2.0/(r+1.0); | ||
| 69 | tx = in.x*xp; | ||
| 70 | ty = in.y*xp; | ||
| 71 | |||
| 72 | break; | ||
| 73 | } | ||
| 74 | |||
| 75 | case Variation::Type::fisheye: | ||
| 76 | { | ||
| 77 | double xp = 2.0/(r+1.0); | ||
| 78 | tx = in.y*xp; | ||
| 79 | ty = in.x*xp; | ||
| 80 | |||
| 81 | break; | ||
| 82 | } | ||
| 83 | |||
| 84 | case Variation::Type::bubble: | ||
| 85 | { | ||
| 86 | double xp = 4.0/(r2+4); | ||
| 87 | tx = in.x*xp; | ||
| 88 | ty = in.y*xp; | ||
| 89 | |||
| 90 | break; | ||
| 91 | } | ||
| 92 | |||
| 93 | case Variation::Type::cylinder: | ||
| 94 | { | ||
| 95 | tx = sin(in.x); | ||
| 96 | ty = in.y; | ||
| 97 | |||
| 98 | break; | ||
| 99 | } | ||
| 100 | |||
| 101 | case Variation::Type::noise: | ||
| 102 | { | ||
| 103 | double phi1 = (double)rand()/RAND_MAX; | ||
| 104 | double phi2 = (double)rand()/RAND_MAX; | ||
| 105 | tx = in.x * phi1 * cos(2*M_PI*phi2); | ||
| 106 | ty = in.y * phi1 * sin(2*M_PI*phi2); | ||
| 107 | |||
| 108 | break; | ||
| 109 | } | ||
| 110 | |||
| 111 | case Variation::Type::blur: | ||
| 112 | { | ||
| 113 | double phi1 = (double)rand()/RAND_MAX; | ||
| 114 | double phi2 = (double)rand()/RAND_MAX; | ||
| 115 | tx = phi1 * cos(2*M_PI*phi2); | ||
| 116 | ty = phi1 * sin(2*M_PI*phi2); | ||
| 117 | |||
| 118 | break; | ||
| 119 | } | ||
| 120 | |||
| 121 | case Variation::Type::horseshoe: | ||
| 122 | { | ||
| 123 | tx = (1.0/r)*((in.x-in.y)*(in.x+in.y)); | ||
| 124 | ty = 2*in.x*in.y/r; | ||
| 125 | |||
| 126 | break; | ||
| 127 | } | ||
| 128 | |||
| 129 | case Variation::Type::swirl: | ||
| 130 | { | ||
| 131 | tx = in.x*sin(r2) - in.y*cos(r2); | ||
| 132 | ty = in.x*cos(r2) + in.y*sin(r2); | ||
| 133 | |||
| 134 | break; | ||
| 135 | } | ||
| 136 | |||
| 137 | case Variation::Type::julian: | ||
| 138 | { | ||
| 139 | double p1 = variation.params[0]; | ||
| 140 | double p2 = variation.params[1]; | ||
| 141 | double p3 = (double)(rand()%(int)floor(std::abs(p1))); | ||
| 142 | double t = (atan2(in.y, in.x) + 2*M_PI*p3) / p1; | ||
| 143 | double pw = pow(r2, p2 / p1 / 2.0); | ||
| 144 | tx = pw * cos(t); | ||
| 145 | ty = pw * sin(t); | ||
| 146 | |||
| 147 | break; | ||
| 148 | } | ||
| 149 | |||
| 150 | case Variation::Type::hyperbolic: | ||
| 151 | { | ||
| 152 | double theta = atan2(in.x, in.y); | ||
| 153 | tx = sin(theta)/r; | ||
| 154 | ty = r*cos(theta); | ||
| 155 | |||
| 156 | break; | ||
| 157 | } | ||
| 158 | |||
| 159 | case Variation::Type::polar: | ||
| 160 | { | ||
| 161 | double theta = atan2(in.x, in.y); | ||
| 162 | tx = theta/M_PI; | ||
| 163 | ty = r - 1; | ||
| 164 | |||
| 165 | break; | ||
| 166 | } | ||
| 167 | |||
| 168 | case Variation::Type::handkerchief: | ||
| 169 | { | ||
| 170 | double theta = atan2(in.x, in.y); | ||
| 171 | tx = r * sin(theta + r); | ||
| 172 | ty = r * cos(theta - r); | ||
| 173 | |||
| 174 | break; | ||
| 175 | } | ||
| 176 | |||
| 177 | case Variation::Type::heart: | ||
| 178 | { | ||
| 179 | double theta = atan2(in.x, in.y); | ||
| 180 | tx = r * sin(theta * r); | ||
| 181 | ty = -r * cos(theta * r); | ||
| 182 | |||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | case Variation::Type::disc: | ||
| 187 | { | ||
| 188 | double theta = atan2(in.x, in.y); | ||
| 189 | tx = theta/M_PI*sin(r*M_PI); | ||
| 190 | ty = theta/M_PI*cos(r*M_PI); | ||
| 191 | |||
| 192 | break; | ||
| 193 | } | ||
| 194 | |||
| 195 | case Variation::Type::spiral: | ||
| 196 | { | ||
| 197 | double theta = atan2(in.x, in.y); | ||
| 198 | tx = 1.0/r * (cos(theta) + sin(r)); | ||
| 199 | ty = 1.0/r * (sin(theta) - cos(r)); | ||
| 200 | |||
| 201 | break; | ||
| 202 | } | ||
| 203 | |||
| 204 | case Variation::Type::diamond: | ||
| 205 | { | ||
| 206 | double theta = atan2(in.x, in.y); | ||
| 207 | tx = sin(theta)*cos(r); | ||
| 208 | ty = cos(theta)*sin(r); | ||
| 209 | |||
| 210 | break; | ||
| 211 | } | ||
| 212 | |||
| 213 | case Variation::Type::ex: | ||
| 214 | { | ||
| 215 | double theta = atan2(in.x, in.y); | ||
| 216 | double p0 = pow(sin(theta + r), 3.0); | ||
| 217 | double p1 = pow(cos(theta - r), 3.0); | ||
| 218 | tx = r * (p0 + p1); | ||
| 219 | ty = r * (p0 - p1); | ||
| 220 | |||
| 221 | break; | ||
| 222 | } | ||
| 223 | |||
| 224 | case Variation::Type::julia: | ||
| 225 | { | ||
| 226 | double theta = atan2(in.x, in.y); | ||
| 227 | double omega = (double)(rand()%2) * M_PI; | ||
| 228 | double sr = sqrt(r); | ||
| 229 | tx = sr * cos(theta/2.0 + omega); | ||
| 230 | ty = sr * sin(theta/2.0 + omega); | ||
| 231 | |||
| 232 | break; | ||
| 233 | } | ||
| 234 | |||
| 235 | case Variation::Type::bent: | ||
| 236 | { | ||
| 237 | if (in.x >= 0) | ||
| 238 | { | ||
| 239 | tx = in.x; | ||
| 240 | } else { | ||
| 241 | tx = 2*in.x; | ||
| 242 | } | ||
| 243 | |||
| 244 | if (in.y >= 0) | ||
| 245 | { | ||
| 246 | ty = in.y; | ||
| 247 | } else { | ||
| 248 | ty = in.y/2.0; | ||
| 249 | } | ||
| 250 | |||
| 251 | break; | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | x += tx * variation.weight; | ||
| 256 | y += ty * variation.weight; | ||
| 257 | } | ||
| 258 | |||
| 259 | c = (c + transform.color) * (1.0/2.0); | ||
| 260 | } | ||
| 261 | |||
| 262 | Color Fractal::get_color(double c) const | ||
| 263 | { | ||
| 264 | int sc = std::min((int)floor(c * 256.0), 255); | ||
| 265 | return palette[sc]; | ||
| 266 | } | ||
| 267 | |||
| 268 | LogScale::LogScale(double brightness, double quality) | ||
| 269 | { | ||
| 270 | double contrast = 1.0; | ||
| 271 | double brightadjust = 2.3; | ||
| 272 | double white = 200.0; | ||
| 273 | k1 = contrast * (268.0 * brightadjust) * 100.0 * brightness / (256.0*256.0); | ||
| 274 | k2 = 1.0 / (contrast * white * quality); | ||
| 275 | |||
| 276 | for (int i=0; i<1024; i++) | ||
| 277 | { | ||
| 278 | memo.push_back(k1 * std::log(1+white*i*k2)/(std::log(10)*white*i)); | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | double LogScale::log(double n) const | ||
| 283 | { | ||
| 284 | int in = (int)floor(n); | ||
| 285 | if (in < 1024) | ||
| 286 | { | ||
| 287 | return memo[in]; | ||
| 288 | } else { | ||
| 289 | double white = 200.0; | ||
| 290 | return k1 * std::log(1+white*n*k2)/(std::log(10)*white*n); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | template <class Container> | ||
| 295 | Container split(std::string input, std::string delimiter) | ||
| 296 | { | ||
| 297 | Container result; | ||
| 298 | |||
| 299 | while (!input.empty()) | ||
| 300 | { | ||
| 301 | int divider = input.find(delimiter); | ||
| 302 | if (divider == std::string::npos) | ||
| 303 | { | ||
| 304 | result.push_back(input); | ||
| 305 | |||
| 306 | input = ""; | ||
| 307 | } else { | ||
| 308 | result.push_back(input.substr(0, divider)); | ||
| 309 | |||
| 310 | input = input.substr(divider+delimiter.length()); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | return result; | ||
| 315 | } | ||
| 316 | |||
| 317 | int Fractal::load(const char* filename, Fractal& fractal) | ||
| 318 | { | ||
| 319 | std::ifstream in(filename); | ||
| 320 | if(!in.is_open()) | ||
| 321 | { | ||
| 322 | return -1; | ||
| 323 | } | ||
| 324 | |||
| 325 | in.close(); | ||
| 326 | |||
| 327 | tinyxml2::XMLDocument doc; | ||
| 328 | doc.LoadFile(filename); | ||
| 329 | if(doc.Error()) | ||
| 330 | { | ||
| 331 | doc.PrintError(); | ||
| 332 | exit(1); | ||
| 333 | } | ||
| 334 | |||
| 335 | tinyxml2::XMLElement* root = doc.FirstChildElement( "flame" ); | ||
| 336 | if( !root ) | ||
| 337 | { | ||
| 338 | std::cerr << "Error: not a flame file!" << std::endl; | ||
| 339 | exit( 1 ); | ||
| 340 | } | ||
| 341 | |||
| 342 | root->QueryDoubleAttribute("filter", &fractal.filterlevel); | ||
| 343 | root->QueryDoubleAttribute("gamma", &fractal.gamma); | ||
| 344 | root->QueryDoubleAttribute("gamma_threshold", &fractal.gammathresh); | ||
| 345 | root->QueryDoubleAttribute("brightness", &fractal.brightness); | ||
| 346 | |||
| 347 | const char* sizestr = root->Attribute("size"); | ||
| 348 | sscanf(sizestr, "%lf %lf", &fractal.width, &fractal.height); | ||
| 349 | |||
| 350 | tinyxml2::XMLElement* elem = root->FirstChildElement(); | ||
| 351 | while (elem) | ||
| 352 | { | ||
| 353 | std::string elementType (elem->Value()); | ||
| 354 | if (elementType == "xform") | ||
| 355 | { | ||
| 356 | double weight; | ||
| 357 | double color; | ||
| 358 | Matrix3x3 transform; | ||
| 359 | elem->QueryDoubleAttribute("weight", &weight); | ||
| 360 | elem->QueryDoubleAttribute("color", &color); | ||
| 361 | std::string transstr(elem->Attribute("coefs")); | ||
| 362 | auto transvals = split<std::vector<std::string>>(transstr, " "); | ||
| 363 | transform(0,0) = std::stod(transvals[0]); | ||
| 364 | transform(0,1) = std::stod(transvals[2]); | ||
| 365 | transform(0,2) = std::stod(transvals[4]); | ||
| 366 | transform(1,0) = std::stod(transvals[1]); | ||
| 367 | transform(1,1) = std::stod(transvals[3]); | ||
| 368 | transform(1,2) = std::stod(transvals[5]); | ||
| 369 | transform(2,0) = 0.0; | ||
| 370 | transform(2,1) = 0.0; | ||
| 371 | transform(2,2) = 1.0; | ||
| 372 | std::vector<Variation> varies; | ||
| 373 | const char* varyval = 0; | ||
| 374 | if ((varyval = elem->Attribute("linear")) != 0) | ||
| 375 | { | ||
| 376 | varies.push_back(Variation(Variation::Type::linear, std::stod(std::string(varyval)))); | ||
| 377 | } | ||
| 378 | |||
| 379 | if ((varyval = elem->Attribute("sinusoidal")) != 0) | ||
| 380 | { | ||
| 381 | varies.push_back(Variation(Variation::Type::sinusoidal, std::stod(std::string(varyval)))); | ||
| 382 | } | ||
| 383 | |||
| 384 | if ((varyval = elem->Attribute("spherical")) != 0) | ||
| 385 | { | ||
| 386 | varies.push_back(Variation(Variation::Type::spherical, std::stod(std::string(varyval)))); | ||
| 387 | } | ||
| 388 | |||
| 389 | if ((varyval = elem->Attribute("eyefish")) != 0) | ||
| 390 | { | ||
| 391 | varies.push_back(Variation(Variation::Type::eyefish, std::stod(std::string(varyval)))); | ||
| 392 | } | ||
| 393 | |||
| 394 | if ((varyval = elem->Attribute("bubble")) != 0) | ||
| 395 | { | ||
| 396 | varies.push_back(Variation(Variation::Type::bubble, std::stod(std::string(varyval)))); | ||
| 397 | } | ||
| 398 | |||
| 399 | if ((varyval = elem->Attribute("cylinder")) != 0) | ||
| 400 | { | ||
| 401 | varies.push_back(Variation(Variation::Type::cylinder, std::stod(std::string(varyval)))); | ||
| 402 | } | ||
| 403 | |||
| 404 | if ((varyval = elem->Attribute("noise")) != 0) | ||
| 405 | { | ||
| 406 | varies.push_back(Variation(Variation::Type::noise, std::stod(std::string(varyval)))); | ||
| 407 | } | ||
| 408 | |||
| 409 | if ((varyval = elem->Attribute("blur")) != 0) | ||
| 410 | { | ||
| 411 | varies.push_back(Variation(Variation::Type::blur, std::stod(std::string(varyval)))); | ||
| 412 | } | ||
| 413 | |||
| 414 | if ((varyval = elem->Attribute("pre_blur")) != 0) | ||
| 415 | { | ||
| 416 | varies.push_back(Variation(Variation::Type::blur, std::stod(std::string(varyval)))); | ||
| 417 | } | ||
| 418 | |||
| 419 | if ((varyval = elem->Attribute("horseshoe")) != 0) | ||
| 420 | { | ||
| 421 | varies.push_back(Variation(Variation::Type::horseshoe, std::stod(std::string(varyval)))); | ||
| 422 | } | ||
| 423 | |||
| 424 | if ((varyval = elem->Attribute("swirl")) != 0) | ||
| 425 | { | ||
| 426 | varies.push_back(Variation(Variation::Type::swirl, std::stod(std::string(varyval)))); | ||
| 427 | } | ||
| 428 | |||
| 429 | if ((varyval = elem->Attribute("hyperbolic")) != 0) | ||
| 430 | { | ||
| 431 | varies.push_back(Variation(Variation::Type::hyperbolic, std::stod(std::string(varyval)))); | ||
| 432 | } | ||
| 433 | |||
| 434 | if ((varyval = elem->Attribute("julian")) != 0) | ||
| 435 | { | ||
| 436 | varies.push_back(Variation(Variation::Type::julian, std::stod(std::string(varyval)), {elem->DoubleAttribute("julian_power"), elem->DoubleAttribute("julian_dist")})); | ||
| 437 | } | ||
| 438 | |||
| 439 | if ((varyval = elem->Attribute("polar")) != 0) | ||
| 440 | { | ||
| 441 | varies.push_back(Variation(Variation::Type::polar, std::stod(std::string(varyval)))); | ||
| 442 | } | ||
| 443 | |||
| 444 | if ((varyval = elem->Attribute("handkerchief")) != 0) | ||
| 445 | { | ||
| 446 | varies.push_back(Variation(Variation::Type::handkerchief, std::stod(std::string(varyval)))); | ||
| 447 | } | ||
| 448 | |||
| 449 | if ((varyval = elem->Attribute("heart")) != 0) | ||
| 450 | { | ||
| 451 | varies.push_back(Variation(Variation::Type::heart, std::stod(std::string(varyval)))); | ||
| 452 | } | ||
| 453 | |||
| 454 | if ((varyval = elem->Attribute("disc")) != 0) | ||
| 455 | { | ||
| 456 | varies.push_back(Variation(Variation::Type::disc, std::stod(std::string(varyval)))); | ||
| 457 | } | ||
| 458 | |||
| 459 | if ((varyval = elem->Attribute("spiral")) != 0) | ||
| 460 | { | ||
| 461 | varies.push_back(Variation(Variation::Type::spiral, std::stod(std::string(varyval)))); | ||
| 462 | } | ||
| 463 | |||
| 464 | if ((varyval = elem->Attribute("diamond")) != 0) | ||
| 465 | { | ||
| 466 | varies.push_back(Variation(Variation::Type::diamond, std::stod(std::string(varyval)))); | ||
| 467 | } | ||
| 468 | |||
| 469 | if ((varyval = elem->Attribute("ex")) != 0) | ||
| 470 | { | ||
| 471 | varies.push_back(Variation(Variation::Type::ex, std::stod(std::string(varyval)))); | ||
| 472 | } | ||
| 473 | |||
| 474 | if ((varyval = elem->Attribute("julia")) != 0) | ||
| 475 | { | ||
| 476 | varies.push_back(Variation(Variation::Type::julia, std::stod(std::string(varyval)))); | ||
| 477 | } | ||
| 478 | |||
| 479 | if ((varyval = elem->Attribute("bent")) != 0) | ||
| 480 | { | ||
| 481 | varies.push_back(Variation(Variation::Type::bent, std::stod(std::string(varyval)))); | ||
| 482 | } | ||
| 483 | |||
| 484 | if ((varyval = elem->Attribute("fisheye")) != 0) | ||
| 485 | { | ||
| 486 | varies.push_back(Variation(Variation::Type::fisheye, std::stod(std::string(varyval)))); | ||
| 487 | } | ||
| 488 | |||
| 489 | fractal.add_transform(weight, transform, color, varies); | ||
| 490 | } else if (elementType == "palette") | ||
| 491 | { | ||
| 492 | std::string val(elem->GetText()); | ||
| 493 | for (int i=0; i<val.length(); i++) | ||
| 494 | { | ||
| 495 | if (val[i] == ' ' || val[i] == '\n') | ||
| 496 | { | ||
| 497 | val.erase(i, 1); | ||
| 498 | i--; | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | fractal.set_palette(val); | ||
| 503 | } | ||
| 504 | |||
| 505 | elem = elem->NextSiblingElement(); | ||
| 506 | } | ||
| 507 | |||
| 508 | return 0; | ||
| 509 | } | ||
| 510 | |||
| 511 | Fractal Fractal::random() | ||
| 512 | { | ||
| 513 | Fractal fractal; | ||
| 514 | |||
| 515 | int xforms = rand() % 2 + 2; | ||
| 516 | double remweight = 1.0; | ||
| 517 | for (int i=0; i<xforms; i++) | ||
| 518 | { | ||
| 519 | double weight; | ||
| 520 | if (i == (xforms-1)) | ||
| 521 | { | ||
| 522 | weight = remweight; | ||
| 523 | } else { | ||
| 524 | weight = ((double)rand()/RAND_MAX)*remweight; | ||
| 525 | remweight -= weight; | ||
| 526 | } | ||
| 527 | |||
| 528 | Triangle gentri( | ||
| 529 | ((double)rand()/RAND_MAX)*2-1, | ||
| 530 | ((double)rand()/RAND_MAX)*2-1, | ||
| 531 | ((double)rand()/RAND_MAX)*2-1, | ||
| 532 | ((double)rand()/RAND_MAX)*2-1, | ||
| 533 | ((double)rand()/RAND_MAX)*2-1, | ||
| 534 | ((double)rand()/RAND_MAX)*2-1 | ||
| 535 | ); | ||
| 536 | Matrix3x3 affine = affineTransform(Triangle(0, 0, 1, 0, 0, 1), gentri); | ||
| 537 | double color = (double)i/(xforms-1); | ||
| 538 | std::vector<Variation> variations; | ||
| 539 | |||
| 540 | double remaffix = 1.0; | ||
| 541 | for (int j=0; j<2; j++) | ||
| 542 | { | ||
| 543 | double affix; | ||
| 544 | if (j == 1) | ||
| 545 | { | ||
| 546 | affix = remaffix; | ||
| 547 | } else { | ||
| 548 | affix = ((double)rand()/RAND_MAX)*remaffix; | ||
| 549 | remaffix -= affix; | ||
| 550 | } | ||
| 551 | |||
| 552 | Variation::Type type; | ||
| 553 | switch (rand()%16) | ||
| 554 | { | ||
| 555 | case 0: type = Variation::Type::linear; break; | ||
| 556 | case 1: type = Variation::Type::sinusoidal; break; | ||
| 557 | case 2: type = Variation::Type::spherical; break; | ||
| 558 | case 3: type = Variation::Type::eyefish; break; | ||
| 559 | case 4: type = Variation::Type::bubble; break; | ||
| 560 | case 5: type = Variation::Type::cylinder; break; | ||
| 561 | case 6: type = Variation::Type::blur; break; | ||
| 562 | case 7: type = Variation::Type::horseshoe; break; | ||
| 563 | case 8: type = Variation::Type::swirl; break; | ||
| 564 | case 9: type = Variation::Type::hyperbolic; break; | ||
| 565 | case 10: type = Variation::Type::polar; break; | ||
| 566 | case 11: type = Variation::Type::handkerchief; break; | ||
| 567 | case 12: type = Variation::Type::heart; break; | ||
| 568 | case 13: type = Variation::Type::disc; break; | ||
| 569 | case 14: type = Variation::Type::spiral; break; | ||
| 570 | case 15: type = Variation::Type::diamond; break; | ||
| 571 | } | ||
| 572 | |||
| 573 | variations.push_back(Variation(type, affix)); | ||
| 574 | } | ||
| 575 | |||
| 576 | fractal.add_transform(weight, affine, color, variations); | ||
| 577 | } | ||
| 578 | |||
| 579 | std::vector<std::string> colors; | ||
| 580 | std::ifstream colorfile("colors.txt"); | ||
| 581 | if (!colorfile.is_open()) | ||
| 582 | { | ||
| 583 | std::cout << "Could not find colors.txt" << std::endl; | ||
| 584 | exit(-1); | ||
| 585 | } | ||
| 586 | |||
| 587 | std::string line; | ||
| 588 | while (getline(colorfile, line)) | ||
| 589 | { | ||
| 590 | if (line.back() == '\r') | ||
| 591 | { | ||
| 592 | line.pop_back(); | ||
| 593 | } | ||
| 594 | |||
| 595 | colors.push_back(line); | ||
| 596 | } | ||
| 597 | |||
| 598 | colorfile.close(); | ||
| 599 | fractal.set_palette(colors[rand() % colors.size()]); | ||
| 600 | |||
| 601 | return fractal; | ||
| 602 | } | ||
