agt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +7 -0
  3. data/README.md +5 -0
  4. data/app/assets/javascripts/agt/config.coffee +9 -0
  5. data/app/assets/javascripts/agt/dom.coffee +12 -0
  6. data/app/assets/javascripts/agt/function.coffee +317 -0
  7. data/app/assets/javascripts/agt/geom/circle.coffee +338 -0
  8. data/app/assets/javascripts/agt/geom/cubic_bezier.coffee +37 -0
  9. data/app/assets/javascripts/agt/geom/diamond.coffee +241 -0
  10. data/app/assets/javascripts/agt/geom/ellipsis.coffee +141 -0
  11. data/app/assets/javascripts/agt/geom/linear_spline.coffee +56 -0
  12. data/app/assets/javascripts/agt/geom/matrix.coffee +240 -0
  13. data/app/assets/javascripts/agt/geom/mixins/geometry.coffee +171 -0
  14. data/app/assets/javascripts/agt/geom/mixins/intersections.coffee +150 -0
  15. data/app/assets/javascripts/agt/geom/mixins/path.coffee +145 -0
  16. data/app/assets/javascripts/agt/geom/mixins/proxyable.coffee +9 -0
  17. data/app/assets/javascripts/agt/geom/mixins/spline.coffee +329 -0
  18. data/app/assets/javascripts/agt/geom/mixins/surface.coffee +55 -0
  19. data/app/assets/javascripts/agt/geom/mixins/triangulable.coffee +112 -0
  20. data/app/assets/javascripts/agt/geom/point.coffee +454 -0
  21. data/app/assets/javascripts/agt/geom/polygon.coffee +119 -0
  22. data/app/assets/javascripts/agt/geom/quad_bezier.coffee +43 -0
  23. data/app/assets/javascripts/agt/geom/quint_bezier.coffee +42 -0
  24. data/app/assets/javascripts/agt/geom/rectangle.coffee +599 -0
  25. data/app/assets/javascripts/agt/geom/spiral.coffee +90 -0
  26. data/app/assets/javascripts/agt/geom/transformation_proxy.coffee +43 -0
  27. data/app/assets/javascripts/agt/geom/triangle.coffee +442 -0
  28. data/app/assets/javascripts/agt/impulse.coffee +105 -0
  29. data/app/assets/javascripts/agt/index.coffee +56 -0
  30. data/app/assets/javascripts/agt/inflector/inflection.coffee +21 -0
  31. data/app/assets/javascripts/agt/inflector/inflections.coffee +75 -0
  32. data/app/assets/javascripts/agt/inflector/inflector.coffee +235 -0
  33. data/app/assets/javascripts/agt/inheritance.coffee +132 -0
  34. data/app/assets/javascripts/agt/math.coffee +45 -0
  35. data/app/assets/javascripts/agt/mixins/activable.coffee +31 -0
  36. data/app/assets/javascripts/agt/mixins/aliasable.coffee +25 -0
  37. data/app/assets/javascripts/agt/mixins/alternate_case.coffee +72 -0
  38. data/app/assets/javascripts/agt/mixins/cloneable.coffee +71 -0
  39. data/app/assets/javascripts/agt/mixins/delegation.coffee +90 -0
  40. data/app/assets/javascripts/agt/mixins/disposable.coffee +7 -0
  41. data/app/assets/javascripts/agt/mixins/equatable.coffee +37 -0
  42. data/app/assets/javascripts/agt/mixins/formattable.coffee +52 -0
  43. data/app/assets/javascripts/agt/mixins/globalizable.coffee +175 -0
  44. data/app/assets/javascripts/agt/mixins/has_ancestors.coffee +47 -0
  45. data/app/assets/javascripts/agt/mixins/has_collection.coffee +107 -0
  46. data/app/assets/javascripts/agt/mixins/has_nested_collection.coffee +51 -0
  47. data/app/assets/javascripts/agt/mixins/memoizable.coffee +64 -0
  48. data/app/assets/javascripts/agt/mixins/parameterizable.coffee +101 -0
  49. data/app/assets/javascripts/agt/mixins/poolable.coffee +62 -0
  50. data/app/assets/javascripts/agt/mixins/sourcable.coffee +45 -0
  51. data/app/assets/javascripts/agt/mixins/state_machine.coffee +47 -0
  52. data/app/assets/javascripts/agt/net/router.coffee +165 -0
  53. data/app/assets/javascripts/agt/object.coffee +9 -0
  54. data/app/assets/javascripts/agt/particles/actions/base_action.coffee +7 -0
  55. data/app/assets/javascripts/agt/particles/actions/die_on_surface.coffee +14 -0
  56. data/app/assets/javascripts/agt/particles/actions/force.coffee +11 -0
  57. data/app/assets/javascripts/agt/particles/actions/friction.coffee +14 -0
  58. data/app/assets/javascripts/agt/particles/actions/live.coffee +9 -0
  59. data/app/assets/javascripts/agt/particles/actions/macro_action.coffee +13 -0
  60. data/app/assets/javascripts/agt/particles/actions/move.coffee +11 -0
  61. data/app/assets/javascripts/agt/particles/actions/null_action.coffee +9 -0
  62. data/app/assets/javascripts/agt/particles/counters/by_rate.coffee +17 -0
  63. data/app/assets/javascripts/agt/particles/counters/fixed.coffee +9 -0
  64. data/app/assets/javascripts/agt/particles/counters/null_counter.coffee +9 -0
  65. data/app/assets/javascripts/agt/particles/emission.coffee +35 -0
  66. data/app/assets/javascripts/agt/particles/emitters/null_emitter.coffee +7 -0
  67. data/app/assets/javascripts/agt/particles/emitters/path.coffee +10 -0
  68. data/app/assets/javascripts/agt/particles/emitters/ponctual.coffee +9 -0
  69. data/app/assets/javascripts/agt/particles/emitters/surface.coffee +10 -0
  70. data/app/assets/javascripts/agt/particles/initializers/explosion.coffee +19 -0
  71. data/app/assets/javascripts/agt/particles/initializers/life.coffee +16 -0
  72. data/app/assets/javascripts/agt/particles/initializers/macro_initializer.coffee +10 -0
  73. data/app/assets/javascripts/agt/particles/initializers/null_initializer.coffee +7 -0
  74. data/app/assets/javascripts/agt/particles/initializers/particle_sub_system.coffee +12 -0
  75. data/app/assets/javascripts/agt/particles/initializers/stream.coffee +20 -0
  76. data/app/assets/javascripts/agt/particles/mixins/randomizable.coffee +10 -0
  77. data/app/assets/javascripts/agt/particles/particle.coffee +32 -0
  78. data/app/assets/javascripts/agt/particles/sub_system.coffee +11 -0
  79. data/app/assets/javascripts/agt/particles/system.coffee +103 -0
  80. data/app/assets/javascripts/agt/particles/timers/instant.coffee +11 -0
  81. data/app/assets/javascripts/agt/particles/timers/limited.coffee +19 -0
  82. data/app/assets/javascripts/agt/particles/timers/null_timer.coffee +11 -0
  83. data/app/assets/javascripts/agt/particles/timers/unlimited.coffee +9 -0
  84. data/app/assets/javascripts/agt/particles/timers/until_death.coffee +11 -0
  85. data/app/assets/javascripts/agt/promise.coffee +214 -0
  86. data/app/assets/javascripts/agt/random/random.coffee +100 -0
  87. data/app/assets/javascripts/agt/random/seeds/lagged_fibonnacci.coffee +53 -0
  88. data/app/assets/javascripts/agt/random/seeds/linear.coffee +16 -0
  89. data/app/assets/javascripts/agt/random/seeds/linear_congruential.coffee +23 -0
  90. data/app/assets/javascripts/agt/random/seeds/math_random.coffee +9 -0
  91. data/app/assets/javascripts/agt/random/seeds/mersenne_twister.coffee +42 -0
  92. data/app/assets/javascripts/agt/random/seeds/no_random.coffee +12 -0
  93. data/app/assets/javascripts/agt/random/seeds/paul_houle.coffee +19 -0
  94. data/app/assets/javascripts/agt/signal.coffee +272 -0
  95. data/app/assets/javascripts/agt/sprites/animation.coffee +13 -0
  96. data/app/assets/javascripts/agt/sprites/sprite.coffee +30 -0
  97. data/app/assets/javascripts/agt/widgets/hash.coffee +36 -0
  98. data/app/assets/javascripts/agt/widgets/widgets.coffee +194 -0
  99. data/app/assets/javascripts/agt/widgets/widgets/checked_input.coffee +7 -0
  100. data/app/assets/javascripts/agt/widgets/widgets/focus_bubbling.coffee +15 -0
  101. data/lib/agt.rb +8 -0
  102. data/lib/agt/version.rb +5 -0
  103. metadata +173 -0
