using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleLSystem { public class LSystemNodeLiteralVariable : LSystemNodeLiteral { public Dictionary variableIndex { get; } public LSystemNodeLiteralVariable(string name, int values_number, Dictionary variableIndex) : base(name, values_number) { this.variableIndex = variableIndex; } } public class LSystemNodeGenerator : LSystemNode { MathExpression[] math_expressions; public LSystemNodeGenerator(string name, int arguments) : base(new LSystemNodeLiteral(name, arguments)) { } public void fillArguments(MathExpression[] math_expressions) { this.math_expressions = math_expressions; } public LSystemNode eval(float[] values) { var literal = new LSystemNodeLiteral(this.literal.name, this.literal.values_number); for (int i = 0; i < literal.values_number; i++) { literal.values[i] = math_expressions[i].eval(values); } var result = new LSystemNode(literal); foreach (LSystemNodeGenerator child in children) { var _child = child.eval(values); _child.parent = result; result.children.Add(_child); } if (mainChild != null) { var _mainChild = ((LSystemNodeGenerator)mainChild).eval(values); _mainChild.parent = result; result.mainChild = _mainChild; } else { result.mainChild = null; } return result; } } abstract public class LSystemRule { abstract public bool is_aplicable(LSystemNode processed_node, String[] ignored); abstract public LSystemNode rewrite(LSystemNode processed_node, String[] ignored); } public class LSystemRuleBasic : LSystemRule { LSystemNodeLiteral input;// { get; } LSystemNode output; public LSystemRuleBasic(LSystemNodeLiteral input, LSystemNode output) { this.input = input; this.output = output; } override public bool is_aplicable(LSystemNode processed_node, String[] ignored) { if (processed_node.literal == input) { return true; } else { return false; } } override public LSystemNode rewrite(LSystemNode processed_node, String[] ignored) { if (is_aplicable(processed_node, ignored)) { return output.deep_copy(); } else { return new LSystemNode(processed_node.literal); } } } public class LSystemRuleParametric : LSystemRule { LSystemNodeLiteralVariable predecesor;// { get; } LSystemNodeGenerator consequent; MathExpressionComparison[] conditions; public LSystemRuleParametric(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent) { this.predecesor = predecesor; this.consequent = consequent; this.conditions = conditions; } public override bool is_aplicable(LSystemNode processed_node, String[] ignored) { if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) { return false; } foreach (var condition in conditions) { if (!condition.eval(processed_node.literal.values)) { return false; } } return true; } public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored) { if (is_aplicable(processed_node, ignored)) { return consequent.eval(processed_node.literal.values); } else { return new LSystemNode(processed_node.literal); } } } public class LSystemRuleParametricStochastic : LSystemRule { protected LSystemNodeLiteralVariable predecesor;// { get; } protected LSystemNodeGenerator[] consequents; protected float[] probabilities; protected MathExpressionComparison[] conditions; protected Random random; public LSystemRuleParametricStochastic(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator[] consequents, float[] probabilities) { this.predecesor = predecesor; this.consequents = consequents; this.conditions = conditions; float probabilities_sum = 0; foreach (var probability in probabilities) { probabilities_sum += probability; } float acumulator = 0; this.probabilities = new float[consequents.Length]; for (int i = 0; i < consequents.Length; i++) { var probability = probabilities[i] / probabilities_sum; this.probabilities[i] = probability + acumulator; acumulator += probability; } random = new Random(); } public LSystemRuleParametricStochastic(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent) { this.predecesor = predecesor; this.consequents = new LSystemNodeGenerator[] { consequent }; this.conditions = conditions; float probabilities_sum = 0; probabilities = new float[1] { 1 }; random = new Random(); } public override bool is_aplicable(LSystemNode processed_node, String[] ignored) { if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) { return false; } foreach (var condition in conditions) { if (!condition.eval(processed_node.literal.values)) { return false; } } return true; } public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored) { var result = random.NextDouble(); int consequent_index = 0; for (int i = 0; i < probabilities.Length; i++) { if (result < probabilities[i]) { consequent_index = i; break; } } if (is_aplicable(processed_node, ignored)) { return consequents[consequent_index].eval(processed_node.literal.values); } else { return new LSystemNode(processed_node.literal); } } } public class LSystemContext { public LSystemNodeLiteral parent { get; set; } public LSystemNodeLiteral child { get; set; } public LSystemNodeLiteral mid { get; set; } bool isPreceding = false; bool isSucceeding = false; public LSystemContext(LSystemNodeLiteral parent, LSystemNodeLiteral child) { this.parent = parent; this.child = child; this.isPreceding = true; this.isSucceeding = true; } public LSystemContext() { } public void setOnlyPreceding(LSystemNodeLiteral parent) { this.parent = parent; this.mid = mid; this.isPreceding = true; this.isSucceeding = false; } public void setOnlySucceeding(LSystemNodeLiteral child) { this.child = child; this.isPreceding = false; this.isSucceeding = true; } public bool isAplicable(LSystemNode node, String[] ignored, out float[] variables) { var variables_list = new List(); var currentParent = node.parent; while (ignored.Contains(currentParent.literal.name)) { currentParent = currentParent.parent; } if (isPreceding && parent != currentParent.literal) { variables = new float[0]; return false; } if (isPreceding) { variables_list.AddRange(currentParent.literal.values); } variables_list.AddRange(node.literal.values); if (isSucceeding) { var result = false; LSystemNodeLiteral childLiteral; Queue ignoredChildren = new Queue(); foreach(var child in node.getAllChildren()) { if (ignored.Contains(child.literal.name)) { ignoredChildren.Enqueue(child); } if (child.literal == this.child) { childLiteral = child.literal; result = true; variables_list.AddRange(child.literal.values); break; } } while (!result && ignoredChildren.Count>0) { var ignoredChild = ignoredChildren.Dequeue(); foreach (var child in ignoredChild.getAllChildren()) { if (ignored.Contains(child.literal.name)) { ignoredChildren.Enqueue(child); } if (child.literal == this.child) { childLiteral = child.literal; result = true; variables_list.AddRange(child.literal.values); break; } } } if (!result) { variables = new float[0]; return false; } } variables = variables_list.ToArray(); return true; } } public class LSystemRuleParametricStochasticContext : LSystemRuleParametricStochastic { LSystemContext context; public LSystemRuleParametricStochasticContext(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator[] consequents, float[] probabilities, LSystemContext context) : base(predecesor, conditions, consequents, probabilities) { this.context = context; } public LSystemRuleParametricStochasticContext(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent, LSystemContext context) : base(predecesor, conditions, consequent) { this.context = context; } public override bool is_aplicable(LSystemNode processed_node,String[] ignored) { if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) { return false; } var variables = new float[0]; if (!context.isAplicable(processed_node, ignored, out variables)) { return false; } foreach (var condition in conditions) { if (!condition.eval(variables)) { return false; } } return true; } bool is_aplicable(LSystemNode processed_node, String[] ignored, out float[] variables) { variables = new float[0]; if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) { return false; } if (!context.isAplicable(processed_node, ignored, out variables)) { return false; } foreach (var condition in conditions) { if (!condition.eval(variables)) { return false; } } return true; } public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored) { var result = random.NextDouble(); int consequent_index = 0; for (int i = 0; i < probabilities.Length; i++) { if (result < probabilities[i]) { consequent_index = i; break; } } float[] variables; if (is_aplicable(processed_node, ignored, out variables)) { return consequents[consequent_index].eval(variables); } else { return new LSystemNode(processed_node.literal); } } } }