This page was generated from
doc/rotation/end-conditions-natural.ipynb.
Interactive online version:
.
“Natural” End Conditions§
notebook about “natural” end conditions for Euclidean splines
[1]:
import numpy as np
[2]:
from helper import angles2quat, animate_rotations, display_animation
splines.quaternion.DeCasteljau
[3]:
from splines.quaternion import DeCasteljau
[4]:
def calculate_rotations(control_quaternions):
times = np.linspace(0, 1, 50)
return DeCasteljau(
segments=[control_quaternions],
).evaluate(times)
[5]:
q0 = angles2quat(45, 0, 0)
q1 = angles2quat(-45, 0, 0)
Begin§
[6]:
def natural_begin(begin, end_control, end):
"""Return second control quaternion given the other three."""
return (
(end_control * end.inverse()) *
(end * begin.inverse())
)**(1 / 2) * begin
[7]:
q1_control = angles2quat(-45, 0, -90)
[8]:
ani = animate_rotations({
'natural begin': calculate_rotations(
[q0, natural_begin(q0, q1_control, q1), q1_control, q1]),
}, figsize=(4, 3))
[9]:
display_animation(ani, default_mode='reflect')
End§
[10]:
def natural_end(begin, begin_control, end):
"""Return third control quaternion given the other three."""
return (
end.inverse() *
(
(end * begin.inverse()) *
(begin * begin_control.inverse())
)**(1 / 2)).inverse()
[11]:
q0_control = angles2quat(45, 0, 90)
[12]:
ani = animate_rotations({
'natural end': calculate_rotations(
[q0, q0_control, natural_end(q0, q0_control, q1), q1]),
}, figsize=(4, 3))
[13]:
display_animation(ani, default_mode='reflect')
(Non-)Symmetries§
Instead of using the function for the begin condition, we could of course also reverse the control quaternions, use the function for the end condition and time-reverse the result. And vice-versa.
Let’s make sure that works:
[14]:
ani = animate_rotations({
'natural end': calculate_rotations(
[q0, q0_control, natural_end(q0, q0_control, q1), q1]),
'natural begin, time-reversed': calculate_rotations(
[q1, natural_begin(q1, q0_control, q0), q0_control, q0])[::-1],
}, figsize=(6, 3))
[15]:
display_animation(ani, default_mode='reflect')
[16]:
begin = natural_begin(q0, q1_control, q1)
[17]:
ani = animate_rotations({
'natural begin': calculate_rotations(
[q0, begin, q1_control, q1]),
'natural end from natural begin': calculate_rotations(
[q0, begin, natural_end(q0, begin, q1), q1]),
}, figsize=(6, 3))
[18]:
display_animation(ani, default_mode='reflect')
[19]:
end = natural_end(q0, q0_control, q1)
[20]:
ani = animate_rotations({
'natural end': calculate_rotations(
[q0, q0_control, end, q1]),
'natural begin from natural end': calculate_rotations(
[q0, natural_begin(q0, end, q1), end, q1]),
}, figsize=(6, 3))
[21]:
display_animation(ani, default_mode='reflect')
[ ]: