This commit is contained in:
fingal 2021-03-26 21:33:33 +01:00
parent 81c6814e16
commit 307a9c9324
5 changed files with 80 additions and 26 deletions

View File

@ -134,16 +134,22 @@ namespace ConsoleLSystem {
var name = line.Substring(0, 1); var name = line.Substring(0, 1);
var varable_index = new Dictionary<string, int>(); var varable_index = new Dictionary<string, int>();
if (line.Length > 1) { if (line.Length > 1) {
foreach (var i in line.Substring(2, line.Length - 3).Split(',').Select((_name, Index) => new { _name, Index })) { foreach (var i in line.Substring(2, line.Length - 3).Split(',').Select((name, Index) => new { name, Index })) {
varable_index.Add(i._name, i.Index); varable_index.Add(i.name, i.Index);
}; };
} }
return new LSystemNodeLiteralVariable(name, varable_index.Count, varable_index); return new LSystemNodeLiteralVariable(name, varable_index.Count, varable_index);
} }
//private static String[] parseIgnore(string line) {
// var items = line.Trim().Split(' ');
// var resut = List
//}
public static LSystemEvaluator parseLSystem(StreamReader sr) { public static LSystemEvaluator parseLSystem(StreamReader sr) {
string line; string line;
int line_number = 0; int line_number = 0;
var ignored = new String[0];
LSystemNode axiom = null; LSystemNode axiom = null;
List<LSystemRule> rules = null; List<LSystemRule> rules = null;
while ((line = sr.ReadLine()) != null) { while ((line = sr.ReadLine()) != null) {
@ -155,12 +161,15 @@ namespace ConsoleLSystem {
} }
axiom = parseWord(line,new LSystemWordBuilder()); axiom = parseWord(line,new LSystemWordBuilder());
} }
if (line.Trim().Split(' ')[0].Trim() == "#ignore") {
ignored = line.Trim().Split(' ').Where(x=> x!= "#ignore" && x.Length>0).Select(x => x.Trim()).ToArray();
}
if (line.Trim() == "#rules") { if (line.Trim() == "#rules") {
rules = parseLSystemRules(sr); rules = parseLSystemRules(sr);
} }
} }
return new LSystemEvaluator(axiom, rules); return new LSystemEvaluator(axiom, rules, ignored);
} }
private static List<LSystemRule> parseLSystemRules(StreamReader sr) { private static List<LSystemRule> parseLSystemRules(StreamReader sr) {

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
namespace ConsoleLSystem { namespace ConsoleLSystem {
@ -44,8 +45,8 @@ namespace ConsoleLSystem {
} }
abstract public class LSystemRule { abstract public class LSystemRule {
abstract public bool is_aplicable(LSystemNode processed_node); abstract public bool is_aplicable(LSystemNode processed_node, String[] ignored);
abstract public LSystemNode rewrite(LSystemNode processed_node); abstract public LSystemNode rewrite(LSystemNode processed_node, String[] ignored);
} }
public class LSystemRuleBasic : LSystemRule { public class LSystemRuleBasic : LSystemRule {
@ -57,7 +58,7 @@ namespace ConsoleLSystem {
this.output = output; this.output = output;
} }
override public bool is_aplicable(LSystemNode processed_node) { override public bool is_aplicable(LSystemNode processed_node, String[] ignored) {
if (processed_node.literal == input) { if (processed_node.literal == input) {
return true; return true;
} }
@ -65,8 +66,8 @@ namespace ConsoleLSystem {
return false; return false;
} }
} }
override public LSystemNode rewrite(LSystemNode processed_node) { override public LSystemNode rewrite(LSystemNode processed_node, String[] ignored) {
if (is_aplicable(processed_node)) { if (is_aplicable(processed_node, ignored)) {
return output.deep_copy(); return output.deep_copy();
} }
else { else {
@ -86,7 +87,7 @@ namespace ConsoleLSystem {
this.conditions = conditions; this.conditions = conditions;
} }
public override bool is_aplicable(LSystemNode processed_node) { 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) { if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) {
return false; return false;
} }
@ -98,8 +99,8 @@ namespace ConsoleLSystem {
return true; return true;
} }
public override LSystemNode rewrite(LSystemNode processed_node) { public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored) {
if (is_aplicable(processed_node)) { if (is_aplicable(processed_node, ignored)) {
return consequent.eval(processed_node.literal.values); return consequent.eval(processed_node.literal.values);
} }
else { else {
@ -140,7 +141,7 @@ namespace ConsoleLSystem {
random = new Random(); random = new Random();
} }
public override bool is_aplicable(LSystemNode processed_node) { 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) { if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) {
return false; return false;
} }
@ -152,7 +153,7 @@ namespace ConsoleLSystem {
return true; return true;
} }
public override LSystemNode rewrite(LSystemNode processed_node) { public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored) {
var result = random.NextDouble(); var result = random.NextDouble();
int consequent_index = 0; int consequent_index = 0;
for (int i = 0; i < probabilities.Length; i++) { for (int i = 0; i < probabilities.Length; i++) {
@ -161,7 +162,7 @@ namespace ConsoleLSystem {
break; break;
} }
} }
if (is_aplicable(processed_node)) { if (is_aplicable(processed_node, ignored)) {
return consequents[consequent_index].eval(processed_node.literal.values); return consequents[consequent_index].eval(processed_node.literal.values);
} }
else { else {
@ -196,20 +197,28 @@ namespace ConsoleLSystem {
this.isPreceding = false; this.isPreceding = false;
this.isSucceeding = true; this.isSucceeding = true;
} }
public bool isAplicable(LSystemNode node,out float[] variables) { public bool isAplicable(LSystemNode node, String[] ignored, out float[] variables) {
var variables_list = new List<float>(); var variables_list = new List<float>();
if (isPreceding && parent != node.parent.literal) { var currentParent = node.parent;
while (ignored.Contains(currentParent.literal.name)) {
currentParent = currentParent.parent;
}
if (isPreceding && parent != currentParent.literal) {
variables = new float[0]; variables = new float[0];
return false; return false;
} }
if (isPreceding) { if (isPreceding) {
variables_list.AddRange(node.parent.literal.values); variables_list.AddRange(currentParent.literal.values);
} }
variables_list.AddRange(node.literal.values); variables_list.AddRange(node.literal.values);
if (isSucceeding) { if (isSucceeding) {
var result = false; var result = false;
LSystemNodeLiteral childLiteral; LSystemNodeLiteral childLiteral;
Queue<LSystemNode> ignoredChildren = new Queue<LSystemNode>();
foreach(var child in node.getAllChildren()) { foreach(var child in node.getAllChildren()) {
if (ignored.Contains(child.literal.name)) {
ignoredChildren.Enqueue(child);
}
if (child.literal == this.child) { if (child.literal == this.child) {
childLiteral = child.literal; childLiteral = child.literal;
result = true; result = true;
@ -217,6 +226,20 @@ namespace ConsoleLSystem {
break; 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) { if (!result) {
variables = new float[0]; variables = new float[0];
return false; return false;
@ -237,12 +260,12 @@ namespace ConsoleLSystem {
public LSystemRuleParametricStochasticContext(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent, LSystemContext context) : base(predecesor, conditions, consequent) { public LSystemRuleParametricStochasticContext(LSystemNodeLiteralVariable predecesor, MathExpressionComparison[] conditions, LSystemNodeGenerator consequent, LSystemContext context) : base(predecesor, conditions, consequent) {
this.context = context; this.context = context;
} }
public override bool is_aplicable(LSystemNode processed_node) { 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) { if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) {
return false; return false;
} }
var variables = new float[0]; var variables = new float[0];
if (!context.isAplicable(processed_node, out variables)) { if (!context.isAplicable(processed_node, ignored, out variables)) {
return false; return false;
} }
foreach (var condition in conditions) { foreach (var condition in conditions) {
@ -252,12 +275,12 @@ namespace ConsoleLSystem {
} }
return true; return true;
} }
bool is_aplicable(LSystemNode processed_node, out float[] variables) { bool is_aplicable(LSystemNode processed_node, String[] ignored, out float[] variables) {
variables = new float[0]; variables = new float[0];
if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) { if (processed_node.literal.name != predecesor.name || processed_node.literal.values_number != predecesor.values_number) {
return false; return false;
} }
if (!context.isAplicable(processed_node, out variables)) { if (!context.isAplicable(processed_node, ignored, out variables)) {
return false; return false;
} }
foreach (var condition in conditions) { foreach (var condition in conditions) {
@ -268,16 +291,17 @@ namespace ConsoleLSystem {
return true; return true;
} }
public override LSystemNode rewrite(LSystemNode processed_node) { public override LSystemNode rewrite(LSystemNode processed_node, String[] ignored) {
var result = random.NextDouble(); var result = random.NextDouble();
int consequent_index = 0; int consequent_index = 0;
for (int i = 0; i < probabilities.Length; i++) { for (int i = 0; i < probabilities.Length; i++) {
if (result < probabilities[i]) { if (result < probabilities[i]) {
consequent_index = i; consequent_index = i;
break;
} }
} }
float[] variables; float[] variables;
if (is_aplicable(processed_node, out variables)) { if (is_aplicable(processed_node, ignored, out variables)) {
return consequents[consequent_index].eval(variables); return consequents[consequent_index].eval(variables);
} }
else { else {

View File

@ -39,6 +39,7 @@ namespace ConsoleLSystem {
private static Random random = new Random(); private static Random random = new Random();
private static Dictionary<char, int> expression_hierarchy = new Dictionary<char, int>{ private static Dictionary<char, int> expression_hierarchy = new Dictionary<char, int>{
{'^', 4},
{'*', 3}, {'*', 3},
{'/', 3}, {'/', 3},
{'+', 1}, {'+', 1},
@ -54,6 +55,9 @@ namespace ConsoleLSystem {
private static float mulitply(float[] children, float[] variables) { private static float mulitply(float[] children, float[] variables) {
return children[0] * children[1]; return children[0] * children[1];
} }
private static float power(float[] children, float[] variables) {
return (float)Math.Pow(children[0],children[1]);
}
private static float divide(float[] children, float[] variables) { private static float divide(float[] children, float[] variables) {
return children[0] / children[1]; return children[0] / children[1];
} }
@ -135,6 +139,9 @@ namespace ConsoleLSystem {
case '-': case '-':
return new MathExpressionNode(subtract, child_nodes); return new MathExpressionNode(subtract, child_nodes);
break; break;
case '^':
return new MathExpressionNode(power, child_nodes);
break;
default: default:
throw new Exception(String.Format("unknown operation {0} in {1}", expression_string[expression_pos], expression_string)); throw new Exception(String.Format("unknown operation {0} in {1}", expression_string[expression_pos], expression_string));
break; break;

View File

@ -141,15 +141,22 @@ namespace ConsoleLSystem {
public class LSystemEvaluator { public class LSystemEvaluator {
public LSystemNode lSystemString { get; set; } public LSystemNode lSystemString { get; set; }
public List<LSystemRule> lSystemRules { get; set; } public List<LSystemRule> lSystemRules { get; set; }
public String[] ignored { get; set; }
public LSystemEvaluator(LSystemNode startingString, List<LSystemRule> rules) { public LSystemEvaluator(LSystemNode startingString, List<LSystemRule> rules) {
lSystemString = startingString; lSystemString = startingString;
lSystemRules = rules; lSystemRules = rules;
ignored = new String[0];
}
public LSystemEvaluator(LSystemNode startingString, List<LSystemRule> rules, String[] ignored) {
lSystemString = startingString;
lSystemRules = rules;
this.ignored = ignored;
} }
private LSystemNode _rewrite(LSystemNode node) { private LSystemNode _rewrite(LSystemNode node) {
foreach (var rule in lSystemRules) { foreach (var rule in lSystemRules) {
if (rule.is_aplicable(node)) { if (rule.is_aplicable(node, ignored)) {
return rule.rewrite(node); return rule.rewrite(node, ignored);
} }
} }
return new LSystemNode(node.literal); return new LSystemNode(node.literal);

View File

@ -77,7 +77,14 @@ abstract public class TurtleLSystem : MonoBehaviour
Debug.Log(evaluator.lSystemString.ToString()); Debug.Log(evaluator.lSystemString.ToString());
} }
private GameObject prepeareGameObject(string name, GameObject gameObject,Matrix4x4 transformation) { private GameObject prepeareGameObject(string name, GameObject gameObject,Matrix4x4 transformation) {
var instance = Instantiate(gameObject); GameObject instance;
if (PrefabUtility.GetPrefabAssetType(gameObject) != PrefabAssetType.NotAPrefab) {
instance = Instantiate(gameObject);
}
else {
instance = gameObject;
}
instance.name = String.Format("LSystem Literal {0}", name); instance.name = String.Format("LSystem Literal {0}", name);
instance.tag = "LSystemLiteral"; instance.tag = "LSystemLiteral";
instance.transform.parent = this.gameObject.transform; instance.transform.parent = this.gameObject.transform;