python-lottie  0.7.0+dev66cafb9
A framework to work with lottie files and telegram animated stickers (tgs)
ik.py
Go to the documentation of this file.
1 from ..nvector import NVector
2 
3 
4 # FABRIK
5 class Chain:
6  def __init__(self, tail, fixed_tail=True, tolerance=0.5, max_iter=8):
7  self.jointsjoints = [tail.clone()]
8  self.fixed_tailfixed_tail = fixed_tail
9  self.lengthslengths = []
10  self.total_lengthtotal_length = 0
11  self.tolerancetolerance = tolerance
12  self.max_itermax_iter = max_iter
13 
14  def add_joint(self, point):
15  length = (point - self.jointsjoints[-1]).length
16  self.lengthslengths.append(length)
17  self.total_lengthtotal_length += length
18  self.jointsjoints.append(point.clone())
19 
20  def add_joints(self, head, n):
21  delta = head - self.jointsjoints[-1]
22  self.total_lengthtotal_length += delta.length
23  segment = delta / n
24  seglen = segment.length
25  for i in range(n):
26  self.lengthslengths.append(seglen)
27  self.jointsjoints.append(self.jointsjoints[-1] + segment)
28 
29  def backward(self, target):
30  """!
31  target -> -> start
32  """
33  self.jointsjoints[-1] = target
34  for i in range(len(self.jointsjoints)-2, -1, -1):
35  r = self.jointsjoints[i+1] - self.jointsjoints[i]
36  l = self.lengthslengths[i] / r.length
37  self.jointsjoints[i] = self.jointsjoints[i+1].lerp(self.jointsjoints[i], l)
38 
39  def forward(self, target):
40  """!
41  start -> -> tail
42  """
43  self.jointsjoints[0] = target
44  for i in range(0, len(self.jointsjoints)-1):
45  r = self.jointsjoints[i+1] - self.jointsjoints[i]
46  l = self.lengthslengths[i] / r.length
47  self.jointsjoints[i+1] = self.jointsjoints[i].lerp(self.jointsjoints[i+1], l)
48 
49  def reach(self, target):
50  if not self.fixed_tailfixed_tail:
51  self.backwardbackward(target)
52  return
53 
54  distance = (target - self.jointsjoints[0]).length
55  if distance >= self.total_lengthtotal_length:
56  for i in range(len(self.jointsjoints)-1):
57  r = target - self.jointsjoints[i]
58  l = self.lengthslengths[i] / r.length
59  self.jointsjoints[i+1] = self.jointsjoints[i].lerp(target, l)
60  return
61 
62  base = self.jointsjoints[0]
63 
64  distance = (target - self.jointsjoints[-1]).length
65  n_it = 0
66  while distance > self.tolerancetolerance and n_it < self.max_itermax_iter:
67  self.backwardbackward(target)
68  self.forwardforward(base)
69  distance = (target - self.jointsjoints[-1]).length
70  n_it += 1
71 
72 
73 class Octopus:
74  def __init__(self, master):
75  self.chainschains = {"master": master}
76  self.mastermaster = master
77 
78  @property
79  def base(self):
80  return self.mastermaster.joints[-1]
81 
82  def add_chain(self, name):
83  ch = Chain(self.basebase)
84  self.chainschains[name] = ch
85  return ch
86 
87  def reach(self, target_map):
88  centroid = NVector(0, 0)
89  for chain, target in target_map.items():
90  self.chainschains[chain].backward(target)
91  centroid += self.chainschains[chain].joints[0]
92  centroid /= len(target_map)
93 
94  self.mastermaster.reach(centroid)
95 
96  for chain in target_map.keys():
97  self.chainschains[chain].forward(self.basebase)
def backward(self, target)
target -> -> start
Definition: ik.py:29
def forward(self, target)
start -> -> tail
Definition: ik.py:39
def __init__(self, tail, fixed_tail=True, tolerance=0.5, max_iter=8)
Definition: ik.py:6
def add_joints(self, head, n)
Definition: ik.py:20
def reach(self, target)
Definition: ik.py:49
def add_joint(self, point)
Definition: ik.py:14
def base(self)
Definition: ik.py:79
def __init__(self, master)
Definition: ik.py:74
def reach(self, target_map)
Definition: ik.py:87
def add_chain(self, name)
Definition: ik.py:82