347 lines
14 KiB
C#
347 lines
14 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Text.RegularExpressions;
|
|||
|
|
|||
|
namespace ConsoleLSystem {
|
|||
|
public class LSystemNodeLiteral {
|
|||
|
public string name { get; }
|
|||
|
public int values_number { get; }
|
|||
|
|
|||
|
public float[] values { get; set; }
|
|||
|
|
|||
|
public LSystemNodeLiteral(string name, int values_number) {
|
|||
|
this.name = name;
|
|||
|
this.values_number = values_number;
|
|||
|
//in case it would be 0
|
|||
|
values = new float[values_number];
|
|||
|
}
|
|||
|
public LSystemNodeLiteral(LSystemNodeLiteral other) {
|
|||
|
this.name = other.name;
|
|||
|
this.values_number = other.values_number;
|
|||
|
//in case it would be 0
|
|||
|
values = new float[this.values_number];
|
|||
|
other.values.CopyTo(values, 0);
|
|||
|
}
|
|||
|
|
|||
|
public static bool operator ==(LSystemNodeLiteral thisLiteral, LSystemNodeLiteral other) {
|
|||
|
return thisLiteral.name == other.name && thisLiteral.values_number == other.values_number;
|
|||
|
}
|
|||
|
public static bool operator !=(LSystemNodeLiteral thisLiteral, LSystemNodeLiteral other) {
|
|||
|
return !(thisLiteral.name == other.name && thisLiteral.values_number == other.values_number);
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString() {
|
|||
|
if (values_number == 0) {
|
|||
|
return name;
|
|||
|
}
|
|||
|
else {
|
|||
|
StringBuilder sb = new StringBuilder(name, name.Length + values_number * 7 + 4);
|
|||
|
sb.Append("(");
|
|||
|
for (int i = 0; i < values_number; i++) {
|
|||
|
var v = values[i];
|
|||
|
sb.AppendFormat("{0:0.##}", v);
|
|||
|
if (i < values_number - 1) {
|
|||
|
sb.Append(",");
|
|||
|
}
|
|||
|
}
|
|||
|
sb.Append(")");
|
|||
|
return sb.ToString();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class LSystemNode {
|
|||
|
public LSystemNodeLiteral literal { get; set; }
|
|||
|
public List<LSystemNode> children { get; set; }
|
|||
|
public LSystemNode mainChild { get; set; }
|
|||
|
|
|||
|
private LSystemNode _parent;
|
|||
|
public LSystemNode parent {
|
|||
|
get { if (_parent is null) { return new LSystemNode(new LSystemNodeLiteral(" _ ", 0)); }
|
|||
|
else { return _parent; } }
|
|||
|
set { _parent = value; } }
|
|||
|
|
|||
|
public LSystemNode(LSystemNodeLiteral nodeLiteral) {
|
|||
|
literal = nodeLiteral;
|
|||
|
children = new List<LSystemNode>();
|
|||
|
mainChild = null;
|
|||
|
}
|
|||
|
|
|||
|
public LSystemNode(LSystemNodeLiteral nodeLiteral, List<LSystemNode> children, LSystemNode mainChild) {
|
|||
|
literal = nodeLiteral;
|
|||
|
this.children = children;
|
|||
|
this.mainChild = mainChild;
|
|||
|
}
|
|||
|
public LSystemNode(LSystemNodeLiteral nodeLiteral, List<LSystemNode> children) {
|
|||
|
literal = nodeLiteral;
|
|||
|
this.children = children;
|
|||
|
this.mainChild = null;
|
|||
|
}
|
|||
|
public List<LSystemNode> getAllChildren() {
|
|||
|
var result = new List<LSystemNode>(children);
|
|||
|
if (mainChild != null){
|
|||
|
result.Add(mainChild);
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public LSystemNode deep_copy() {
|
|||
|
if (children.Count() == 0 && mainChild == null) {
|
|||
|
return new LSystemNode(new LSystemNodeLiteral(literal));
|
|||
|
}
|
|||
|
else if (mainChild != null) {
|
|||
|
var result = new LSystemNode(new LSystemNodeLiteral(literal));
|
|||
|
result.mainChild = mainChild.deep_copy();
|
|||
|
return result;
|
|||
|
}
|
|||
|
else {
|
|||
|
var new_children = new List<LSystemNode>();
|
|||
|
foreach (var x in children) {
|
|||
|
new_children.Add(x.deep_copy());
|
|||
|
}
|
|||
|
return new LSystemNode(literal, new_children, this.mainChild.deep_copy());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static LSystemNode deepestNode(LSystemNode node) {
|
|||
|
while (node.mainChild != null) {
|
|||
|
node = node.mainChild;
|
|||
|
}
|
|||
|
return node;
|
|||
|
}
|
|||
|
|
|||
|
public LSystemNode newParent() {
|
|||
|
return deepestNode(this);
|
|||
|
}
|
|||
|
|
|||
|
public override string ToString() {
|
|||
|
StringBuilder sb = new StringBuilder(literal.ToString());
|
|||
|
var node = this;
|
|||
|
while (true) {
|
|||
|
foreach (var child in node.children) {
|
|||
|
sb.Append("[");
|
|||
|
sb.Append(child.ToString());
|
|||
|
sb.Append("]");
|
|||
|
}
|
|||
|
if (node.mainChild != null) {
|
|||
|
sb.Append(node.mainChild.literal.ToString());
|
|||
|
node = node.mainChild;
|
|||
|
}
|
|||
|
else {
|
|||
|
return sb.ToString();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public class LSystemEvaluator {
|
|||
|
public LSystemNode lSystemString { get; set; }
|
|||
|
public List<LSystemRule> lSystemRules { get; set; }
|
|||
|
|
|||
|
public LSystemEvaluator(LSystemNode startingString, List<LSystemRule> rules) {
|
|||
|
lSystemString = startingString;
|
|||
|
lSystemRules = rules;
|
|||
|
}
|
|||
|
private LSystemNode _rewrite(LSystemNode node) {
|
|||
|
foreach (var rule in lSystemRules) {
|
|||
|
if (rule.is_aplicable(node)) {
|
|||
|
return rule.rewrite(node);
|
|||
|
}
|
|||
|
}
|
|||
|
return new LSystemNode(node.literal);
|
|||
|
}
|
|||
|
//private void _rewrite_recursive(LSystemNode node, LSystemNode parent) {
|
|||
|
// var new_node = _rewrite(node);
|
|||
|
// parent.children.Add(new_node);
|
|||
|
// new_node.parent = parent;
|
|||
|
// var new_parent = new_node.newParent();
|
|||
|
|
|||
|
// foreach (var child in node.children) {
|
|||
|
// _rewrite_recursive(child, new_parent);
|
|||
|
// }
|
|||
|
//}
|
|||
|
|
|||
|
|
|||
|
private void _rewrite_recursive(LSystemNode node, LSystemNode parent) {
|
|||
|
var new_node = _rewrite(node);
|
|||
|
parent.children.Add(new_node);
|
|||
|
new_node.parent = parent;
|
|||
|
var new_parent = new_node.newParent();
|
|||
|
|
|||
|
foreach (var child in node.children) {
|
|||
|
_rewrite_recursive(child, new_parent);
|
|||
|
}
|
|||
|
while (node.mainChild != null) {
|
|||
|
new_node = _rewrite(node.mainChild);
|
|||
|
new_node.parent = new_parent;
|
|||
|
|
|||
|
new_parent.mainChild = new_node;
|
|||
|
new_parent = new_node.newParent();
|
|||
|
foreach (var child in node.mainChild.children) {
|
|||
|
_rewrite_recursive(child, new_parent);
|
|||
|
}
|
|||
|
node = node.mainChild;
|
|||
|
}
|
|||
|
}
|
|||
|
public void rewrite() {
|
|||
|
var new_root = _rewrite(lSystemString);
|
|||
|
var new_parent = new_root.newParent();
|
|||
|
foreach (var child in lSystemString.children) {
|
|||
|
_rewrite_recursive(child, new_parent);
|
|||
|
}
|
|||
|
var node = lSystemString;
|
|||
|
|
|||
|
while (node.mainChild != null) {
|
|||
|
var new_node = _rewrite(node.mainChild);
|
|||
|
new_node.parent = new_parent;
|
|||
|
|
|||
|
new_parent.mainChild = new_node;
|
|||
|
new_parent = new_node.newParent();
|
|||
|
foreach (var child in node.mainChild.children) {
|
|||
|
_rewrite_recursive(child, new_parent);
|
|||
|
}
|
|||
|
node = node.mainChild;
|
|||
|
}
|
|||
|
lSystemString = new_root;
|
|||
|
}
|
|||
|
//private void rewrite(ref LSystemNode currentNode)
|
|||
|
}
|
|||
|
//abstract class LSystemWordParser { }
|
|||
|
//abstract class LSystemRulesParser { }
|
|||
|
|
|||
|
class A {
|
|||
|
public int B { get; set; }
|
|||
|
public A[] AA { get; set; }
|
|||
|
}
|
|||
|
class Program {
|
|||
|
static void runParametric() {
|
|||
|
|
|||
|
Dictionary<string, int> variableIndex = new Dictionary<string, int> {
|
|||
|
{"a", 0},
|
|||
|
{"b", 1},
|
|||
|
|
|||
|
};
|
|||
|
var predecesor1 = LSystemFileParser.parsePredecesor("B(a,b)");
|
|||
|
var predecesor2 = LSystemFileParser.parsePredecesor("A(a)");
|
|||
|
var condition1 = MathExpressionComparasionParser.parse(variableIndex, "a>b");
|
|||
|
var condition2 = MathExpressionComparasionParser.parse(variableIndex, "a>5");
|
|||
|
|
|||
|
var builder = new LSystemWordGeneratorBuilder(variableIndex);
|
|||
|
|
|||
|
var consequent1 = (LSystemNodeGenerator)LSystemFileParser.parseWord("B(0,b)[A(a/2)]A(a/2)", builder);
|
|||
|
var consequent2 = (LSystemNodeGenerator)LSystemFileParser.parseWord("B(a+3.5,b+1)", builder);
|
|||
|
var consequent3 = (LSystemNodeGenerator)LSystemFileParser.parseWord("B(0,a)", builder);
|
|||
|
var consequent4 = (LSystemNodeGenerator)LSystemFileParser.parseWord("A(a+1)", builder);
|
|||
|
|
|||
|
var rule1 = new LSystemRuleParametric(predecesor1, new MathExpressionComparison[] { condition1 }, consequent1 );
|
|||
|
var rule2 = new LSystemRuleParametric(predecesor1, new MathExpressionComparison[] { }, consequent2 );
|
|||
|
var rule3 = new LSystemRuleParametric(predecesor2, new MathExpressionComparison[] { condition2 }, consequent3 );
|
|||
|
var rule4 = new LSystemRuleParametric(predecesor2, new MathExpressionComparison[] { }, consequent4);
|
|||
|
|
|||
|
var axiom = LSystemFileParser.parseWord("A(6)", new LSystemWordBuilder());
|
|||
|
|
|||
|
var rules = new List<LSystemRule> { rule1, rule2, rule3, rule4 };
|
|||
|
var evaluator = new LSystemEvaluator(axiom, rules);
|
|||
|
Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
for (int i = 0; i < 20; i++) {
|
|||
|
evaluator.rewrite();
|
|||
|
Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
static void runContext() {
|
|||
|
var axiom = LSystemFileParser.parseWord("A(1)A(1)A(1)A(1)A(1)A(1)B(2)", new LSystemWordBuilder());
|
|||
|
var predecesor = LSystemFileParser.parsePredecesor("A(a)");
|
|||
|
var predecesor1 = LSystemFileParser.parsePredecesor("B(b)");
|
|||
|
|
|||
|
var contex = new LSystemContext();
|
|||
|
contex.setOnlySucceeding(new LSystemNodeLiteral("B", 1));
|
|||
|
|
|||
|
var contex1 = new LSystemContext();
|
|||
|
contex1.setOnlyPreceding(new LSystemNodeLiteral("A", 1));
|
|||
|
|
|||
|
|
|||
|
Dictionary<string, int> variableIndex = new Dictionary<string, int> {
|
|||
|
{ "a", 0 },
|
|||
|
{ "b", 1 },
|
|||
|
};
|
|||
|
var builder = new LSystemWordGeneratorBuilder(variableIndex);
|
|||
|
var consequent = (LSystemNodeGenerator)LSystemFileParser.parseWord("B(a)", builder);
|
|||
|
var consequent1 = (LSystemNodeGenerator)LSystemFileParser.parseWord("A(1)", builder);
|
|||
|
var consequent2 = (LSystemNodeGenerator)LSystemFileParser.parseWord("A(a+1)", builder);
|
|||
|
|
|||
|
MathExpressionComparison comparison = MathExpressionComparasionParser.parse(variableIndex, "a>b");
|
|||
|
MathExpressionComparison comparison1 = MathExpressionComparasionParser.parse(variableIndex, "a<=b");
|
|||
|
|
|||
|
var rule = new LSystemRuleParametricStochasticContext(predecesor, new MathExpressionComparison[] { comparison }, consequent, contex);
|
|||
|
var rule1 = new LSystemRuleParametricStochasticContext(predecesor, new MathExpressionComparison[] { }, consequent2, contex);
|
|||
|
var rule2 = new LSystemRuleParametricStochasticContext(predecesor1, new MathExpressionComparison[] { comparison }, consequent1, contex1);
|
|||
|
|
|||
|
|
|||
|
var rules = new List<LSystemRule> { rule, rule1, rule2 };
|
|||
|
var evaluator = new LSystemEvaluator(axiom, rules);
|
|||
|
Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
for (int i = 0; i < 20; i++) {
|
|||
|
evaluator.rewrite();
|
|||
|
Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
static void runFile() {
|
|||
|
Console.WriteLine("Enter filepath:");
|
|||
|
string filepath = Console.ReadLine();
|
|||
|
var evaluator = LSystemFileParser.parseLSystem(new StreamReader(filepath));
|
|||
|
Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
while (true) {
|
|||
|
Console.ReadLine();
|
|||
|
evaluator.rewrite();
|
|||
|
Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
static void Main(string[] args) {
|
|||
|
runFile();
|
|||
|
//runContext();
|
|||
|
//var Al = new LSystemNodeLiteral("Al", 0);
|
|||
|
//var Ar = new LSystemNodeLiteral("Ar", 0);
|
|||
|
//var Bl = new LSystemNodeLiteral("Bl", 0);
|
|||
|
//var Br = new LSystemNodeLiteral("Br", 0);
|
|||
|
|
|||
|
//var root = new LSystemNode(Ar);
|
|||
|
//var rule_list = new List<LSystemRule>();
|
|||
|
|
|||
|
//var result = new LSystemNode(Al);
|
|||
|
//result.children.Add(new LSystemNode(Br));
|
|||
|
|
|||
|
//rule_list.Add(new LSystemRuleBasic(Ar, result));
|
|||
|
|
|||
|
//result = new LSystemNode(Bl);
|
|||
|
//result.children.Add(new LSystemNode(Ar));
|
|||
|
//rule_list.Add(new LSystemRuleBasic(Al, result));
|
|||
|
|
|||
|
//result = new LSystemNode(Ar);
|
|||
|
//rule_list.Add(new LSystemRuleBasic(Br, result));
|
|||
|
|
|||
|
//result = new LSystemNode(Al);
|
|||
|
//rule_list.Add(new LSystemRuleBasic(Bl, result));
|
|||
|
|
|||
|
|
|||
|
//var evaluator = new LSystemEvaluator(root, rule_list);
|
|||
|
//for (int i=0; i < 5; i++) {
|
|||
|
// Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
// evaluator.rewrite();
|
|||
|
//}
|
|||
|
//Console.WriteLine(evaluator.lSystemString.ToString());
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//var node = LSystemFileParser.parseWord("A[AA][A]AB(1,2)[A(1)]C", new LSystemWordBuilder());
|
|||
|
//Console.WriteLine(node.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|