author | Claus Gittinger <cg@exept.de> |
Tue, 25 Jun 2019 14:28:51 +0200 | |
changeset 5050 | 44fa8672d102 |
parent 2902 | 8b615b5c2fc4 |
permissions | -rw-r--r-- |
278 | 1 |
" |
2 |
This class is based on a file from the Manchester Goodie library. |
|
3 |
It is not covered by the ST/X copyright and may be copied and used |
|
4 |
according the rules as stated by the athor and the manchester archive. |
|
5 |
||
6 |
The original readme was: |
|
7 |
||
8 |
||
9 |
The above file is a Manchester Goodie. It is distributed freely on condition |
|
10 |
that you observe these conditions in respect of the whole Goodie, and on |
|
11 |
any significant part of it which is separately transmitted or stored: |
|
12 |
* You must ensure that every copy includes this notice, and that |
|
13 |
source and author(s) of the material are acknowledged. |
|
14 |
* These conditions must be imposed on anyone who receives a copy. |
|
15 |
* The material shall not be used for commercial gain without the prior |
|
16 |
written consent of the author(s). |
|
17 |
||
18 |
For more information about the Manchester Goodies Library (from which |
|
19 |
this file was distributed) send e-mail: |
|
20 |
To: goodies-lib@cs.man.ac.uk |
|
21 |
Subject: help |
|
22 |
" |
|
1303 | 23 |
"{ Package: 'stx:libbasic2' }" |
24 |
||
278 | 25 |
Geometric subclass:#Spline |
26 |
instanceVariableNames:'controlPoints lines function firstDerivative secondDerivative |
|
27 |
thirdDerivative' |
|
28 |
classVariableNames:'' |
|
29 |
poolDictionaries:'' |
|
1303 | 30 |
category:'Graphics-Geometry-Objects' |
278 | 31 |
! |
32 |
||
33 |
!Spline class methodsFor:'documentation'! |
|
34 |
||
35 |
copyright |
|
36 |
" |
|
37 |
This class is based on a file from the Manchester Goodie library. |
|
38 |
It is not covered by the ST/X copyright and may be copied and used |
|
39 |
according the rules as stated by the athor and the manchester archive. |
|
40 |
||
41 |
The original readme was: |
|
42 |
||
43 |
||
44 |
The above file is a Manchester Goodie. It is distributed freely on condition |
|
45 |
that you observe these conditions in respect of the whole Goodie, and on |
|
46 |
any significant part of it which is separately transmitted or stored: |
|
47 |
* You must ensure that every copy includes this notice, and that |
|
48 |
source and author(s) of the material are acknowledged. |
|
49 |
* These conditions must be imposed on anyone who receives a copy. |
|
50 |
* The material shall not be used for commercial gain without the prior |
|
51 |
written consent of the author(s). |
|
52 |
||
53 |
For more information about the Manchester Goodies Library (from which |
|
54 |
this file was distributed) send e-mail: |
|
55 |
To: goodies-lib@cs.man.ac.uk |
|
56 |
Subject: help |
|
57 |
" |
|
58 |
||
59 |
||
60 |
! |
|
61 |
||
62 |
documentation |
|
63 |
" |
|
64 |
Spline defines a path that includes an arbitrary collection of points |
|
280 | 65 |
connected by a third order curve. The curve passes through all controlPoints. |
66 |
Both open and closed curves are possible. |
|
278 | 67 |
|
279 | 68 |
[see also:] |
289 | 69 |
Polygon LineSegment Circle EllipticalArc |
331 | 70 |
Rectangle Curve Arrow ArrowedSpline |
71 |
GraphicsContext StrokingWrapper FillingWrapper |
|
279 | 72 |
|
278 | 73 |
[author:] |
74 |
scaletti@uxc.cso.uiuc.edu (Kurt J. Hebel) |
|
279 | 75 |
adapted to ST/X & minor fixes by Claus Gittinger |
278 | 76 |
" |
77 |
! |
|
78 |
||
79 |
examples |
|
80 |
" |
|
280 | 81 |
open spline; filled & unfilled: |
82 |
[exBegin] |
|
83 |
|v s| |
|
84 |
||
85 |
v := (View extent:100@100) openAndWait. |
|
86 |
||
87 |
s := Spline controlPoints: |
|
88 |
(Array with:(20@20) |
|
89 |
with:(80@80) |
|
90 |
with:(20@80)). |
|
91 |
||
92 |
v paint:Color blue. |
|
93 |
s displayFilledOn:v. |
|
94 |
||
95 |
v paint:Color red. |
|
96 |
s displayStrokedOn:v. |
|
97 |
[exEnd] |
|
98 |
||
99 |
closed spline; filled & unfilled: |
|
100 |
[exBegin] |
|
101 |
|v s| |
|
102 |
||
103 |
v := (View extent:100@100) openAndWait. |
|
104 |
||
105 |
s := Spline controlPoints: |
|
106 |
(Array with:(20@20) |
|
107 |
with:(80@80) |
|
108 |
with:(20@80) |
|
109 |
with:(20@20)). |
|
110 |
||
111 |
v paint:Color blue. |
|
112 |
s displayFilledOn:v. |
|
113 |
||
114 |
v paint:Color red. |
|
115 |
s displayStrokedOn:v. |
|
116 |
[exEnd] |
|
117 |
||
118 |
spiral: |
|
119 |
[exBegin] |
|
120 |
|v points s| |
|
121 |
||
122 |
v := View extent:(200 @ 200). |
|
123 |
||
124 |
v openAndWait. |
|
125 |
||
126 |
points := OrderedCollection new. |
|
127 |
90 to:10 by:-10 do:[:r | |
|
128 |
0 to:330 by:30 do:[:angle | |
|
129 |
|d| |
|
130 |
||
131 |
d := (angle / 360) * 10. |
|
132 |
points add:(Point r:r-d angle:angle) + (100@100) |
|
133 |
]. |
|
134 |
]. |
|
135 |
s := Spline controlPoints:points. |
|
136 |
||
137 |
v paint:Color red. |
|
138 |
s displayStrokedOn:v. |
|
139 |
[exEnd] |
|
140 |
interactive example: |
|
493 | 141 |
click-left for first-points; right for last. |
278 | 142 |
[exBegin] |
143 |
|v points eventCatcher| |
|
144 |
||
145 |
v := StandardSystemView extent:(450 @ 450). |
|
146 |
v label:'Spline Example - (click left/middle)'. |
|
147 |
||
148 |
points := OrderedCollection new. |
|
2425 | 149 |
v viewBackground:Color black. |
278 | 150 |
v openAndWait. |
151 |
||
152 |
eventCatcher := Plug new. |
|
153 |
eventCatcher respondTo:#handlesButtonPress:inView: |
|
154 |
with:[:butt :view | true]. |
|
155 |
eventCatcher respondTo:#buttonPress:x:y:view: |
|
156 |
with:[:butt :x :y :view | |
|
157 |
v paint:(Color white). |
|
158 |
v fillCircle:(x @ y) radius:3. |
|
159 |
points add:(x @ y). |
|
160 |
||
161 |
(butt == 1 or:[butt == #select]) ifFalse:[ |
|
162 |
v paint:(Color white). |
|
163 |
v fillCircle:(x @ y) radius:3. |
|
164 |
||
165 |
(Spline controlPoints:points) displayStrokedOn:v. |
|
166 |
||
167 |
points := OrderedCollection new. |
|
168 |
] |
|
169 |
]. |
|
170 |
||
171 |
v delegate:(eventCatcher) |
|
172 |
[exEnd] |
|
173 |
" |
|
174 |
! ! |
|
175 |
||
176 |
!Spline class methodsFor:'instance creation'! |
|
177 |
||
178 |
controlPoints:aSequentialCollectionOfPoints |
|
179 |
"return a new spline, which passes through aSequentialCollectionOfPoints" |
|
180 |
||
181 |
^ self new controlPoints:aSequentialCollectionOfPoints |
|
182 |
! ! |
|
183 |
||
184 |
!Spline methodsFor:'accessing'! |
|
185 |
||
186 |
controlPoints |
|
2318 | 187 |
"return the collection of points through which the spline is to pass" |
278 | 188 |
|
189 |
^ controlPoints |
|
190 |
||
191 |
"Created: 8.5.1996 / 18:46:35 / cg" |
|
192 |
! |
|
193 |
||
194 |
controlPoints:aCollectionOfPoints |
|
2318 | 195 |
"set the collection of points through which the spline is to pass" |
278 | 196 |
|
197 |
controlPoints := aCollectionOfPoints. |
|
198 |
lines := nil |
|
199 |
||
200 |
"Created: 8.5.1996 / 18:50:24 / cg" |
|
201 |
"Modified: 8.5.1996 / 19:32:57 / cg" |
|
202 |
! ! |
|
203 |
||
204 |
!Spline methodsFor:'converting'! |
|
205 |
||
283 | 206 |
asPointArray |
207 |
"return an array containing my approximated vertex points." |
|
208 |
||
209 |
^ self computeLineSegments |
|
210 |
||
211 |
"Created: 8.5.1996 / 20:44:09 / cg" |
|
212 |
! |
|
213 |
||
280 | 214 |
asPolygon |
278 | 215 |
"return a polygon, approximating the spline" |
216 |
||
217 |
^ Polygon vertices:(self computeLineSegments) |
|
218 |
||
280 | 219 |
"Created: 8.5.1996 / 20:15:37 / cg" |
220 |
! |
|
221 |
||
222 |
asPolyline |
|
223 |
"same as #asPolygon - for ST-80 compatibility" |
|
224 |
||
225 |
^ self asPolygon |
|
226 |
||
278 | 227 |
"Created: 8.5.1996 / 18:49:42 / cg" |
280 | 228 |
"Modified: 8.5.1996 / 20:15:59 / cg" |
278 | 229 |
! ! |
230 |
||
231 |
!Spline methodsFor:'displaying'! |
|
232 |
||
233 |
displayFilledOn:aGC |
|
234 |
"Display this Spline as a filled polygon from approximated lines." |
|
235 |
||
236 |
lines isNil ifTrue:[ |
|
237 |
lines := self computeLineSegments. |
|
238 |
]. |
|
239 |
||
240 |
aGC fillPolygon:lines |
|
241 |
||
242 |
"Modified: 8.5.1996 / 18:45:49 / cg" |
|
243 |
"Created: 8.5.1996 / 18:54:12 / cg" |
|
244 |
! |
|
245 |
||
246 |
displayStrokedOn:aGC |
|
247 |
"Display this Spline as a series of approximating lines." |
|
248 |
||
249 |
lines isNil ifTrue:[ |
|
250 |
lines := self computeLineSegments. |
|
251 |
]. |
|
252 |
||
253 |
"/ Plot the lines |
|
254 |
aGC displayPolygon:lines |
|
255 |
||
256 |
"Created: 8.5.1996 / 18:44:17 / cg" |
|
332
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
257 |
"Modified: 13.5.1996 / 11:19:14 / cg" |
278 | 258 |
! ! |
259 |
||
260 |
!Spline methodsFor:'private'! |
|
261 |
||
262 |
computeCurve |
|
263 |
"Compute an array for the derivatives at each knot." |
|
264 |
||
265 |
|size values cyclic second third secondFromLast thirdFromLast |
|
266 |
addedExtra| |
|
267 |
||
268 |
"/ Get the number of points, |
|
269 |
"/ and make an OrderedColleciton of all of the points." |
|
270 |
||
271 |
size := controlPoints size. |
|
272 |
function := OrderedCollection new:size. |
|
273 |
controlPoints do:[:point | function addLast:point]. |
|
274 |
||
275 |
"/ stop if the spline has not enough points for the derivation(s). |
|
276 |
size < 3 ifTrue: [^ self]. |
|
277 |
||
278 |
"/ Flag whether curve is cyclic or not. |
|
279 |
cyclic := size > 3 and: [function first = function last]. |
|
280 |
||
281 |
"/ Set up the values collection. The derivatives are computed from this. |
|
282 |
values := function copy. |
|
283 |
||
284 |
"/ Process cyclic curves differently. |
|
285 |
"/ Add the last two points to the beginning, |
|
286 |
"/ and the first two points to the end, so that the derivative calculation |
|
287 |
"/ can look at a cycle." |
|
288 |
cyclic ifTrue: [ |
|
289 |
second := values at: 2. |
|
290 |
third := values at: 3. |
|
291 |
thirdFromLast := values at: size - 2. |
|
292 |
secondFromLast := values at: size - 1. |
|
293 |
||
294 |
values addFirst: secondFromLast. |
|
295 |
values addFirst: thirdFromLast. |
|
296 |
values addLast: second. |
|
297 |
values addLast: third |
|
298 |
] ifFalse:[ |
|
299 |
size == 3 ifTrue:[ |
|
300 |
addedExtra := true. |
|
301 |
values addLast:(values last). |
|
302 |
] ifFalse:[ |
|
303 |
addedExtra := false |
|
304 |
] |
|
305 |
]. |
|
306 |
||
307 |
"/ Compute the derivatives of the values collection. |
|
308 |
self computeDerivatives:values. |
|
309 |
||
310 |
"/ Remove any extra points which were added if the Spline is cyclic. |
|
311 |
cyclic ifTrue: [ |
|
312 |
firstDerivative removeFirst. |
|
313 |
firstDerivative removeFirst. |
|
314 |
firstDerivative removeLast. |
|
315 |
firstDerivative removeLast. |
|
316 |
secondDerivative removeFirst. |
|
317 |
secondDerivative removeFirst. |
|
318 |
secondDerivative removeLast. |
|
319 |
secondDerivative removeLast. |
|
320 |
thirdDerivative removeFirst. |
|
321 |
thirdDerivative removeFirst. |
|
322 |
thirdDerivative removeLast. |
|
323 |
thirdDerivative removeLast |
|
324 |
] ifFalse:[ |
|
325 |
addedExtra ifTrue:[ |
|
326 |
firstDerivative removeLast. |
|
327 |
secondDerivative removeLast. |
|
328 |
thirdDerivative removeLast. |
|
329 |
] |
|
330 |
] |
|
331 |
||
332 |
"Created: 8.5.1996 / 18:34:43 / cg" |
|
333 |
"Modified: 8.5.1996 / 19:43:51 / cg" |
|
334 |
! |
|
335 |
||
336 |
computeDerivatives: values |
|
337 |
"Computes the first, second and third derivatives at each point |
|
338 |
in the collection values." |
|
339 |
||
340 |
|size "{Class: SmallInteger }" |
|
341 |
v b |
|
342 |
lastV lastB nextV nextB |
|
343 |
valuesI valuesI1 valuesI2 |
|
344 |
twoDerivI twoDerivI1| |
|
345 |
||
346 |
"/ Set up the derivative arrays. |
|
347 |
size := values size. |
|
348 |
size < 3 ifTrue: [ |
|
2902 | 349 |
'SPLINE: not enough controlPoints' errorPrintCR. |
278 | 350 |
^ self |
351 |
]. |
|
352 |
||
353 |
firstDerivative := Array new:size. |
|
354 |
secondDerivative := Array new:size. |
|
355 |
thirdDerivative := Array new:size. |
|
356 |
||
357 |
"/ Compute the second derivative of the values. |
|
358 |
size > 3 ifTrue: [ |
|
359 |
lastV := 4.0. |
|
360 |
lastB := 6.0 * (values first - ((values at:2) * 2.0) + (values at:3)). |
|
361 |
v := Array new:size. |
|
362 |
b := Array new:size. |
|
363 |
v at: 1 put:lastV. |
|
364 |
b at: 1 put:lastB. |
|
365 |
valuesI := values at:2. |
|
366 |
valuesI1 := values at:3. |
|
367 |
size > 3 ifTrue: [valuesI2 := values at:4]. |
|
368 |
||
369 |
2 to:size-2 do: [:i | |
|
370 |
nextV := 4.0 - (1.0 / lastV). |
|
371 |
nextB := 6.0 * (valuesI - (valuesI1 * 2.0) + valuesI2) - (lastB / lastV). |
|
372 |
v at:i put:nextV. |
|
373 |
b at:i put:nextB. |
|
374 |
||
375 |
size-2 == i ifFalse: [ |
|
376 |
lastV := nextV. |
|
377 |
lastB := nextB. |
|
378 |
valuesI := valuesI1. |
|
379 |
valuesI1 := valuesI2. |
|
380 |
valuesI2 := values at:i+3 |
|
381 |
] |
|
382 |
]. |
|
383 |
||
384 |
secondDerivative at:size-1 put:nextB/nextV. |
|
385 |
||
386 |
size-2 to:2 by:-1 do: [:i | |
|
387 |
secondDerivative at:i |
|
388 |
put:(b at:i-1) |
|
389 |
- (secondDerivative at:i+1) / (v at:i-1) |
|
390 |
] |
|
391 |
]. |
|
392 |
||
393 |
secondDerivative at:1 put:0.0 asPoint. |
|
394 |
secondDerivative at:size put:0.0 asPoint. |
|
395 |
||
396 |
"/ Compute the values of the first and third derivative |
|
397 |
"/ from the second derivative and the values. |
|
398 |
||
399 |
valuesI := values at:1. |
|
400 |
valuesI1 := values at:2. |
|
401 |
twoDerivI := secondDerivative at:1. |
|
402 |
twoDerivI1 := secondDerivative at:2. |
|
403 |
1 to:size-1 do:[:i | |
|
404 |
firstDerivative at:i put:valuesI1 - valuesI - (twoDerivI * 2.0 + twoDerivI1 / 6.0). |
|
405 |
thirdDerivative at:i put:twoDerivI1 - twoDerivI. |
|
406 |
||
407 |
size-1 == i ifFalse:[ |
|
408 |
twoDerivI := twoDerivI1. |
|
409 |
twoDerivI1 := secondDerivative at:i+2. |
|
410 |
valuesI := valuesI1. |
|
411 |
valuesI1 := values at:i+2 |
|
412 |
] |
|
413 |
]. |
|
414 |
||
415 |
"/ The derivative collections should be OrderedCollections. |
|
416 |
||
417 |
firstDerivative := firstDerivative asOrderedCollection. |
|
418 |
secondDerivative := secondDerivative asOrderedCollection. |
|
419 |
thirdDerivative := thirdDerivative asOrderedCollection. |
|
420 |
||
421 |
"Created: 8.5.1996 / 18:39:31 / cg" |
|
422 |
"Modified: 8.5.1996 / 19:44:36 / cg" |
|
423 |
! |
|
424 |
||
425 |
computeLineSegments |
|
426 |
"compute a series of approximating lines." |
|
427 |
||
428 |
|lines |
|
429 |
n " {Class: SmallInteger }" |
|
430 |
nSteps " {Class: SmallInteger }" |
|
431 |
steps |
|
432 |
a b c d t| |
|
433 |
||
283 | 434 |
lines notNil ifTrue:[ ^ lines]. |
278 | 435 |
controlPoints size < 3 ifTrue:[^ controlPoints]. |
436 |
||
437 |
"/ Make sure that the function and its derivatives are up to date. |
|
438 |
self validateDerivatives. |
|
439 |
||
440 |
"/ Create a polygon for plotting. |
|
441 |
lines := OrderedCollection new. |
|
442 |
lines add:function first. |
|
443 |
||
444 |
"/ Approximate each spline knot. |
|
445 |
||
446 |
n := function size - 1. |
|
447 |
||
448 |
1 to:n do: [:k | |
|
449 |
"/ Compute the Taylor series coefficients. |
|
450 |
d := function at:k. |
|
451 |
c := firstDerivative at:k. |
|
452 |
b := (secondDerivative at:k) / 2.0. |
|
453 |
a := (thirdDerivative at:k) / 6.0. |
|
454 |
||
455 |
"/ Compute the number of approximating segments. |
|
456 |
steps := (secondDerivative at:k) abs + (secondDerivative at:k + 1) abs. |
|
457 |
steps := 5 max:(steps x + steps y) // 100. |
|
458 |
||
459 |
"/ Add each of the approximating line segments. |
|
460 |
nSteps := steps. |
|
461 |
1 to:nSteps do:[:j | |
|
462 |
t := j asFloat / steps. |
|
463 |
lines add: a * t + b * t + c * t + d |
|
464 |
]. |
|
465 |
||
466 |
"/ Add the last line to the real spline endpoint. |
|
467 |
lines add: (function at: k + 1) |
|
468 |
]. |
|
469 |
||
470 |
^ lines |
|
471 |
||
472 |
"Created: 8.5.1996 / 18:44:54 / cg" |
|
283 | 473 |
"Modified: 8.5.1996 / 20:45:10 / cg" |
278 | 474 |
! |
475 |
||
476 |
validateDerivatives |
|
477 |
"Make sure that the function and derivative arrays are still valid. |
|
478 |
If they are not, recompute them." |
|
479 |
||
480 |
|index "{ Class: SmallInteger }"| |
|
481 |
||
482 |
"/ |
|
483 |
"/ Compute the derivatives if the cached function has not been computed. |
|
484 |
"/ |
|
485 |
function isNil ifTrue:[ |
|
486 |
^ self computeCurve |
|
487 |
]. |
|
488 |
||
489 |
"/ Compute the derivatives if the cached function |
|
490 |
"/ and the collection of points do not agree." |
|
491 |
||
492 |
index := 1. |
|
493 |
controlPoints do:[:point | |
|
494 |
point ~~ (function at:index) ifTrue:[ |
|
495 |
^ self computeCurve |
|
496 |
]. |
|
497 |
index := index + 1 |
|
498 |
] |
|
499 |
||
500 |
"Created: 8.5.1996 / 18:31:46 / cg" |
|
501 |
"Modified: 8.5.1996 / 18:32:39 / cg" |
|
502 |
! ! |
|
503 |
||
504 |
!Spline methodsFor:'queries'! |
|
505 |
||
490
ef43c7a69346
added dummy Scale & InverseScale classVars.
Claus Gittinger <cg@exept.de>
parents:
388
diff
changeset
|
506 |
computeBounds |
327 | 507 |
"return the smallest enclosing rectangle" |
508 |
||
332
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
509 |
|l minX maxX minY maxY| |
327 | 510 |
|
332
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
511 |
lines isNil ifTrue:[ |
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
512 |
lines := self computeLineSegments. |
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
513 |
]. |
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
514 |
l := lines. |
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
515 |
|
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
516 |
minX := maxX := l first x rounded. |
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
517 |
minY := maxY := l first y rounded. |
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
518 |
l do:[:p | |
327 | 519 |
|x y| |
520 |
||
332
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
521 |
(x := p x rounded) < minX ifTrue:[ |
327 | 522 |
minX := x |
523 |
] ifFalse:[ |
|
524 |
x > maxX ifTrue:[ |
|
525 |
maxX := x |
|
526 |
] |
|
527 |
]. |
|
388 | 528 |
(y := p y rounded) < minY ifTrue:[ |
327 | 529 |
minY := y |
530 |
] ifFalse:[ |
|
531 |
y > maxY ifTrue:[ |
|
532 |
maxY := y |
|
533 |
] |
|
534 |
]. |
|
535 |
]. |
|
536 |
||
537 |
^ Rectangle left:minX right:maxX top:minY bottom:maxY |
|
538 |
||
332
bb2dd1a968c2
bounds may be larger than controlPoint-bounds
Claus Gittinger <cg@exept.de>
parents:
331
diff
changeset
|
539 |
"Modified: 13.5.1996 / 11:02:29 / cg" |
490
ef43c7a69346
added dummy Scale & InverseScale classVars.
Claus Gittinger <cg@exept.de>
parents:
388
diff
changeset
|
540 |
"Created: 12.2.1997 / 11:45:02 / cg" |
374
a77f804c605e
added #canBeFilled for protocol completeness
Claus Gittinger <cg@exept.de>
parents:
332
diff
changeset
|
541 |
! |
a77f804c605e
added #canBeFilled for protocol completeness
Claus Gittinger <cg@exept.de>
parents:
332
diff
changeset
|
542 |
|
278 | 543 |
isCyclic |
544 |
"return true, if this spline represents a closed curve" |
|
545 |
||
546 |
^ controlPoints size > 3 and: [controlPoints first = controlPoints last]. |
|
547 |
||
548 |
"Created: 8.5.1996 / 18:47:50 / cg" |
|
549 |
! ! |
|
550 |
||
2159 | 551 |
!Spline methodsFor:'testing'! |
552 |
||
553 |
canBeFilled |
|
554 |
"return true, if the receiver can be drawn as a filled geometric. |
|
555 |
Always true here." |
|
556 |
||
557 |
^ true |
|
558 |
||
559 |
! ! |
|
560 |
||
278 | 561 |
!Spline class methodsFor:'documentation'! |
562 |
||
563 |
version |
|
2902 | 564 |
^ '$Header: /cvs/stx/stx/libbasic2/Spline.st,v 1.19 2013-02-08 20:45:16 cg Exp $' |
2318 | 565 |
! |
566 |
||
567 |
version_CVS |
|
2902 | 568 |
^ '$Header: /cvs/stx/stx/libbasic2/Spline.st,v 1.19 2013-02-08 20:45:16 cg Exp $' |
278 | 569 |
! ! |
2902 | 570 |