bezier_curve 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +44 -0
- data/Rakefile +8 -0
- data/lib/bezier_curve/n_point.rb +46 -0
- data/lib/bezier_curve/version.rb +7 -0
- data/lib/bezier_curve.rb +151 -0
- data/test/test_bezier_curve.rb +104 -0
- data/test/test_n_point.rb +51 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7bdfef0208f447bf444392f207505bcf076d56db
|
4
|
+
data.tar.gz: fffe1353eca9734c7b1e5a8076a0da179bfd0435
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7b57e98d8ffcd9ac90b1d969e3728890bc654493d56006d8ec5a5d39f4386e6b6eb5252a6272bfc8c10511130b5bf7f0cbaedcfb8c62ae2779dedf9092119818
|
7
|
+
data.tar.gz: e8f69f9b96cb70bed85e8f70167247e33ecd26dd9536061c822b0773f4391b8f274303fc95958d1afc881b549d6c42c6f39d52a787fc15e615b8842bf16b6e8a
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# bezier_curve
|
2
|
+
A bézier curve library for Ruby, supporting n-dimensional, nth-degree curves
|
3
|
+
|
4
|
+
A rather simple and small library that should do pretty much anything you need to do with a bezier curve. It supports arbitrary numbers of dimensions, and arbitrary numbers of control points. Even still, it is pretty easy to use. Here's a simple quadratic (1st degree) bezier curve, in 2-dimensional space:
|
5
|
+
|
6
|
+
# create the curve
|
7
|
+
curve = BezierCurve.new([0,0],[0,1],[1,1])
|
8
|
+
# determine its points for drawing purposes
|
9
|
+
curve.points
|
10
|
+
[[0, 0], [0.00390625, 0.12109375], ... [0.87890625, 0.99609375], 1, 1]
|
11
|
+
|
12
|
+
When outputting points, it automatically chooses a suitable angle tolerance which would make the resulting poly-line appear relatively smooth (no angle changes more than about 3 degrees). But you can choose your own tolerance:
|
13
|
+
|
14
|
+
# Extreme precision, less than 1 degree tolerance
|
15
|
+
curve.points(tolerance: Math::PI/180)
|
16
|
+
# just give me 5 points, quick:
|
17
|
+
curve.points(count: 5)
|
18
|
+
|
19
|
+
You can easily split a curve into two, at a given value of `t`
|
20
|
+
|
21
|
+
# split the curve at its midpoint
|
22
|
+
curve.split_at(0.5)
|
23
|
+
#=> [BezierCurve([0, 0], [0.0, 0.5], [0.25, 0.75]), BezierCurve([0.25, 0.75], [0.5, 1.0], [1, 1])]
|
24
|
+
|
25
|
+
You can also specify n-dimensional curves:
|
26
|
+
|
27
|
+
# a 4-dimensional curve of 2nd order
|
28
|
+
curve = BezierCurve.new([0,0,0,0], [1,1,2,2], [4,5,9,3])
|
29
|
+
# get its points
|
30
|
+
curve.points(count:3)
|
31
|
+
#=> [[0.0, 0.0, 0.0, 0.0], [1.5, 1.75, 3.25, 1.75], [4.0, 5.0, 9.0, 3.0]]
|
32
|
+
|
33
|
+
You can also specify any degree/order of curve you like:
|
34
|
+
|
35
|
+
# 2d curve, 6th degree
|
36
|
+
curve = BezierCurve.new([0,0],[1,1],[2,-1],[3,1],[4,-1],[5,1],[6,-1])
|
37
|
+
curve.degree
|
38
|
+
#=> 6
|
39
|
+
curve.points.size
|
40
|
+
#=> 35
|
41
|
+
|
42
|
+
Note that the complexity goes up exponentially for higher degree curves, so performance may suffer if used extensively; but the capability is there if you need it. In fact, if you want, you can really slow things down and do a 18-dimensional curve of the 300th order. The sky is the limit. Well, your processor and memory are the limit, but you get the idea.
|
43
|
+
|
44
|
+
I am interested in making this the most useful ruby library for working with bezier curves. If you need help, or have a suggestion for improvement, feel free to file an issue on Github (https://github.com/marcuserronius/bezier_curve/), or contact me directly.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# bezier_curve/n_point.rb
|
2
|
+
|
3
|
+
# Extends an array to treat it as an n-dimensional point. Should not
|
4
|
+
# occlude any original Array methods
|
5
|
+
module NPoint
|
6
|
+
# calculates how far this point is from `other`
|
7
|
+
def dist_from(other)
|
8
|
+
raise "Dimension counts don't match! (%i and %i)" %[size,other.size] unless size == other.size
|
9
|
+
zip(other).map{|a,b|(a-b)**2}.inject{|a,b|a+b}**0.5
|
10
|
+
end
|
11
|
+
# calculates the angle formed by this point and two others
|
12
|
+
# in radians
|
13
|
+
def angle_to(a,b)
|
14
|
+
a,b = *[a,b].map(&:to_np)
|
15
|
+
d0,d1 = dist_from(a), a.dist_from(b)
|
16
|
+
z = self.to(a,1+d1/d0)
|
17
|
+
dz = z.dist_from(b)
|
18
|
+
Math.asin(dz/2/d1)*2
|
19
|
+
end
|
20
|
+
|
21
|
+
# calculates the new point on the vector of self->other, scaled by `t`.
|
22
|
+
# t=0 returns `self`, t=.5 is the midpoint, t=1 is `other`.
|
23
|
+
def to(other, t)
|
24
|
+
self.zip(other).map{|a,b|t*(b-a)+a}.to_np
|
25
|
+
end
|
26
|
+
|
27
|
+
# convert to NPoint; returns self
|
28
|
+
def to_np
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
# get the x value
|
33
|
+
def x() self[0]; end
|
34
|
+
# get the y value
|
35
|
+
def y() self[1]; end
|
36
|
+
# get the z value
|
37
|
+
def z() self[2]; end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
class Array
|
42
|
+
# add n-point functions to a copy of this array
|
43
|
+
def to_np
|
44
|
+
dup.extend NPoint
|
45
|
+
end
|
46
|
+
end
|
data/lib/bezier_curve.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# bezier_curve.rb
|
2
|
+
# A bézier curve library for Ruby, supporting n-dimensional,
|
3
|
+
# nth-degree curves.
|
4
|
+
|
5
|
+
require 'bezier_curve/version'
|
6
|
+
require 'bezier_curve/n_point'
|
7
|
+
|
8
|
+
# A bezier curve. Usage:
|
9
|
+
# c = BezierCurve.new([0,0], [0,1], [1,1])
|
10
|
+
# c.first #=> [0,0]
|
11
|
+
# c.last #=> [1,1]
|
12
|
+
# c[0.375] #=> [t=.375]
|
13
|
+
# c.points #=> an array of points that make a fairly smooth curve
|
14
|
+
# c.points(tolerance:Math::PI/20)
|
15
|
+
# #=> returns points with given tolerance for smoothness
|
16
|
+
# c.points(count: 10) #=> returns 10 points, for evenly spaced values of `t`
|
17
|
+
class BezierCurve
|
18
|
+
# create a new curve, from a list of points.
|
19
|
+
def initialize(*controls)
|
20
|
+
# check for argument errors
|
21
|
+
ZeroDimensionError.check! controls
|
22
|
+
DifferingDimensionError.check! controls
|
23
|
+
InsufficientPointsError.check! controls
|
24
|
+
|
25
|
+
@controls = controls.map(&:to_np)
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :controls
|
29
|
+
|
30
|
+
# the first control point
|
31
|
+
def first() controls.first; end
|
32
|
+
alias_method :start, :first
|
33
|
+
# the last control point
|
34
|
+
def last() controls.last; end
|
35
|
+
alias_method :end, :last
|
36
|
+
|
37
|
+
# the degree of the curve
|
38
|
+
def degree
|
39
|
+
controls.size - 1
|
40
|
+
end
|
41
|
+
alias_method :order, :degree
|
42
|
+
# the number of dimensions given
|
43
|
+
def dimensions
|
44
|
+
controls[0].size
|
45
|
+
end
|
46
|
+
|
47
|
+
# find the point for a given value of `t`.
|
48
|
+
def index(t)
|
49
|
+
pts = controls
|
50
|
+
while pts.size > 1
|
51
|
+
pts = (0..pts.size-2).map do |i|
|
52
|
+
pts[i].zip(pts[i+1]).map{|a,b| t*(b-a)+a}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
pts[0].to_np
|
56
|
+
end
|
57
|
+
alias_method :[], :index
|
58
|
+
|
59
|
+
# divide this bezier curve into two curves, at the given `t`
|
60
|
+
def split_at(t)
|
61
|
+
pts = controls
|
62
|
+
a,b = [pts.first],[pts.last]
|
63
|
+
while pts.size > 1
|
64
|
+
pts = (0..pts.size-2).map do |i|
|
65
|
+
pts[i].zip(pts[i+1]).map{|a,b| t*(b-a)+a}
|
66
|
+
end
|
67
|
+
a<<pts.first
|
68
|
+
b<<pts.last
|
69
|
+
end
|
70
|
+
[BezierCurve.new(*a), BezierCurve.new(*b.reverse)]
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Returns a list of points on this curve. If you specify `count`,
|
75
|
+
# returns that many points, evenly spread over values of `t`.
|
76
|
+
# If you specify `tolerance`, no adjoining line segments will
|
77
|
+
# deviate from 180 by an angle of more than the value given (in
|
78
|
+
# radians). If unspecified, defaults to `tolerance: 1/64pi` (~3 deg)
|
79
|
+
def points(count:nil, tolerance:Math::PI/64)
|
80
|
+
if count
|
81
|
+
(0...count).map{|i| index i/(count-1.0)}
|
82
|
+
else
|
83
|
+
lines = subdivide(tolerance)
|
84
|
+
lines.map{|seg|seg.first} + [lines.last.last]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# recursively subdivides the curve until each is straight within the
|
89
|
+
# given tolerance value, in radians
|
90
|
+
def subdivide(tolerance)
|
91
|
+
if is_straight?(tolerance)
|
92
|
+
[self]
|
93
|
+
else
|
94
|
+
a,b = split_at(0.5)
|
95
|
+
a.subdivide(tolerance) + b.subdivide(tolerance)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# test this curve to see of it can be considered straight, optionally
|
101
|
+
# within the given angular tolerance, in radians
|
102
|
+
def is_straight?(tolerance)
|
103
|
+
# sanity check for tolerance in radians
|
104
|
+
if first.angle_to(index(0.5), last) <= tolerance
|
105
|
+
# maximum wavyness is `degree` - 1; split at `degree` points
|
106
|
+
pts = points(count:degree)
|
107
|
+
# size-3, because we ignore the last 2 points as starting points;
|
108
|
+
# check all angles against `tolerance`
|
109
|
+
(0..pts.size-3).all? do |i|
|
110
|
+
pts[i].angle_to(pts[i+1], pts[i+2]) < tolerance
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Indicates an error where the control points are in zero dimensions.
|
116
|
+
# Sounds silly, but you never know when software is generating the
|
117
|
+
# points.
|
118
|
+
class ZeroDimensionError < ArgumentError
|
119
|
+
def initialize
|
120
|
+
super "Points given must have at least one dimension"
|
121
|
+
end
|
122
|
+
def self.check! pointset
|
123
|
+
raise new.tap{|e|e.backtrace.shift} if
|
124
|
+
pointset[0].size == 0
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Indicates that the points do not all have the same number of
|
129
|
+
# dimensions, which makes them impossible to use.
|
130
|
+
class DifferingDimensionError < ArgumentError
|
131
|
+
def initialize
|
132
|
+
super "All points must have the same number of dimensions"
|
133
|
+
end
|
134
|
+
def self.check! pointset
|
135
|
+
raise new.tap{|e|e.backtrace.shift} if
|
136
|
+
pointset[1..-1].any?{|pt| pointset[0].size != pt.size}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Indicates that there aren't enough control points; minimum of two
|
141
|
+
# for a first-degree bezier.
|
142
|
+
class InsufficientPointsError < ArgumentError
|
143
|
+
def initialize
|
144
|
+
super "All points must have the same number of dimensions"
|
145
|
+
end
|
146
|
+
def self.check! pointset
|
147
|
+
raise new.tap{|e|e.backtrace.shift} if
|
148
|
+
pointset.size <= 1
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# test functionality of BezierCurve class
|
2
|
+
require 'test/unit'
|
3
|
+
require 'bezier_curve'
|
4
|
+
|
5
|
+
class TestBezierCurve < Test::Unit::TestCase
|
6
|
+
# shorthand to create a bezier curve
|
7
|
+
def bc(*args)
|
8
|
+
BezierCurve.new(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_degree
|
12
|
+
assert_equal 2, bc([0,0],[0,1],[1,1]).degree
|
13
|
+
assert_equal 3, bc([0,0],[0,1],[1,0],[1,1]).degree
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_dimensions
|
17
|
+
assert_equal 2, bc([0,0],[0,1],[1,1]).dimensions
|
18
|
+
assert_equal 3, bc([0,0,0],[0,1,1],[1,1,2]).dimensions
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_index
|
22
|
+
# simple curves that cross the origin
|
23
|
+
# degree 1
|
24
|
+
assert_equal [0,0], bc([1,1],[-1,-1])[0.5]
|
25
|
+
assert_equal [0,0,0], bc([1,1,1],[-1,-1,-1])[0.5]
|
26
|
+
assert_equal [0,0,0,0], bc([1,1,1,1],[-1,-1,-1,-1])[0.5]
|
27
|
+
assert_equal [0,0,0,0,0], bc([1,1,1,1,1],[-1,-1,-1,-1,-1])[0.5]
|
28
|
+
# degree 2 (quadratic)
|
29
|
+
assert_equal [0,0], bc([1,1],[0,-1],[-1,1])[0.5]
|
30
|
+
assert_equal [0,0,0], bc([1,1,1],[0,0,-1],[-1,-1,1])[0.5]
|
31
|
+
assert_equal [0,0,0,0], bc([1,1,1,1],[0,0,0,-1],[-1,-1,-1,1])[0.5]
|
32
|
+
assert_equal [0,0,0,0,0], bc([1,1,1,1,1],[0,0,0,0,-1],[-1,-1,-1,-1,1])[0.5]
|
33
|
+
# degree 3 (cubic)
|
34
|
+
assert_equal [0,0], bc([1,1],[-1,1],[1,-1],[-1,-1])[0.5]
|
35
|
+
assert_equal [0,0,0], bc([1,1,1],[-1,1,1],[1,-1,-1],[-1,-1,-1])[0.5]
|
36
|
+
assert_equal [0,0,0,0], bc([1,1,1,1],[-1,1,1,1],[1,-1,-1,-1],[-1,-1,-1,-1])[0.5]
|
37
|
+
assert_equal [0,0,0,0,0], bc([1,1,1,1,1],[-1,1,1,1,1],[1,-1,-1,-1,-1],[-1,-1,-1,-1,-1])[0.5]
|
38
|
+
end
|
39
|
+
def test_split_at
|
40
|
+
# not going to test specific points, just that the resulting curves are the same
|
41
|
+
# degree 1
|
42
|
+
c = bc([23,42],[13,7])
|
43
|
+
_c1, _c2 = *c.split_at(0.25)
|
44
|
+
assert_equal c.points(count:9), _c1.points(count:3)[0,2] + _c2.points(count:7)
|
45
|
+
# degree 2
|
46
|
+
c = bc([23,42],[13,7])
|
47
|
+
_c1, _c2 = *c.split_at(0.25)
|
48
|
+
assert_equal c.points(count:9), _c1.points(count:3)[0,2] + _c2.points(count:7)
|
49
|
+
# degree 3
|
50
|
+
c = bc([23,42,],[13,7],[12,54])
|
51
|
+
_c1, _c2 = *c.split_at(0.25)
|
52
|
+
assert_equal c.points(count:9), _c1.points(count:3)[0,2] + _c2.points(count:7)
|
53
|
+
# degree 4
|
54
|
+
c = bc([23,42],[13,7],[12,54],[103,144])
|
55
|
+
_c1, _c2 = *c.split_at(0.25)
|
56
|
+
assert_equal c.points(count:9), _c1.points(count:3)[0,2] + _c2.points(count:7)
|
57
|
+
# degree 5
|
58
|
+
c = bc([23,42],[13,7],[12,54],[103,144],[512,360])
|
59
|
+
_c1, _c2 = *c.split_at(0.25)
|
60
|
+
assert_equal c.points(count:9), _c1.points(count:3)[0,2] + _c2.points(count:7)
|
61
|
+
end
|
62
|
+
# does this really need testing? I really hope not. Oh well.
|
63
|
+
def test_points_count
|
64
|
+
# 1d,o1
|
65
|
+
[2,3,5,8,13,23].each do |n|
|
66
|
+
assert_equal n, bc([0,0],[1,1]).points(count:n).count
|
67
|
+
end
|
68
|
+
# 2d,o2
|
69
|
+
[2,3,5,8,13,23].each do |n|
|
70
|
+
assert_equal n, bc([0,0,0],[1,1,1],[2,2,2]).points(count:n).count
|
71
|
+
end
|
72
|
+
# 3d,o3
|
73
|
+
[2,3,5,8,13,23].each do |n|
|
74
|
+
assert_equal n, bc(*4.times.map{|n|Array.new(4).fill(n)}).points(count:n).count
|
75
|
+
end
|
76
|
+
# 4d,o4
|
77
|
+
[2,3,5,8,13,23].each do |n|
|
78
|
+
assert_equal n, bc(*5.times.map{|n|Array.new(5).fill(n)}).points(count:n).count
|
79
|
+
end
|
80
|
+
# 5d,o5
|
81
|
+
[2,3,5,8,13,23].each do |n|
|
82
|
+
assert_equal n, bc(*6.times.map{|n|Array.new(6).fill(n)}).points(count:n).count
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_points_tolerance
|
87
|
+
pi = Math::PI
|
88
|
+
# just make sure all points are under tolerance
|
89
|
+
# 2d/o
|
90
|
+
p = bc([1,0],[3,2],[7,9]).points(tolerance:pi/53)
|
91
|
+
assert_true (0..p.count-3).all?{|i|p[i].angle_to(p[i+1],p[i+2]).abs < pi/53}
|
92
|
+
# 3d/o
|
93
|
+
p = bc([1,0,2],[3,2,5],[7,9,8],[13,17,12]).points(tolerance:pi/53)
|
94
|
+
assert_true (0..p.count-3).all?{|i|p[i].angle_to(p[i+1],p[i+2]).abs < pi/53}
|
95
|
+
# 4d/o
|
96
|
+
p = bc([1,0,2,-1],[3,2,5,4],[7,9,8,6],[13,17,12,15],[20,21,32,25]).points(tolerance:pi/53)
|
97
|
+
assert_true (0..p.count-3).all?{|i|p[i].angle_to(p[i+1],p[i+2]).abs < pi/53}
|
98
|
+
# 5d/o
|
99
|
+
p = bc([1,0,2,-1,3],[3,2,5,4,6],[7,9,8,6,5],[13,17,12,15,14],[20,21,32,25,23],[34,33,47,39,52]).points(tolerance:pi/53)
|
100
|
+
assert_true (0..p.count-3).all?{|i|p[i].angle_to(p[i+1],p[i+2]).abs < pi/53}
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# test functionality of NPoint module
|
2
|
+
require 'test/unit'
|
3
|
+
require 'bezier_curve/n_point'
|
4
|
+
|
5
|
+
class TestNPoint < Test::Unit::TestCase
|
6
|
+
def test_to_np
|
7
|
+
np = [9,8,7].to_np
|
8
|
+
|
9
|
+
assert_kind_of NPoint, np, "Array#to_np should return an NPoint"
|
10
|
+
assert_same np.to_np, np, "NPoint#to_np should return self"
|
11
|
+
end
|
12
|
+
def test_x
|
13
|
+
np = [9,8,7].to_np
|
14
|
+
assert_equal 9, np.x
|
15
|
+
end
|
16
|
+
def test_y
|
17
|
+
np = [9,8,7].to_np
|
18
|
+
assert_equal 8, np.y
|
19
|
+
end
|
20
|
+
def test_z
|
21
|
+
np = [9,8,7].to_np
|
22
|
+
assert_equal 7, np.z
|
23
|
+
end
|
24
|
+
def test_to
|
25
|
+
a, b = [1,1,1].to_np, [5,5,5].to_np
|
26
|
+
|
27
|
+
assert_equal [3,3,3], a.to(b,0.5)
|
28
|
+
assert_equal [-1,-1,-1], a.to(b,-0.5)
|
29
|
+
assert_equal [7,7,7], a.to(b,1.5)
|
30
|
+
end
|
31
|
+
def test_dist_from
|
32
|
+
# various numbers of dimensions
|
33
|
+
assert_equal 3, [3].to_np.dist_from([6])
|
34
|
+
assert_equal (3**2*2)**0.5, [3,3].to_np.dist_from([6,6])
|
35
|
+
assert_equal (3**2*3)**0.5, [3,3,3].to_np.dist_from([6,6,6])
|
36
|
+
assert_equal (3**2*4)**0.5, [3,3,3,3].to_np.dist_from([6,6,6,6])
|
37
|
+
assert_equal (3**2*5)**0.5, [3,3,3,3,3].to_np.dist_from([6,6,6,6,6])
|
38
|
+
|
39
|
+
# across the origin
|
40
|
+
assert_in_delta 8**0.5, [1,1].to_np.dist_from([-1,-1]), 0.00001
|
41
|
+
end
|
42
|
+
def test_angle_to
|
43
|
+
pi = Math::PI
|
44
|
+
pi_eps = (pi.next_float-pi)*16
|
45
|
+
assert_in_epsilon pi/2, [1,0].to_np.angle_to([0,0],[0,1]), pi_eps
|
46
|
+
assert_in_epsilon pi, [1,1].to_np.angle_to([0,0],[1,1]), pi_eps
|
47
|
+
assert_in_epsilon 0, [1,1].to_np.angle_to([0,0],[-1,-1]), pi_eps
|
48
|
+
assert_in_epsilon pi/4, [-1,0].to_np.angle_to([0,0],[1,1]), pi_eps
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bezier_curve
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Hubbart
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A bézier curve library for Ruby, supporting n-dimensional, nth-degree
|
14
|
+
curves
|
15
|
+
email: mark.hubbart@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- README.md
|
21
|
+
- Rakefile
|
22
|
+
- lib/bezier_curve.rb
|
23
|
+
- lib/bezier_curve/n_point.rb
|
24
|
+
- lib/bezier_curve/version.rb
|
25
|
+
- test/test_bezier_curve.rb
|
26
|
+
- test/test_n_point.rb
|
27
|
+
homepage: https://github.com/marcuserronius/bezier_curve
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.4.5
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: N-dimensional, nth-degree bézier curves
|
51
|
+
test_files: []
|