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 varable_index = new Dictionary<string, int>();
if (line.Length > 1) {
foreach (var i in line.Substring(2, line.Length - 3).Split(',').Select((_name, Index) => new { _name, Index })) {
varable_index.Add(i._name, i.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);
};
}
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) {
string line;
int line_number = 0;
var ignored = new String[0];
LSystemNode axiom = null;
List<LSystemRule> rules = null;
while ((line = sr.ReadLine()) != null) {
@ -155,12 +161,15 @@ namespace ConsoleLSystem {
}
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") {
rules = parseLSystemRules(sr);
}
}
return new LSystemEvaluator(axiom, rules);
return new LSystemEvaluator(axiom, rules, ignored);
}
private static List<LSystemRule> parseLSystemRules(StreamReader sr) {

View File

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

View File

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

View File

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

View File

@ -77,7 +77,14 @@ abstract public class TurtleLSystem : MonoBehaviour
Debug.Log(evaluator.lSystemString.ToString());
}
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.tag = "LSystemLiteral";
instance.transform.parent = this.gameObject.transform;