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