Hal Canary | 8800042 | 2020-01-15 11:51:12 -0500 | [diff] [blame] | 1 | // Copyright 2020 Google LLC. |
| 2 | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. |
| 3 | #include "tools/fiddle/examples.h" |
| 4 | REG_FIDDLE_ANIMATED(l_system_plant, 256, 256, false, 0, 3) { |
| 5 | // L-System |
| 6 | // https://en.wikipedia.org/wiki/L-system#Example_7:_Fractal_plant |
| 7 | |
| 8 | struct rules_t { |
| 9 | char c; |
| 10 | std::string s; |
| 11 | }; |
| 12 | |
| 13 | rules_t rules[6] = { |
| 14 | {'X', "F-[[X]+X]+F[+FX]-X"}, |
| 15 | {'F', "FF"}, |
| 16 | {'+', "+"}, |
| 17 | {'-', "-"}, |
| 18 | {'[', "["}, |
| 19 | {']', "]"}, |
| 20 | }; |
| 21 | |
| 22 | std::string E(std::string s) { |
| 23 | if (s.size() == 0) { |
| 24 | return ""; |
| 25 | } |
| 26 | for (int i=0; i<6; i++) { |
| 27 | if (rules[i].c == s[0]) { |
| 28 | return rules[i].s + E(s.substr(1)); |
| 29 | } |
| 30 | } |
| 31 | return ""; |
| 32 | } |
| 33 | |
| 34 | struct Pt { |
| 35 | SkScalar x; |
| 36 | SkScalar y; |
| 37 | SkScalar a; |
| 38 | }; |
| 39 | |
| 40 | void draw(SkCanvas* canvas) { |
| 41 | canvas->drawColor(SK_ColorLTGRAY); |
| 42 | |
| 43 | SkPaint p; |
| 44 | p.setColor(0xFFA6761D); |
| 45 | p.setAntiAlias(true); |
| 46 | p.setStyle(SkPaint::kStroke_Style); |
| 47 | p.setStrokeWidth(1); |
| 48 | |
| 49 | std::vector<struct Pt> ptstack; |
| 50 | std::string plant = E(E(E(E(E("X"))))); |
| 51 | const double len = 2.5; |
| 52 | struct Pt pt = {128, 256, 3.14}; |
| 53 | SkPath path; |
| 54 | path.moveTo(pt.x, pt.y); |
| 55 | |
| 56 | for (std::string::iterator it=plant.begin(); it!=plant.end(); ++it) { |
| 57 | if (*it == 'F') { |
| 58 | pt.x += len*sin(pt.a); |
| 59 | pt.y += len*cos(pt.a); |
| 60 | path.lineTo(pt.x, pt.y); |
| 61 | } else if (*it == '+') { |
| 62 | pt.a += (0.15 + sin(frame*2.0*3.14159)*0.05); |
| 63 | } else if (*it == '-') { |
| 64 | pt.a += (-0.15 + sin(frame*2.0*3.14159)*0.05); |
| 65 | } else if (*it == '[') { |
| 66 | ptstack.push_back(pt); |
| 67 | } else if (*it == ']') { |
| 68 | pt = ptstack.back(); |
| 69 | ptstack.pop_back(); |
| 70 | path.moveTo(pt.x, pt.y); |
| 71 | } |
| 72 | } |
| 73 | canvas->drawPath(path, p); |
| 74 | } |
| 75 | } // END FIDDLE |