@@ -0,0 +1,37 @@
1
+ namespace('agt.geom')
2
+
3
+ # Public:
4
+ class agt.geom.CubicBezier
5
+ @include agt.mixins.Formattable('CubicBezier')
6
+ @include agt.mixins.Sourcable('agt.geom.CubicBezier', 'vertices', 'bias')
7
+ @include agt.geom.Geometry
8
+ @include agt.geom.Path
9
+ @include agt.geom.Intersections
10
+ @include agt.geom.Spline(3)
11
+
12
+ ### Public ###
13
+
14
+ constructor: (vertices, bias=20) ->
15
+ @initSpline vertices, bias
16
+
17
+ pointInSegment: (t, seg) ->
18
+ pt = new agt.geom.Point()
19
+ pt.x = (seg[0].x * @b1 (t)) +
20
+ (seg[1].x * @b2 (t)) +
21
+ (seg[2].x * @b3 (t)) +
22
+ (seg[3].x * @b4 (t))
23
+ pt.y = (seg[0].y * @b1 (t)) +
24
+ (seg[1].y * @b2 (t)) +
25
+ (seg[2].y * @b3 (t)) +
26
+ (seg[3].y * @b4 (t))
27
+ pt
28
+
29
+ ### Internal ###
30
+
31
+ b1: (t) -> ((1 - t) * (1 - t) * (1 - t))
32
+
33
+ b2: (t) -> (3 * t * (1 - t) * (1 - t))
34
+
35
+ b3: (t) -> (3 * t * t * (1 - t))
36
+
37
+ b4: (t) -> (t * t * t)
@@ -0,0 +1,241 @@
1
+ namespace('agt.geom')
2
+
3
+ # Public:
4
+ class agt.geom.Diamond
5
+ properties = ['topLength', 'rightLength', 'bottomLength', 'leftLength', 'x', 'y', 'rotation']
6
+
7
+ @include agt.mixins.Formattable(['Diamond'].concat(properties)...)
8
+ @include agt.mixins.Parameterizable('diamondFrom', {
9
+ topLength: 1
10
+ rightLength: 1
11
+ bottomLength: 1
12
+ leftLength: 1
13
+ x: 0
14
+ y: 0
15
+ rotation: 0
16
+ })
17
+ @include agt.mixins.Sourcable(['agt.geom.Diamond'].concat properties)
18
+ @include agt.mixins.Equatable(properties...)
19
+ @include agt.mixins.Cloneable()
20
+ @include agt.mixins.Memoizable
21
+ @include agt.geom.Geometry
22
+ @include agt.geom.Surface
23
+ @include agt.geom.Path
24
+ @include agt.geom.Intersections
25
+
26
+ ### Public ###
27
+
28
+ constructor: (topLength, rightLength, bottomLength, leftLength, x, y, rotation) ->
29
+ args = @diamondFrom topLength, rightLength, bottomLength, leftLength, x, y, rotation
30
+ {@topLength, @rightLength, @bottomLength, @leftLength, @x, @y, @rotation} = args
31
+
32
+ center: -> new agt.geom.Point(@x, @y)
33
+
34
+ topAxis: -> new agt.geom.Point(0,-@topLength).rotate(@rotation)
35
+
36
+ bottomAxis: -> new agt.geom.Point(0,@bottomLength).rotate(@rotation)
37
+
38
+ leftAxis: -> new agt.geom.Point(-@leftLength,0).rotate(@rotation)
39
+
40
+ rightAxis: -> new agt.geom.Point(@rightLength,0).rotate(@rotation)
41
+
42
+ corners: ->
43
+ [
44
+ @topCorner()
45
+ @rightCorner()
46
+ @bottomCorner()
47
+ @leftCorner()
48
+ ]
49
+
50
+ topCorner: -> @center().add(@topAxis())
51
+
52
+ bottomCorner: -> @center().add(@bottomAxis())
53
+
54
+ leftCorner: -> @center().add(@leftAxis())
55
+
56
+ rightCorner: -> @center().add(@rightAxis())
57
+
58
+ edges: ->
59
+ [
60
+ @topLeftEdge()
61
+ @topRightEdge()
62
+ @bottomRightEdge()
63
+ @bottomLeftEdge()
64
+ ]
65
+
66
+ topLeftEdge: -> @topCorner().subtract(@leftCorner())
67
+
68
+ topRightEdge: -> @rightCorner().subtract(@topCorner())
69
+
70
+ bottomLeftEdge: -> @leftCorner().subtract(@bottomCorner())
71
+
72
+ bottomRightEdge: -> @bottomCorner().subtract(@rightCorner())
73
+
74
+ quadrants: ->
75
+ [
76
+ @topLeftQuadrant()
77
+ @topRightQuadrant()
78
+ @bottomRightQuadrant()
79
+ @bottomLeftQuadrant()
80
+ ]
81
+
82
+ topLeftQuadrant: ->
83
+ k = 'topLeftQuadrant'
84
+ return @memoFor k if @memoized k
85
+ @memoize k, new agt.geom.Triangle(@center(), @topCorner(), @leftCorner())
86
+
87
+ topRightQuadrant: ->
88
+ k = 'topRightQuadrant'
89
+ return @memoFor k if @memoized k
90
+ @memoize k, new agt.geom.Triangle(@center(), @topCorner(), @rightCorner())
91
+
92
+ bottomLeftQuadrant: ->
93
+ k = 'bottomLeftQuadrant'
94
+ return @memoFor k if @memoized k
95
+ @memoize k, new agt.geom.Triangle(@center(), @bottomCorner(), @leftCorner())
96
+
97
+ bottomRightQuadrant: ->
98
+ k = 'bottomRightQuadrant'
99
+ return @memoFor k if @memoized k
100
+ @memoize k, new agt.geom.Triangle(@center(), @bottomCorner(), @rightCorner())
101
+
102
+ top: -> Math.min @topCorner().y,
103
+ @bottomCorner().y,
104
+ @leftCorner().y,
105
+ @rightCorner().y,
106
+
107
+ bottom: -> Math.max @topCorner().y,
108
+ @bottomCorner().y,
109
+ @leftCorner().y,
110
+ @rightCorner().y,
111
+
112
+ left: -> Math.min @topCorner().x,
113
+ @bottomCorner().x,
114
+ @leftCorner().x,
115
+ @rightCorner().x,
116
+
117
+ right: -> Math.max @topCorner().x,
118
+ @bottomCorner().x,
119
+ @leftCorner().x,
120
+ @rightCorner().x,
121
+
122
+ translate: (xOrPt, y) ->
123
+ {x,y} = agt.geom.Point.pointFrom xOrPt, y
124
+
125
+ @x += x
126
+ @y += y
127
+ this
128
+
129
+ rotate: (rotation) ->
130
+ @rotation += rotation
131
+ this
132
+
133
+ scale: (scale) ->
134
+ @topLength *= scale
135
+ @bottomLength *= scale
136
+ @rightLength *= scale
137
+ @leftLength *= scale
138
+ this
139
+
140
+ points: ->
141
+ [t = @topCorner(), @rightCorner(), @bottomCorner(), @leftCorner(), t]
142
+
143
+ triangles: -> @quadrants()
144
+
145
+ closedGeometry: -> true
146
+
147
+ pointAtAngle: (angle) ->
148
+ center = @center()
149
+ vec = center.add Math.cos(angle)*10000,
150
+ Math.sin(angle)*10000
151
+ @intersections(points: -> [center, vec])?[0]
152
+
153
+ acreage: ->
154
+ @topLeftQuadrant().acreage() +
155
+ @topRightQuadrant().acreage() +
156
+ @bottomLeftQuadrant().acreage() +
157
+ @bottomRightQuadrant().acreage()
158
+
159
+ contains: (x,y) ->
160
+ @center().equals(x,y) or
161
+ @topLeftQuadrant().contains(x,y) or
162
+ @topRightQuadrant().contains(x,y) or
163
+ @bottomLeftQuadrant().contains(x,y) or
164
+ @bottomRightQuadrant().contains(x,y)
165
+
166
+ randomPointInSurface: (random) ->
167
+ l = @acreage()
168
+ q1 = @topLeftQuadrant()
169
+ q2 = @topRightQuadrant()
170
+ q3 = @bottomRightQuadrant()
171
+ q4 = @bottomLeftQuadrant()
172
+
173
+ a1 = q1.acreage()
174
+ a2 = q2.acreage()
175
+ a3 = q3.acreage()
176
+ a4 = q4.acreage()
177
+ a = a1 + a2 + a3 + a4
178
+
179
+ l1 = a1 / a
180
+ l2 = a2 / a
181
+ l3 = a3 / a
182
+ l4 = a4 / a
183
+
184
+ n = random.get()
185
+
186
+ if n < l1
187
+ q1.randomPointInSurface random
188
+ else if n < l1 + l2
189
+ q2.randomPointInSurface random
190
+ else if n < l1 + l2 + l3
191
+ q3.randomPointInSurface random
192
+ else
193
+ q4.randomPointInSurface random
194
+
195
+ length: ->
196
+ @topRightEdge().length() +
197
+ @topLeftEdge().length() +
198
+ @bottomRightEdge().length() +
199
+ @bottomLeftEdge().length()
200
+
201
+ pathPointAt: (n, pathBasedOnLength=true) ->
202
+ [p1,p2,p3] = @pathSteps pathBasedOnLength
203
+
204
+ if n < p1
205
+ @topCorner().add @topRightEdge().scale Math.map n, 0, p1, 0, 1
206
+ else if n < p2
207
+ @rightCorner().add @bottomRightEdge().scale Math.map n, p1, p2, 0, 1
208
+ else if n < p3
209
+ @bottomCorner().add @bottomLeftEdge().scale Math.map n, p2, p3, 0, 1
210
+ else
211
+ @leftCorner().add @topLeftEdge().scale Math.map n, p3, 1, 0, 1
212
+
213
+ pathOrientationAt: (n, pathBasedOnLength=true) ->
214
+ [p1,p2,p3] = @pathSteps pathBasedOnLength
215
+
216
+ if n < p1
217
+ p = @topRightEdge()
218
+ else if n < p2
219
+ p = @bottomRightEdge()
220
+ else if n < p3
221
+ p = @bottomLeftEdge().scale -1
222
+ else
223
+ p = @topLeftEdge().scale -1
224
+
225
+ p.angle()
226
+
227
+ pathSteps: (pathBasedOnLength=true) ->
228
+ if pathBasedOnLength
229
+ l = @length()
230
+ p1 = @topRightEdge().length() / l
231
+ p2 = p1 + @bottomRightEdge().length() / l
232
+ p3 = p2 + @bottomLeftEdge().length() / l
233
+ else
234
+ p1 = 1 / 4
235
+ p2 = 1 / 2
236
+ p3 = 3 / 4
237
+
238
+ [p1, p2, p3]
239
+
240
+ memoizationKey: ->
241
+ "#{@x};#{@y};#{@rotation};#{@topLength};#{@bottomLength};#{@leftLength};#{@rightLength};"
@@ -0,0 +1,141 @@
1
+ namespace('agt.geom')
2
+
3
+ # Public:
4
+ class agt.geom.Ellipsis
5
+ properties = ['radius1', 'radius2', 'x', 'y', 'rotation', 'segments']
6
+
7
+ @include agt.mixins.Equatable(properties...)
8
+ @include agt.mixins.Formattable(['Ellipsis'].concat(properties)...)
9
+ @include agt.mixins.Parameterizable('ellipsisFrom', {
10
+ radius1: 1
11
+ radius2: 1
12
+ x: 0
13
+ y: 0
14
+ rotation: 0
15
+ segments: 36
16
+ })
17
+ @include agt.mixins.Sourcable(['agt.geom.Ellipsis'].concat(properties)...)
18
+ @include agt.mixins.Cloneable()
19
+ @include agt.mixins.Memoizable
20
+ @include agt.geom.Geometry
21
+ @include agt.geom.Surface
22
+ @include agt.geom.Path
23
+ @include agt.geom.Intersections
24
+
25
+ ### Public ###
26
+
27
+ constructor: (r1, r2, x, y, rot, segments) ->
28
+ {@radius1,@radius2,@x,@y,@rotation,@segments} = @ellipsisFrom r1, r2,
29
+ x, y, rot,
30
+ segments
31
+
32
+ center: -> new agt.geom.Point @x, @y
33
+
34
+ left: -> Math.min.apply Math, @xBounds()
35
+
36
+ right: -> Math.max.apply Math, @xBounds()
37
+
38
+ bottom: -> Math.max.apply Math, @yBounds()
39
+
40
+ top: -> Math.min.apply Math, @yBounds()
41
+
42
+ # Internal:
43
+ xBounds: ->
44
+ phi = @rotation
45
+ t = Math.atan(-@radius2 * Math.tan(phi) / @radius1)
46
+ [t, t+Math.PI].map (t) =>
47
+ @x + @radius1*Math.cos(t)*Math.cos(phi) -
48
+ @radius2*Math.sin(t)*Math.sin(phi)
49
+
50
+ # Internal:
51
+ yBounds: ->
52
+ phi = @rotation
53
+ t = Math.atan(@radius2 * (Math.cos(phi) / Math.sin(phi)) / @radius1)
54
+ [t, t+Math.PI].map (t) =>
55
+ @y + @radius1*Math.cos(t)*Math.sin(phi) +
56
+ @radius2*Math.sin(t)*Math.cos(phi)
57
+
58
+ translate: (xOrPt, y) ->
59
+ {x,y} = agt.geom.Point.pointFrom xOrPt, y
60
+
61
+ @x += x
62
+ @y += y
63
+ this
64
+
65
+ rotate: (rotation) ->
66
+ @rotation += rotation
67
+ this
68
+
69
+ scale: (scale) ->
70
+ @radius1 *= scale
71
+ @radius2 *= scale
72
+ this
73
+
74
+ points: ->
75
+ @memoFor('points').concat() if @memoized 'points'
76
+ @memoize 'points', (@pathPointAt n / @segments for n in [0..@segments])
77
+
78
+ triangles: ->
79
+ return @memoFor 'triangles' if @memoized 'triangles'
80
+
81
+ triangles = []
82
+ points = @points()
83
+ center = @center()
84
+ for i in [1..points.length-1]
85
+ triangles.push new agt.geom.Triangle center, points[i-1], points[i]
86
+
87
+ @memoize 'triangles', triangles
88
+
89
+ closedGeometry: -> true
90
+
91
+ pointAtAngle: (angle) ->
92
+ a = angle - @rotation
93
+ ratio = @radius1 / @radius2
94
+ vec = new agt.geom.Point Math.cos(a) * @radius1, Math.sin(a) * @radius1
95
+ vec.x = vec.x / ratio if @radius1 < @radius2
96
+ vec.y = vec.y * ratio if @radius1 > @radius2
97
+ a = vec.angle()
98
+ p = new agt.geom.Point Math.cos(a) * @radius1, Math.sin(a) * @radius2
99
+
100
+ @center().add p.rotate(@rotation)
101
+
102
+ acreage: -> Math.PI * @radius1 * @radius2
103
+
104
+ randomPointInSurface: (random) ->
105
+ unless random?
106
+ random = new agt.random.Random new agt.random.MathRandom
107
+
108
+ pt = @pathPointAt random.get()
109
+ center = @center()
110
+ dif = pt.subtract center
111
+ center.add dif.scale Math.sqrt random.random()
112
+
113
+ contains: (xOrPt, y) ->
114
+ p = new agt.geom.Point xOrPt, y
115
+ c = @center()
116
+ d = p.subtract c
117
+ a = d.angle()
118
+ p2 = @pointAtAngle a
119
+ c.distance(p2) >= c.distance(p)
120
+
121
+ length: -> Math.PI * (3*(@radius1 + @radius2) -
122
+ Math.sqrt((3* @radius1 + @radius2) * (@radius1 + @radius2 *3)))
123
+
124
+ pathPointAt: (n) ->
125
+ a = n * Math.PI * 2
126
+ p = new agt.geom.Point Math.cos(a) * @radius1, Math.sin(a) * @radius2
127
+
128
+ @center().add p.rotate(@rotation)
129
+
130
+ drawPath: (context) ->
131
+ context.save()
132
+ context.translate(@x, @y)
133
+ context.rotate(@rotation)
134
+ context.scale(@radius1, @radius2)
135
+ context.beginPath()
136
+ context.arc(0,0,1,0, Math.PI*2)
137
+ context.closePath()
138
+ context.restore()
139
+
140
+ memoizationKey: ->
141
+ "#{@radius1};#{@radius2};#{@x};#{@y};#{@rotation};#{@segments}"
@@ -0,0 +1,56 @@
1
+ namespace('agt.geom')
2
+
3
+ # Public: The `LinearSpline` is the simplest spline you can find.
4
+ #
5
+ # <script>window.exampleKey = 'linear_spline'</script>
6
+ # <script>drawGeometry(exampleKey, {highlight: true})</script>
7
+ #
8
+ # ### Included Mixins
9
+ #
10
+ # - {agt.geom.Geometry}
11
+ # - {agt.geom.Intersections}
12
+ # - {agt.geom.Path}
13
+ # - [agt.mixins.Spline](../../../files/geom/mixins/spline.coffee.html)
14
+ # - [agt.mixins.Formattable](../../../files/mixins/formattable.coffee.html)
15
+ # - [agt.mixins.Memoizable](../../../files/mixins/memoizable.coffee.html)
16
+ # - [agt.mixins.Sourcable](../../../files/mixins/sourcable.coffee.html)
17
+ class agt.geom.LinearSpline
18
+ @include agt.mixins.Formattable('LinearSpline')
19
+ @include agt.mixins.Sourcable('agt.geom.LinearSpline', 'vertices', 'bias')
20
+ @include agt.geom.Geometry
21
+ @include agt.geom.Path
22
+ @include agt.geom.Intersections
23
+ @include agt.geom.Spline(1)
24
+
25
+ ### Public ###
26
+
27
+ # Creates a new [LinearSpline]{agt.geom.LinearSpline}
28
+ #
29
+ # vertices - An {Array} of [Points]{agt.geom.Point} that forms the spline.
30
+ constructor: (vertices) ->
31
+ @initSpline vertices
32
+
33
+ # The points of a linear spline are the same as its array of vertices.
34
+ #
35
+ # <script>drawGeometryPoints(exampleKey, 'points')</script>
36
+ #
37
+ # Returns an {Array} of [Points]{agt.geom.Point}.
38
+ points: -> vertex.clone() for vertex in @vertices
39
+
40
+ # Returns the number of segments in the spline.
41
+ #
42
+ # Returns a {Number}
43
+ segments: -> @vertices.length - 1
44
+
45
+ # **Unsupported** - As the final points of a linear spine are its vertices
46
+ # there's no need to render the connections between them.
47
+ drawVerticesConnections: ->
48
+
49
+ ### Internal ###
50
+
51
+ # Validates the size of the vertices array.
52
+ #
53
+ # vertices - The {Array} of vertices to validate.
54
+ #
55
+ # Returns a {Boolean}.
56
+ validateVertices: (vertices) -> vertices.length >= 2