-
Notifications
You must be signed in to change notification settings - Fork 49
/
hermit3.go
126 lines (100 loc) · 2.85 KB
/
hermit3.go
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Package hermit3 contains functions for 3D cubic hermit splines.
// See: http://en.wikipedia.org/wiki/Cubic_Hermite_spline
package hermit
import (
"fmt"
"github.com/ungerik/go3d/float64/vec3"
)
// PointTangent contains a point and a tangent at that point.
// This is a helper sub-struct for T.
type PointTangent struct {
Point vec3.T
Tangent vec3.T
}
// T holds the data to define a hermit spline.
type T struct {
A PointTangent
B PointTangent
}
// Parse parses T from a string. See also String()
func Parse(s string) (r T, err error) {
_, err = fmt.Sscan(s,
&r.A.Point[0], &r.A.Point[1], &r.A.Point[2],
&r.A.Tangent[0], &r.A.Tangent[1], &r.A.Tangent[2],
&r.B.Point[0], &r.B.Point[1], &r.B.Point[2],
&r.B.Tangent[0], &r.B.Tangent[1], &r.B.Tangent[2],
)
return r, err
}
// String formats T as string. See also Parse().
func (herm *T) String() string {
return fmt.Sprintf("%s %s %s %s",
herm.A.Point.String(), herm.A.Tangent.String(),
herm.B.Point.String(), herm.B.Tangent.String(),
)
}
// Point returns a point on a hermit spline at t (0,1).
func (herm *T) Point(t float64) vec3.T {
return Point(&herm.A.Point, &herm.A.Tangent, &herm.B.Point, &herm.B.Tangent, t)
}
// Tangent returns a tangent on a hermit spline at t (0,1).
func (herm *T) Tangent(t float64) vec3.T {
return Tangent(&herm.A.Point, &herm.A.Tangent, &herm.B.Point, &herm.B.Tangent, t)
}
// Length returns the length of a hermit spline from A.Point to t (0,1).
func (herm *T) Length(t float64) float64 {
return Length(&herm.A.Point, &herm.A.Tangent, &herm.B.Point, &herm.B.Tangent, t)
}
// Point returns a point on a hermit spline at t (0,1).
func Point(pointA, tangentA, pointB, tangentB *vec3.T, t float64) vec3.T {
t2 := t * t
t3 := t2 * t
f := 2*t3 - 3*t2 + 1
result := pointA.Scaled(f)
f = t3 - 2*t2 + t
tAf := tangentA.Scaled(f)
result.Add(&tAf)
f = t3 - t2
tBf := tangentB.Scaled(f)
result.Add(&tBf)
f = -2*t3 + 3*t2
pAf := pointB.Scaled(f)
result.Add(&pAf)
return result
}
// Tangent returns a tangent on a hermit spline at t (0,1).
func Tangent(pointA, tangentA, pointB, tangentB *vec3.T, t float64) vec3.T {
t2 := t * t
t3 := t2 * t
f := 2*t3 - 3*t2
result := pointA.Scaled(f)
f = t3 - 2*t2 + 1
tAf := tangentA.Scaled(f)
result.Add(&tAf)
f = t3 - t2
tBf := tangentB.Scaled(f)
result.Add(&tBf)
f = -2*t3 + 3*t2
pAf := pointB.Scaled(f)
result.Add(&pAf)
return result
}
// Length returns the length of a hermit spline from pointA to t (0,1).
func Length(pointA, tangentA, pointB, tangentB *vec3.T, t float64) float64 {
sqrT := t * t
t1 := sqrT * 0.5
t2 := sqrT * t * 1.0 / 3.0
t3 := sqrT*sqrT + 1.0/4.0
f := 2*t3 - 3*t2 + t
result := pointA.Scaled(f)
f = t3 - 2*t2 + t1
tAf := tangentA.Scaled(f)
result.Add(&tAf)
f = t3 - t2
tBf := tangentB.Scaled(f)
result.Add(&tBf)
f = -2*t3 + 3*t2
pBf := pointB.Scaled(f)
result.Add(&pBf)
return result.Length()
}