forked from martinventer/virtual_creatures
-
Notifications
You must be signed in to change notification settings - Fork 1
/
CreatureTools2.py
104 lines (85 loc) · 3 KB
/
CreatureTools2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import numpy as np
from shapely.geometry import LineString
from math import radians, cos, sin, pi
import re
class Creature:
"""
Generates a complete virtual creature
Tests
-----------
"""
def __init__(self, params):
"""
Initialises a simple L-system
Parameters
----------
variables : str
a string containing all of the letters that take part in the
recursion. These letters should also have associated rules.
constants : str or None
a string containing all the letters that do not take part in the
recursion. These letters will not have an associated rule
axiom : str
The initial character string
rules : dict
a dictionary containing the rules for recursion. This is a
dictionary of listing the letter replacement in the recursion.
eg.
{"A": "AB",
"B": "A"}
"""
if not 'L-string' in params:
self.rules = params.get('rules')
self.l_string = params.get('axiom')
self.constants = params.get('constants')
self.variables = params.get('variables')
self.recur(params.get('num_char'))
else:
self.l_string = params.get('L-string')
self.length = params.get('length')
self.angle = radians(params.get('angle'))
self.mapper()
self.layout()
def recur(self, n):
for _ in range(n):
self.l_string = ''.join([self.next_char(c) for c in self.l_string])
self.l_string = self.l_string.replace('X', '')
def next_char(self, c):
rule = self.rules.get(c, c)
if len(rule) > 1:
return np.random.choice(self.rules.get(c, ["Other"])["options"],
p=self.rules.get(c, ["Other"])[
"probabilities"])
else:
return rule
def mapper(self):
"""Converts L-string to coordinates
Returns
-------
List
List of coordinates
"""
num_chars = len(self.l_string)
coords = np.zeros((num_chars + 1, 3), np.double)
rotVec = np.array((
(cos(self.angle), -sin(self.angle), 0),
(sin(self.angle), cos(self.angle), 0),
(0, 0, 1)
))
start_vec = np.array((0, 1, 0), np.float64)
curr_vec = start_vec
i = 1
for c in self.l_string:
if c == 'F':
coords[i] = (coords[i-1] + (self.length * curr_vec))
i += 1
if c == '-':
curr_vec = np.dot(curr_vec, (-1*rotVec))
if c == '+':
curr_vec = np.dot(curr_vec, rotVec)
coords = np.delete(coords, np.s_[i:], 0)
self.coords = coords
def layout(self):
self.linestring = LineString(self.coords[:, :2])
self.area = self.linestring.buffer(0.499999).area
self.bounds = self.linestring.bounds