1 module rip.draw.lsystem; 2 3 private 4 { 5 import std.math; 6 import std.string; 7 8 import rip.concepts; 9 import rip.draw.turtle; 10 } 11 12 // Правила переписывания 13 alias RewritingRules = string[string]; 14 15 // параметры L-системы 16 class LSystemParameters 17 { 18 private 19 { 20 float x; 21 float y; 22 float stepIncrement; 23 float angleIncrement; 24 ulong numberOfGeneration; 25 } 26 27 this(S, T, U, V, W)(S x, T y, U stepIncrement, V angleIncrement, W numberOfGeneration) 28 if (allArithmetic!(S, T, U, V, W)) 29 { 30 this.x = cast(float) x; 31 this.y = cast(float) y; 32 this.stepIncrement = cast(float) stepIncrement; 33 this.angleIncrement = cast(float) angleIncrement; 34 this.numberOfGeneration = cast(uint) abs(numberOfGeneration); 35 } 36 37 38 mixin(addTypedGetter!("x", "getX")); 39 mixin(addTypedGetter!("y", "getY")); 40 mixin(addTypedGetter!("stepIncrement", "getStep")); 41 mixin(addTypedGetter!("angleIncrement", "getAngle")); 42 mixin(addTypedGetter!("numberOfGeneration", "getGeneration")); 43 44 45 46 void setX(T)(T x) 47 if (allArithmetic!T) 48 { 49 this.x = cast(float) x; 50 } 51 52 void setY(T)(T y) 53 if (allArithmetic!T) 54 { 55 this.y = cast(float) y; 56 } 57 58 void setStep(T)(T angle) 59 if (allArithmetic!T) 60 { 61 this.stepIncrement = cast(float) stepIncrement; 62 } 63 64 void setAngle(T)(T angle) 65 if (allArithmetic!T) 66 { 67 this.angleIncrement = cast(float) angleIncrement; 68 } 69 70 void setGeneration(T)(T angle) 71 if (allArithmetic!T) 72 { 73 this.numberOfGeneration = cast(uint) numberOfGeneration; 74 } 75 } 76 77 class LSystem 78 { 79 private 80 { 81 Surface surface; 82 RGBColor color; 83 84 LSystemParameters parameters; 85 RewritingRules rules; 86 string axiom; 87 88 // процедура переписывания строки 89 string rewrite(string sourceTerm, string termForRewrite, string newTerm) 90 { 91 auto acc = ""; 92 auto search = 0; 93 94 for (uint i = 0; i < sourceTerm.length; i++) 95 { 96 auto index = indexOf(sourceTerm[search .. search + termForRewrite.length], termForRewrite); 97 98 if (index != -1) 99 { 100 search += termForRewrite.length; 101 acc ~= newTerm; 102 } 103 else 104 { 105 search++; 106 acc ~= sourceTerm[search-1]; 107 } 108 } 109 110 return acc; 111 } 112 } 113 114 this(Surface surface, RGBColor color, LSystemParameters parameters, 115 string axiom, RewritingRules rules) 116 { 117 this.surface = surface; 118 this.color = color; 119 this.parameters = parameters; 120 this.axiom = axiom; 121 this.rules = rules; 122 } 123 124 LSystemParameters execute() 125 { 126 // новое состояние черепахи 127 auto turtleState = new TurtleState( 128 parameters.getX!float, 129 parameters.getY!float, 130 parameters.getAngle!float 131 ); 132 // новая черепаха 133 auto turtle = new Turtle(surface, color, turtleState, 134 parameters.getStep!float, 135 parameters.getAngle!float 136 ); 137 138 // команды L-системы 139 auto lSystemCmd = axiom; 140 141 // запуск процедуры переписывания 142 for (ulong i = 1; i < parameters.getGeneration!ulong; i++) 143 { 144 foreach (rule; rules.keys) 145 { 146 lSystemCmd = rewrite(lSystemCmd.idup, rule, rules[rule]); 147 } 148 } 149 150 turtle.execute(lSystemCmd); 151 152 return parameters; 153 } 154 } 155