The Inbox: ST80-mt.265.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

The Inbox: ST80-mt.265.mcz

commits-2
A new version of ST80 was added to project The Inbox:
http://source.squeak.org/inbox/ST80-mt.265.mcz

==================== Summary ====================

Name: ST80-mt.265
Author: mt
Time: 9 March 2021, 1:33:39.525921 pm
UUID: 1b02e796-d790-b34d-9f4f-dd406f43e130
Ancestors: ST80-mt.264

Free the names Path, Arc, Circle, Line, Spline to be used in a prospective Math package.

=============== Diff against ST80-mt.264 ===============

Item was removed:
- Path subclass: #Arc
- instanceVariableNames: 'quadrant radius center'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Arc commentStamp: '<historical>' prior: 0!
- Arcs are an unusual implementation of splines due to Ted Kaehler.  Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner.  Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern).  By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines.  Voila.!

Item was removed:
- ----- Method: Arc class>>example (in category 'examples') -----
- example
- "Click the button somewhere on the screen. The designated point will
- be the center of an Arc with radius 50 in the 4th quadrant."
-
- | anArc aForm |
- aForm := Form extent: 1 @ 30. "make a long thin Form for display"
- aForm fillBlack. "turn it black"
- anArc := Arc new.
- anArc form: aForm. "set the form for display"
- anArc radius: 50.0.
- anArc center: Sensor waitButton.
- anArc quadrant: 4.
- anArc displayOn: Display.
- Sensor waitButton
-
- "Arc example"!

Item was removed:
- ----- Method: Arc>>center (in category 'accessing') -----
- center
- "Answer the point at the center of the receiver."
-
- ^center!

Item was removed:
- ----- Method: Arc>>center: (in category 'accessing') -----
- center: aPoint
- "Set aPoint to be the receiver's center."
-
- center := aPoint!

Item was removed:
- ----- Method: Arc>>center:radius: (in category 'accessing') -----
- center: aPoint radius: anInteger
- "The receiver is defined by a point at the center and a radius. The
- quadrant is not reset."
-
- center := aPoint.
- radius := anInteger!

Item was removed:
- ----- Method: Arc>>center:radius:quadrant: (in category 'accessing') -----
- center: aPoint radius: anInteger quadrant: section
- "Set the receiver's quadrant to be the argument, section. The size of the
- receiver is defined by the center and its radius."
-
- center := aPoint.
- radius := anInteger.
- quadrant := section!

Item was removed:
- ----- Method: Arc>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
- | aRectangle aPoint |
- aRectangle := center - radius + form offset extent: form extent + (radius * 2) asPoint.
- aPoint := center + form extent.
- quadrant = 1 ifTrue: [^ aRectangle encompass: center x @ aPoint y].
- quadrant = 2 ifTrue: [^ aRectangle encompass: aPoint x @ aPoint y].
- quadrant = 3 ifTrue: [^ aRectangle encompass: aPoint x @ center y].
- quadrant = 4 ifTrue: [^ aRectangle encompass: center x @ center y]!

Item was removed:
- ----- Method: Arc>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | nSegments line angle sin cos xn yn |
- nSegments := 12.0.
- line := Line new.
- line form: self form.
- angle := (90.0 / nSegments) degreesToRadians.
- sin := angle sin.
- cos := angle cos.
- quadrant = 1
- ifTrue:
- [xn := radius asFloat.
- yn := 0.0].
- quadrant = 2
- ifTrue:
- [xn := 0.0.
- yn := 0.0 - radius asFloat].
- quadrant = 3
- ifTrue:
- [xn := 0.0 - radius asFloat.
- yn := 0.0].
- quadrant = 4
- ifTrue:
- [xn := 0.0.
- yn := radius asFloat].
- nSegments asInteger
- timesRepeat:
- [ | xn1 yn1 |
- xn1 := xn * cos + (yn * sin).
- yn1 := yn * cos - (xn * sin).
- line beginPoint: center + (xn asInteger @ yn asInteger).
- line endPoint: center + (xn1 asInteger @ yn1 asInteger).
- line
- displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm.
- xn := xn1.
- yn := yn1]!

Item was removed:
- ----- Method: Arc>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | newArc tempCenter |
- newArc := Arc new.
- tempCenter := aTransformation applyTo: self center.
- newArc center: tempCenter x asInteger @ tempCenter y asInteger.
- newArc quadrant: self quadrant.
- newArc radius: (self radius * aTransformation scale x) asInteger.
- newArc form: self form.
- newArc
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Arc>>quadrant (in category 'accessing') -----
- quadrant
- "Answer the part of the circle represented by the receiver."
- ^quadrant!

Item was removed:
- ----- Method: Arc>>quadrant: (in category 'accessing') -----
- quadrant: section
- "Set the part of the circle represented by the receiver to be the argument,
- section."
-
- quadrant := section!

Item was removed:
- ----- Method: Arc>>radius (in category 'accessing') -----
- radius
- "Answer the receiver's radius."
-
- ^radius!

Item was removed:
- ----- Method: Arc>>radius: (in category 'accessing') -----
- radius: anInteger
- "Set the receiver's radius to be the argument, anInteger."
-
- radius := anInteger!

Item was removed:
- Arc subclass: #Circle
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Circle commentStamp: '<historical>' prior: 0!
- I represent a full circle. I am made from four Arcs.!

Item was removed:
- ----- Method: Circle class>>exampleOne (in category 'examples') -----
- exampleOne
- "Click any button somewhere on the screen. The point will be the center
- of the circcle of radius 150."
-
- | aCircle aForm |
- aForm := Form extent: 1@30.
- aForm fillBlack.
- aCircle := Circle new.
- aCircle form: aForm.
- aCircle radius: 150.
- aCircle center: Sensor waitButton.
- aCircle displayOn: Display
-
- "Circle exampleOne"!

Item was removed:
- ----- Method: Circle class>>exampleTwo (in category 'examples') -----
- exampleTwo
- "Designate a rectangular area that should be used as the brush for
- displaying the circle. Click any button at a point on the screen which
- will be the center location for the circle. The curve will be displayed
- with a long black form."
-
- | aCircle aForm |
- aForm := Form fromUser.
- aCircle := Circle new.
- aCircle form: aForm.
- aCircle radius: 150.
- aCircle center: Sensor waitButton.
- aCircle displayOn: Display at: 0 @ 0 rule: Form reverse
-  
- "Circle exampleTwo"!

Item was removed:
- ----- Method: Circle>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
-
- ^center - radius + form offset extent: form extent + (radius * 2) asPoint!

Item was removed:
- ----- Method: Circle>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
-
- 1 to: 4 do:
- [:i |
- super quadrant: i.
- super displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: Circle>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- 1 to: 4 do:
- [:i |
- super quadrant: i.
- super displayOn: aDisplayMedium
- transformation: aTransformation
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- Path subclass: #CurveFitter
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !CurveFitter commentStamp: '<historical>' prior: 0!
- I represent a conic section determined by three points p1, p2 and p3. I interpolate p1 and p3 and am tangent to line p1, p2 at p1 and line p3, p2 at p3.!

Item was removed:
- ----- Method: CurveFitter class>>example (in category 'examples') -----
- example
- "Designate three locations on the screen by clicking any button. The
- curve determined by the points will be displayed with a long black form."
-
- | aCurveFitter aForm |  
- aForm := Form extent: 1@30. "make a long thin Form for display "
- aForm fillBlack. "turn it black"
- aCurveFitter := CurveFitter new.
- aCurveFitter form: aForm. "set the form for display"
- "collect three Points and show them on the dispaly"
- aCurveFitter firstPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aCurveFitter firstPoint.
- aCurveFitter secondPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aCurveFitter secondPoint.
- aCurveFitter thirdPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aCurveFitter thirdPoint.
-
- aCurveFitter displayOn: Display "display the CurveFitter"
-
- "CurveFitter example"!

Item was removed:
- ----- Method: CurveFitter class>>new (in category 'instance creation') -----
- new
-
- | newSelf |
- newSelf := super new: 3.
- newSelf add: 0@0.
- newSelf add: 0@0.
- newSelf add: 0@0.
- ^newSelf!

Item was removed:
- ----- Method: CurveFitter>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | pa pb k s p1 p2 p3 line |
- line := Line new.
- line form: self form.
- collectionOfPoints size < 3 ifTrue: [self error: 'Curve must have three points'].
- p1 := self firstPoint.
- p2 := self secondPoint.
- p3 := self thirdPoint.
- s := Path new.
- s add: p1.
- pa := p2 - p1.
- pb := p3 - p2.
- k := 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20.
- "k is a guess as to how many line segments to use to approximate
- the curve."
- 1 to: k do:
- [:i |
- s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) // (k - 1)].
- s add: p3.
- 1 to: s size - 1 do:
- [:i |
- line beginPoint: (s at: i).
- line endPoint: (s at: i + 1).
- line displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: CurveFitter>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | transformedPath newCurveFitter |
- transformedPath := aTransformation applyTo: self.
- newCurveFitter := CurveFitter new.
- newCurveFitter firstPoint: transformedPath firstPoint.
- newCurveFitter secondPoint: transformedPath secondPoint.
- newCurveFitter thirdPoint: transformedPath thirdPoint.
- newCurveFitter form: self form.
- newCurveFitter
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was added:
+ DisplayPath subclass: #DisplayArc
+ instanceVariableNames: 'quadrant radius center'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayArc commentStamp: '<historical>' prior: 0!
+ Arcs are an unusual implementation of splines due to Ted Kaehler.  Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner.  Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern).  By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines.  Voila.!

Item was added:
+ ----- Method: DisplayArc class>>example (in category 'examples') -----
+ example
+ "Click the button somewhere on the screen. The designated point will
+ be the center of an DisplayArc with radius 50 in the 4th quadrant."
+
+ | anDisplayArc aForm |
+ aForm := Form extent: 1 @ 30. "make a long thin Form for display"
+ aForm fillBlack. "turn it black"
+ anDisplayArc := DisplayArc new.
+ anDisplayArc form: aForm. "set the form for display"
+ anDisplayArc radius: 50.0.
+ anDisplayArc center: Sensor waitButton.
+ anDisplayArc quadrant: 4.
+ anDisplayArc displayOn: Display.
+ Sensor waitButton
+
+ "DisplayArc example"!

Item was added:
+ ----- Method: DisplayArc>>center (in category 'accessing') -----
+ center
+ "Answer the point at the center of the receiver."
+
+ ^center!

Item was added:
+ ----- Method: DisplayArc>>center: (in category 'accessing') -----
+ center: aPoint
+ "Set aPoint to be the receiver's center."
+
+ center := aPoint!

Item was added:
+ ----- Method: DisplayArc>>center:radius: (in category 'accessing') -----
+ center: aPoint radius: anInteger
+ "The receiver is defined by a point at the center and a radius. The
+ quadrant is not reset."
+
+ center := aPoint.
+ radius := anInteger!

Item was added:
+ ----- Method: DisplayArc>>center:radius:quadrant: (in category 'accessing') -----
+ center: aPoint radius: anInteger quadrant: section
+ "Set the receiver's quadrant to be the argument, section. The size of the
+ receiver is defined by the center and its radius."
+
+ center := aPoint.
+ radius := anInteger.
+ quadrant := section!

Item was added:
+ ----- Method: DisplayArc>>computeBoundingBox (in category 'display box access') -----
+ computeBoundingBox
+ | aRectangle aPoint |
+ aRectangle := center - radius + form offset extent: form extent + (radius * 2) asPoint.
+ aPoint := center + form extent.
+ quadrant = 1 ifTrue: [^ aRectangle encompass: center x @ aPoint y].
+ quadrant = 2 ifTrue: [^ aRectangle encompass: aPoint x @ aPoint y].
+ quadrant = 3 ifTrue: [^ aRectangle encompass: aPoint x @ center y].
+ quadrant = 4 ifTrue: [^ aRectangle encompass: center x @ center y]!

Item was added:
+ ----- Method: DisplayArc>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | nSegments line angle sin cos xn yn |
+ nSegments := 12.0.
+ line := DisplayLine new.
+ line form: self form.
+ angle := (90.0 / nSegments) degreesToRadians.
+ sin := angle sin.
+ cos := angle cos.
+ quadrant = 1
+ ifTrue:
+ [xn := radius asFloat.
+ yn := 0.0].
+ quadrant = 2
+ ifTrue:
+ [xn := 0.0.
+ yn := 0.0 - radius asFloat].
+ quadrant = 3
+ ifTrue:
+ [xn := 0.0 - radius asFloat.
+ yn := 0.0].
+ quadrant = 4
+ ifTrue:
+ [xn := 0.0.
+ yn := radius asFloat].
+ nSegments asInteger
+ timesRepeat:
+ [ | xn1 yn1 |
+ xn1 := xn * cos + (yn * sin).
+ yn1 := yn * cos - (xn * sin).
+ line beginPoint: center + (xn asInteger @ yn asInteger).
+ line endPoint: center + (xn1 asInteger @ yn1 asInteger).
+ line
+ displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm.
+ xn := xn1.
+ yn := yn1]!

Item was added:
+ ----- Method: DisplayArc>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | newDisplayArc tempCenter |
+ newDisplayArc := DisplayArc new.
+ tempCenter := aTransformation applyTo: self center.
+ newDisplayArc center: tempCenter x asInteger @ tempCenter y asInteger.
+ newDisplayArc quadrant: self quadrant.
+ newDisplayArc radius: (self radius * aTransformation scale x) asInteger.
+ newDisplayArc form: self form.
+ newDisplayArc
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayArc>>quadrant (in category 'accessing') -----
+ quadrant
+ "Answer the part of the circle represented by the receiver."
+ ^quadrant!

Item was added:
+ ----- Method: DisplayArc>>quadrant: (in category 'accessing') -----
+ quadrant: section
+ "Set the part of the circle represented by the receiver to be the argument,
+ section."
+
+ quadrant := section!

Item was added:
+ ----- Method: DisplayArc>>radius (in category 'accessing') -----
+ radius
+ "Answer the receiver's radius."
+
+ ^radius!

Item was added:
+ ----- Method: DisplayArc>>radius: (in category 'accessing') -----
+ radius: anInteger
+ "Set the receiver's radius to be the argument, anInteger."
+
+ radius := anInteger!

Item was added:
+ DisplayArc subclass: #DisplayCircle
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayCircle commentStamp: '<historical>' prior: 0!
+ I represent a full circle. I am made from four Arcs.!

Item was added:
+ ----- Method: DisplayCircle class>>exampleOne (in category 'examples') -----
+ exampleOne
+ "Click any button somewhere on the screen. The point will be the center
+ of the circcle of radius 150."
+
+ | aDisplayCircle aForm |
+ aForm := Form extent: 1@30.
+ aForm fillBlack.
+ aDisplayCircle := DisplayCircle new.
+ aDisplayCircle form: aForm.
+ aDisplayCircle radius: 150.
+ aDisplayCircle center: Sensor waitButton.
+ aDisplayCircle displayOn: Display
+
+ "DisplayCircle exampleOne"!

Item was added:
+ ----- Method: DisplayCircle class>>exampleTwo (in category 'examples') -----
+ exampleTwo
+ "Designate a rectangular area that should be used as the brush for
+ displaying the circle. Click any button at a point on the screen which
+ will be the center location for the circle. The curve will be displayed
+ with a long black form."
+
+ | aDisplayCircle aForm |
+ aForm := Form fromUser.
+ aDisplayCircle := DisplayCircle new.
+ aDisplayCircle form: aForm.
+ aDisplayCircle radius: 150.
+ aDisplayCircle center: Sensor waitButton.
+ aDisplayCircle displayOn: Display at: 0 @ 0 rule: Form reverse
+  
+ "DisplayCircle exampleTwo"!

Item was added:
+ ----- Method: DisplayCircle>>computeBoundingBox (in category 'display box access') -----
+ computeBoundingBox
+
+ ^center - radius + form offset extent: form extent + (radius * 2) asPoint!

Item was added:
+ ----- Method: DisplayCircle>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ 1 to: 4 do:
+ [:i |
+ super quadrant: i.
+ super displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayCircle>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ 1 to: 4 do:
+ [:i |
+ super quadrant: i.
+ super displayOn: aDisplayMedium
+ transformation: aTransformation
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ DisplayPath subclass: #DisplayCurveFitter
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayCurveFitter commentStamp: '<historical>' prior: 0!
+ I represent a conic section determined by three points p1, p2 and p3. I interpolate p1 and p3 and am tangent to line p1, p2 at p1 and line p3, p2 at p3.!

Item was added:
+ ----- Method: DisplayCurveFitter class>>example (in category 'examples') -----
+ example
+ "Designate three locations on the screen by clicking any button. The
+ curve determined by the points will be displayed with a long black form."
+
+ | aDisplayCurveFitter aForm |  
+ aForm := Form extent: 1@30. "make a long thin Form for display "
+ aForm fillBlack. "turn it black"
+ aDisplayCurveFitter := DisplayCurveFitter new.
+ aDisplayCurveFitter form: aForm. "set the form for display"
+ "collect three Points and show them on the dispaly"
+ aDisplayCurveFitter firstPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayCurveFitter firstPoint.
+ aDisplayCurveFitter secondPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayCurveFitter secondPoint.
+ aDisplayCurveFitter thirdPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayCurveFitter thirdPoint.
+
+ aDisplayCurveFitter displayOn: Display "display the DisplayCurveFitter"
+
+ "DisplayCurveFitter example"!

Item was added:
+ ----- Method: DisplayCurveFitter class>>new (in category 'instance creation') -----
+ new
+
+ | newSelf |
+ newSelf := super new: 3.
+ newSelf add: 0@0.
+ newSelf add: 0@0.
+ newSelf add: 0@0.
+ ^newSelf!

Item was added:
+ ----- Method: DisplayCurveFitter>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | pa pb k s p1 p2 p3 line |
+ line := DisplayLine new.
+ line form: self form.
+ collectionOfPoints size < 3 ifTrue: [self error: 'Curve must have three points'].
+ p1 := self firstPoint.
+ p2 := self secondPoint.
+ p3 := self thirdPoint.
+ s := DisplayPath new.
+ s add: p1.
+ pa := p2 - p1.
+ pb := p3 - p2.
+ k := 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20.
+ "k is a guess as to how many line segments to use to approximate
+ the curve."
+ 1 to: k do:
+ [:i |
+ s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) // (k - 1)].
+ s add: p3.
+ 1 to: s size - 1 do:
+ [:i |
+ line beginPoint: (s at: i).
+ line endPoint: (s at: i + 1).
+ line displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayCurveFitter>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | transformedPath newDisplayCurveFitter |
+ transformedPath := aTransformation applyTo: self.
+ newDisplayCurveFitter := DisplayCurveFitter new.
+ newDisplayCurveFitter firstPoint: transformedPath firstPoint.
+ newDisplayCurveFitter secondPoint: transformedPath secondPoint.
+ newDisplayCurveFitter thirdPoint: transformedPath thirdPoint.
+ newDisplayCurveFitter form: self form.
+ newDisplayCurveFitter
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ DisplayPath subclass: #DisplayLine
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayLine commentStamp: '<historical>' prior: 0!
+ I represent the line segment specified by two points.!

Item was added:
+ ----- Method: DisplayLine class>>example (in category 'examples') -----
+ example
+ "Designate two places on the screen by clicking any mouse button. A
+ straight path with a square black form will be displayed connecting the
+ two selected points."
+
+ | aDisplayLine aForm |  
+ aForm := Form extent: 20@20. "make a form one quarter of inch square"
+ aForm fillBlack. "turn it black"
+ aDisplayLine := DisplayLine new.
+ aDisplayLine form: aForm. "use the black form for display"
+ aDisplayLine beginPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayLine beginPoint.
+ aDisplayLine endPoint: Sensor waitButton.
+ aDisplayLine displayOn: Display. "display the line"
+
+ "DisplayLine example"!

Item was added:
+ ----- Method: DisplayLine class>>from:to:withForm: (in category 'instance creation') -----
+ from: beginPoint to: endPoint withForm: aForm
+ "Answer an instance of me with end points begingPoint and endPoint;
+ the source form for displaying the line is aForm."
+
+ | newSelf |
+ newSelf := super new: 2.
+ newSelf add: beginPoint.
+ newSelf add: endPoint.
+ newSelf form: aForm.
+ ^newSelf!

Item was added:
+ ----- Method: DisplayLine class>>new (in category 'instance creation') -----
+ new
+
+ | newSelf |
+ newSelf := super new: 2.
+ newSelf add: 0@0.
+ newSelf add: 0@0.
+ ^newSelf!

Item was added:
+ ----- Method: DisplayLine>>beginPoint (in category 'accessing') -----
+ beginPoint
+ "Answer the first end point of the receiver."
+
+ ^self first!

Item was added:
+ ----- Method: DisplayLine>>beginPoint: (in category 'accessing') -----
+ beginPoint: aPoint
+ "Set the first end point of the receiver to be the argument, aPoint.
+ Answer aPoint."
+
+ self at: 1 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayLine>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+ "The form associated with this Path will be displayed, according  
+ to one of the sixteen functions of two logical variables (rule), at  
+ each point on the Line. Also the source form will be first anded  
+ with aForm as a mask. Does not effect the state of the Path."
+
+ collectionOfPoints size < 2 ifTrue: [self error: 'a line must have two points'].
+ aDisplayMedium
+ drawLine: self form
+ from: self beginPoint + aPoint
+ to: self endPoint + aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayLine>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | newPath newDisplayLine |
+ newPath := aTransformation applyTo: self.
+ newDisplayLine := DisplayLine new.
+ newDisplayLine beginPoint: newPath firstPoint.
+ newDisplayLine endPoint: newPath secondPoint.
+ newDisplayLine form: self form.
+ newDisplayLine
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayLine>>displayOnPort:at: (in category 'displaying') -----
+ displayOnPort: aPort at: aPoint
+ aPort sourceForm: self form; combinationRule: Form under; fillColor: nil.
+ aPort drawFrom: collectionOfPoints first + aPoint
+ to: collectionOfPoints last + aPoint!

Item was added:
+ ----- Method: DisplayLine>>endPoint (in category 'accessing') -----
+ endPoint
+ "Answer the last end point of the receiver."
+
+ ^self last!

Item was added:
+ ----- Method: DisplayLine>>endPoint: (in category 'accessing') -----
+ endPoint: aPoint
+ "Set the first end point of the receiver to be the argument, aPoint.
+ Answer aPoint."
+
+ self at: 2 put: aPoint.
+ ^aPoint!

Item was added:
+ DisplayPath subclass: #DisplayLinearFit
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayLinearFit commentStamp: '<historical>' prior: 0!
+ I represent a piece-wise linear approximation to a set of points in the plane.!

Item was added:
+ ----- Method: DisplayLinearFit class>>example (in category 'examples') -----
+ example
+ "Select points on a Path using the red button. Terminate by selecting
+ any other button. Creates a Path from the points and displays it as a
+ piece-wise linear approximation."
+
+ | aDisplayLinearFit aForm flag |
+ aDisplayLinearFit := DisplayLinearFit new.
+ aForm := Form extent: 1 @ 40.
+ aForm  fillBlack.
+ aDisplayLinearFit form: aForm.
+ flag := true.
+ [flag] whileTrue:
+ [Sensor waitButton.
+ Sensor redButtonPressed
+ ifTrue: [aDisplayLinearFit add: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayLinearFit last]
+ ifFalse: [flag:=false]].
+ aDisplayLinearFit displayOn: Display
+
+ "DisplayLinearFit example"!

Item was added:
+ ----- Method: DisplayLinearFit>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger
+ fillColor: aForm
+  
+ | line |
+ line := DisplayLine new.
+ line form: self form.
+ 1 to: self size - 1 do:
+ [:i |
+ line beginPoint: (self at: i).
+ line endPoint: (self at: i + 1).
+ line displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayLinearFit>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox:
+ clipRect rule: anInteger fillColor: aForm
+
+ | transformedPath |
+ "get the scaled and translated Path."
+ transformedPath := aTransformation applyTo: self.
+ transformedPath
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ DisplayObject subclass: #DisplayPath
+ instanceVariableNames: 'form collectionOfPoints'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayPath commentStamp: '<historical>' prior: 0!
+ I am the abstract superclass of the Graphic spatial primitives. I represent an ordered sequence of Points. Spatial primitives are used to generate "trajectories" such as lines and circles.!

Item was added:
+ ----- Method: DisplayPath class>>example (in category 'examples') -----
+ example
+ "Creates a DisplayPath from mousePoints and displays it several ways on the display screen. Messes up the display. For learning about class DisplayPath, just select the code below and execute it to create a path and see it redisplayed in another place on the screen. Each path displays using a different form. A path is indicated by pressing the red mouse button in a sequence; press any other mouse button to terminate. "
+
+ | aDisplayPath aForm pl fl flag |
+ aForm := Form extent: 2 @ 40. "creates a form one inch long"
+ aForm fillBlack. "turns it black"
+ aDisplayPath := DisplayPath new.
+ aDisplayPath form: aForm. "use the long black form for displaying"
+ flag := true.
+ [flag]
+ whileTrue:
+ [Sensor waitButton.
+ Sensor redButtonPressed
+ ifTrue:
+ [aDisplayPath add: Sensor waitButton.
+ Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayPath last]
+ ifFalse: [flag := false]].
+ Display fillWhite.
+ aDisplayPath displayOn: Display. "the original path"
+ pl := aDisplayPath translateBy: 0 @ 100.
+ fl := Form extent: 40 @ 40.
+ fl fillGray.
+ pl form: fl.
+ pl displayOn: Display. "the translated path"
+ Sensor waitNoButton
+
+ "DisplayPath example"!

Item was added:
+ ----- Method: DisplayPath class>>new (in category 'instance creation') -----
+ new
+
+ ^self basicNew initializeCollectionOfPoints!

Item was added:
+ ----- Method: DisplayPath class>>new: (in category 'instance creation') -----
+ new: anInteger
+
+ ^self basicNew initializeCollectionOfPoints: anInteger!

Item was added:
+ ----- Method: DisplayPath>>add: (in category 'adding') -----
+ add: aPoint
+ "Include aPoint as one of the receiver's elements."
+
+ ^collectionOfPoints add: aPoint!

Item was added:
+ ----- Method: DisplayPath>>at: (in category 'accessing') -----
+ at: index
+ "Answer the point on the receiver's path at position index."
+
+ ^collectionOfPoints at: index!

Item was added:
+ ----- Method: DisplayPath>>at:put: (in category 'accessing') -----
+ at: index put: aPoint
+ "Store the argument, aPoint, as the point on the receiver's path at position
+ index."
+
+ ^collectionOfPoints at: index put: aPoint!

Item was added:
+ ----- Method: DisplayPath>>collect: (in category 'enumerating') -----
+ collect: aBlock
+ "Evaluate aBlock with each of the receiver's elements as the argument.
+ Collect the resulting values into a path that is like the receiver. Answer
+ the new path."
+
+ | newCollection |
+ newCollection := collectionOfPoints collect: aBlock.
+ newCollection form: self form.
+ ^newCollection!

Item was added:
+ ----- Method: DisplayPath>>computeBoundingBox (in category 'display box access') -----
+ computeBoundingBox
+ "Refer to the comment in DisplayObject|computeBoundingBox."
+
+ | box |
+ box := Rectangle origin: (self at: 1) extent: 0 @ 0.
+ collectionOfPoints do:
+ [:aPoint | box swallow: (Rectangle origin: aPoint extent: 0 @ 0)].
+ ^box!

Item was added:
+ ----- Method: DisplayPath>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
+ "Display this Path--offset by aPoint, clipped by clipRect and the form
+ associated with this Path will be displayedr according to one of the sixteen
+ functions of two logical variables (rule). Also the source form will be first
+ anded with aForm as a mask. Does not effect the state of the Path"
+
+ collectionOfPoints do:
+ [:element |
+ self form
+ displayOn: aDisplayMedium
+ at: element + aDisplayPoint
+ clippingBox: clipRectangle
+ rule: ruleInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayPath>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
+ "Displays this path, translated and scaled by aTransformation. Get the
+ scaled and translated DisplayPath."
+
+ | newDisplayPath transformedDisplayPath |
+ transformedDisplayPath := displayTransformation applyTo: self.
+ newDisplayPath := DisplayPath new.
+ transformedDisplayPath do: [:point | newDisplayPath add: point].
+ newDisplayPath form: self form.
+ newDisplayPath
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRectangle
+ rule: ruleInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayPath>>first (in category 'accessing') -----
+ first
+ "Answer the first point on the receiver's path; included to correspond to
+ OrderedCollection protocol."
+
+ ^collectionOfPoints first!

Item was added:
+ ----- Method: DisplayPath>>firstPoint (in category 'accessing') -----
+ firstPoint
+ "Answer the first point on the receiver's path."
+
+ ^collectionOfPoints first!

Item was added:
+ ----- Method: DisplayPath>>firstPoint: (in category 'accessing') -----
+ firstPoint: aPoint
+ "Replace the first element of the receiver with the new value aPoint.
+ Answer the argument aPoint."
+
+ collectionOfPoints at: 1 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayPath>>form (in category 'accessing') -----
+ form
+ "Answer the receiver's form, or, if form is nil, then answer a 1 x 1 black
+ form (a black dot)."
+
+ | aForm |
+ form == nil
+ ifTrue:
+ [aForm := Form extent: 1 @ 1.
+ aForm fillBlack.
+ ^aForm]
+ ifFalse:
+ [^form]!

Item was added:
+ ----- Method: DisplayPath>>form: (in category 'accessing') -----
+ form: aForm
+ "Make the argument, aForm, be the receiver's form."
+
+ form := aForm!

Item was added:
+ ----- Method: DisplayPath>>initializeCollectionOfPoints (in category 'private') -----
+ initializeCollectionOfPoints
+
+ collectionOfPoints := OrderedCollection new!

Item was added:
+ ----- Method: DisplayPath>>initializeCollectionOfPoints: (in category 'private') -----
+ initializeCollectionOfPoints: anInteger
+
+ collectionOfPoints := OrderedCollection new: anInteger!

Item was added:
+ ----- Method: DisplayPath>>isEmpty (in category 'testing') -----
+ isEmpty
+
+ ^collectionOfPoints isEmpty!

Item was added:
+ ----- Method: DisplayPath>>last (in category 'accessing') -----
+ last
+ "Answer the last point on the receiver's path; included to correspond to
+ OrderedCollection protocol."
+
+ ^collectionOfPoints last!

Item was added:
+ ----- Method: DisplayPath>>offset (in category 'accessing') -----
+ offset
+ "There are basically two kinds of display objects in the system: those
+ that, when asked to transform themselves, create a new object; and those
+ that side effect themselves by maintaining a record of the transformation
+ request (typically an offset). Path, like Rectangle and Point, is a display
+ object of the first kind."
+
+ self shouldNotImplement!

Item was added:
+ ----- Method: DisplayPath>>removeAllSuchThat: (in category 'removing') -----
+ removeAllSuchThat: aBlock
+ "Evaluate aBlock for each element of the receiver.
+ Remove each element for which aBlock evaluates to true."
+
+ collectionOfPoints removeAllSuchThat: aBlock.
+ !

Item was added:
+ ----- Method: DisplayPath>>scaleBy: (in category 'transforming') -----
+ scaleBy: aPoint
+ "Answers a new Path scaled by aPoint. Does not affect the current data in
+ this Path."
+
+ | newPath |
+ newPath := self species new: self size.
+ newPath form: self form.
+ collectionOfPoints do: [:element | newPath add: (element scaleBy: aPoint)].
+ ^newPath!

Item was added:
+ ----- Method: DisplayPath>>secondPoint (in category 'accessing') -----
+ secondPoint
+ "Answer the second element of the receiver."
+
+ ^collectionOfPoints at: 2!

Item was added:
+ ----- Method: DisplayPath>>secondPoint: (in category 'accessing') -----
+ secondPoint: aPoint
+ "Replace the second element of the receiver with the new value aPoint.
+ Answer the argument aPoint."
+
+ collectionOfPoints at: 2 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayPath>>select: (in category 'enumerating') -----
+ select: aBlock
+ "Evaluate aBlock with each of the receiver's elements as the argument.
+ Collect into a new path like the receiver only those elements for which
+ aBlock evaluates to true. Answer the new path."
+
+ | newCollection |
+ newCollection := collectionOfPoints select: aBlock.
+ newCollection form: self form.
+ ^newCollection!

Item was added:
+ ----- Method: DisplayPath>>size (in category 'accessing') -----
+ size
+ "Answer the length of the receiver."
+
+ ^collectionOfPoints size!

Item was added:
+ ----- Method: DisplayPath>>thirdPoint (in category 'accessing') -----
+ thirdPoint
+ "Answer the third element of the receiver."
+
+ ^collectionOfPoints at: 3!

Item was added:
+ ----- Method: DisplayPath>>thirdPoint: (in category 'accessing') -----
+ thirdPoint: aPoint
+ "Replace the third element of the receiver with the new value aPoint.
+ Answer the argument aPoint."
+
+ collectionOfPoints at: 3 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayPath>>translateBy: (in category 'transforming') -----
+ translateBy: aPoint
+ "Answers a new Path whose elements are translated by aPoint. Does not
+ affect the elements of this Path."
+
+ | newPath |
+ newPath := self species new: self size.
+ newPath form: self form.
+ collectionOfPoints do: [:element | newPath add: (element translateBy: aPoint)].
+ ^newPath!

Item was added:
+ DisplayPath subclass: #DisplaySpline
+ instanceVariableNames: 'coefficients'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplaySpline commentStamp: '<historical>' prior: 0!
+ I represent a collection of Points through which a cubic spline curve is fitted.!

Item was added:
+ ----- Method: DisplaySpline class>>example (in category 'examples') -----
+ example
+ "Designate points on the Path by clicking the red button. Terminate by
+ pressing any other button. A curve will be displayed, through the
+ selected points, using a long black form."
+
+ | splineCurve aForm flag|
+ aForm := Form extent: 2@2.
+ aForm  fillBlack.
+ splineCurve := DisplaySpline new.
+ splineCurve form: aForm.
+ flag := true.
+ [flag] whileTrue:
+ [Sensor waitButton.
+ Sensor redButtonPressed
+ ifTrue:
+ [splineCurve add: Sensor waitButton.
+ Sensor waitNoButton.
+ aForm displayOn: Display at: splineCurve last]
+ ifFalse: [flag:=false]].
+ splineCurve computeCurve.
+ splineCurve isEmpty
+ ifFalse: [splineCurve displayOn: Display.
+ Sensor waitNoButton].
+  
+ "DisplaySpline example"!

Item was added:
+ ----- Method: DisplaySpline>>coefficients (in category 'accessing') -----
+ coefficients
+ "Answer an eight-element Array of Arrays each of which is the length
+ of the receiver. The first four arrays are the values, first, second and
+ third derivatives, respectively, for the parametric spline in x. The last
+ four elements are for y."
+
+ ^coefficients!

Item was added:
+ ----- Method: DisplaySpline>>computeCurve (in category 'displaying') -----
+ computeCurve
+ "Compute an array for the coefficients."
+
+ | length extras |
+ length := self size.
+ extras := 0.
+ coefficients := Array new: 8.
+ 1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].
+ 1 to: 5 by: 4 do:
+ [:k |
+ 1 to: length do:
+ [:i | (coefficients at: k)
+ at: i put: (k = 1
+ ifTrue: [(self at: i) x asFloat]
+ ifFalse: [(self at: i) y asFloat])].
+ 1 to: extras do: [:i | (coefficients at: k)
+ at: length + i put: ((coefficients at: k)
+ at: i + 1)].
+ self derivs: (coefficients at: k)
+ first: (coefficients at: k + 1)
+ second: (coefficients at: k + 2)
+ third: (coefficients at: k + 3)].
+ extras > 0
+ ifTrue: [1 to: 8 do:
+ [:i |
+ coefficients at: i put: ((coefficients at: i)
+ copyFrom: 2 to: length + 1)]]!

Item was added:
+ ----- Method: DisplaySpline>>derivs:first:second:third: (in category 'private') -----
+ derivs: a first: point1 second: point2 third: point3
+ "Compute the first, second and third derivitives (in coefficients) from
+ the Points in this Path (coefficients at: 1 and coefficients at: 5)."
+
+ | l v anArray |
+ l := a size.
+ l < 2 ifTrue: [^self].
+ l > 2
+  ifTrue:
+ [v := Array new: l.
+ v  at:  1 put: 4.0.
+ anArray := Array new: l.
+ anArray  at:  1 put: (6.0 * ((a  at:  1) - ((a  at:  2) * 2.0) + (a  at:  3))).
+ 2 to: l - 2 do:
+ [:i |
+ v  at:  i put: (4.0 - (1.0 / (v  at:  (i - 1)))).
+ anArray
+ at:  i
+ put: (6.0 * ((a  at:  i) - ((a  at:  (i + 1)) * 2.0) + (a  at:  (i + 2)))
+ - ((anArray  at:  (i - 1)) / (v  at:  (i - 1))))].
+ point2  at: (l - 1) put: ((anArray  at:  (l - 2)) / (v  at:  (l - 2))).
+ l - 2 to: 2 by: 0-1 do:
+ [:i |
+ point2
+ at: i
+ put: ((anArray  at:  (i - 1)) - (point2  at:  (i + 1)) / (v  at:  (i - 1)))]].
+ point2 at: 1 put: (point2  at:  l put: 0.0).
+ 1 to: l - 1 do:
+ [:i | point1
+ at: i
+ put: ((a at: (i + 1)) - (a  at:  i) -
+ ((point2  at:  i) * 2.0 + (point2  at:  (i + 1)) / 6.0)).
+      point3 at: i put: ((point2  at:  (i + 1)) - (point2  at:  i))]!

Item was added:
+ ----- Method: DisplaySpline>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+ "Display the receiver, a spline curve, approximated by straight line
+ segments."
+
+ | n line t x y x1 x2 x3 y1 y2 y3 |
+ collectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point'].
+ line := DisplayLine new.
+ line form: self form.
+ line beginPoint:
+ (x := (coefficients at: 1) at: 1) rounded @ (y := (coefficients at: 5) at: 1) rounded.
+ 1 to: (coefficients at: 1) size - 1 do:
+ [:i |
+ "taylor series coefficients"
+ x1 := (coefficients at: 2) at: i.
+ y1 := (coefficients at: 6) at: i.
+ x2 := ((coefficients at: 3) at: i) / 2.0.
+ y2 := ((coefficients at: 7) at: i) / 2.0.
+ x3 := ((coefficients at: 4) at: i) / 6.0.
+ y3 := ((coefficients at: 8) at: i) / 6.0.
+ "guess n"
+ n := 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3)
+ at: i + 1) abs + ((coefficients at: 7)
+ at: i + 1) abs / 100.0) rounded.
+ 1 to: n - 1 do:
+ [:j |
+ t := j asFloat / n.
+ line endPoint:
+ (x3 * t + x2 * t + x1 * t + x) rounded
+ @ (y3 * t + y2 * t + y1 * t + y) rounded.
+ line
+ displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm.
+ line beginPoint: line endPoint].
+ line beginPoint:
+ (x := (coefficients at: 1) at: i + 1) rounded
+ @ (y := (coefficients at: 5) at: i + 1) rounded.
+ line
+ displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplaySpline>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+ "Get the scaled and translated path of newKnots."
+
+ | newKnots newDisplaySpline |
+ newKnots := aTransformation applyTo: self.
+ newDisplaySpline := DisplaySpline new.
+ newKnots do: [:knot | newDisplaySpline add: knot].
+ newDisplaySpline form: self form.
+ newDisplaySpline
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was changed:
  ----- Method: FormEditor>>curve (in category 'editing tools') -----
  curve
  "Conic-section specified by three points designated by: first point--press
  red button second point--release red button third point--click red button.
  The resultant curve on the display is displayed according to the current
  form and mode."
 
  | firstPoint secondPoint thirdPoint curve drawForm |
  "sensor noButtonPressed ifTrue: [^self]."
  firstPoint := self cursorPoint.
  secondPoint := self rubberBandFrom: firstPoint until: [sensor noButtonPressed].
  thirdPoint :=  self rubberBandFrom: secondPoint until: [sensor redButtonPressed].
  Display depth > 1
   ifTrue:
     [self deleteRubberBandFrom: secondPoint to: thirdPoint.
      self deleteRubberBandFrom: firstPoint to: secondPoint].
+ curve := DisplayCurveFitter new.
- curve := CurveFitter new.
  curve firstPoint: firstPoint.
  curve secondPoint: secondPoint.
  curve thirdPoint: thirdPoint.
  drawForm := form asFormOfDepth: Display depth.
  Display depth > 1 ifTrue:
   [drawForm mapColor: Color white to: Color transparent;
                mapColor: Color black to: color].
 
  curve form: drawForm.
  curve
  displayOn: Display
  at: 0 @ 0
  clippingBox: view insetDisplayBox
  rule: (Display depth > 1 ifTrue: [mode ~= Form erase ifTrue: [Form paint] ifFalse: [mode]]
  ifFalse: [mode])
  fillColor: (Display depth = 1 ifTrue: [color] ifFalse: [nil]).
  sensor waitNoButton.
  hasUnsavedChanges contents: true.!

Item was changed:
  ----- Method: FormEditor>>deleteRubberBandFrom:to: (in category 'private') -----
  deleteRubberBandFrom: startPoint to: endPoint
 
+ (DisplayLine from: startPoint to: endPoint withForm: form)
- (Line from: startPoint to: endPoint withForm: form)
  displayOn: Display
  at: 0 @ 0
  clippingBox: view insetDisplayBox
  rule: Form reverse
  fillColor: (Display depth = 1 ifTrue: [Color black] ifFalse: [Color gray]).!

Item was changed:
  ----- Method: FormEditor>>line (in category 'editing tools') -----
  line
+ "DisplayLine is specified by two points from the mouse: first point--press red
- "Line is specified by two points from the mouse: first point--press red
  button; second point--release red button. The resultant line is displayed
  according to the current form and mode."
 
  | firstPoint endPoint drawForm |
  drawForm := form asFormOfDepth: Display depth.
 
  Display depth > 1
   ifTrue:
     [drawForm mapColor: Color white to: Color transparent;
                  mapColor: Color black to: color].
           
  firstPoint := self cursorPoint.
  endPoint := self rubberBandFrom: firstPoint until: [sensor noButtonPressed].
  endPoint isNil ifTrue: [^self].
  Display depth > 1 ifTrue: [self deleteRubberBandFrom: firstPoint to: endPoint.].
+ (DisplayLine from: firstPoint to: endPoint withForm: drawForm)
- (Line from: firstPoint to: endPoint withForm: drawForm)
  displayOn: Display
  at: 0 @ 0
  clippingBox: view insetDisplayBox
  rule: (Display depth > 1 ifTrue: [mode ~= Form erase ifTrue: [Form paint] ifFalse: [mode]]
  ifFalse: [mode])
  fillColor: (Display depth = 1 ifTrue: [color] ifFalse: [nil]).  
  hasUnsavedChanges contents: true.!

Item was changed:
  ----- Method: FormEditor>>rubberBandFrom:until: (in category 'private') -----
  rubberBandFrom: startPoint until: aBlock
 
  | endPoint previousEndPoint |
  previousEndPoint := startPoint.
  [aBlock value] whileFalse:
  [(endPoint := self cursorPoint) = previousEndPoint
  ifFalse:
+ [(DisplayLine from: startPoint to: previousEndPoint withForm: form)
- [(Line from: startPoint to: previousEndPoint withForm: form)
  displayOn: Display
  at: 0 @ 0
  clippingBox: view insetDisplayBox
  rule: Form reverse
  fillColor: Color gray.
+ (DisplayLine from: startPoint to: endPoint withForm: form)
- (Line from: startPoint to: endPoint withForm: form)
  displayOn: Display
  at: 0 @ 0
  clippingBox: view insetDisplayBox
  rule: Form reverse
  fillColor: Color gray.
  previousEndPoint  := endPoint]].
+ (DisplayLine from: startPoint to: previousEndPoint withForm: form)
- (Line from: startPoint to: previousEndPoint withForm: form)
  displayOn: Display
  at: 0 @ 0
  clippingBox: view insetDisplayBox
  rule: Form reverse
  fillColor: (Display depth = 1 ifTrue: [Color gray] ifFalse: [Color black]).
  ^endPoint!

Item was changed:
  ----- Method: GraphicSymbolInstance class>>example (in category 'examples') -----
  example
  "Simply evaluate the method and two GraphicSymbolInstances, each
  displaying a transformation of the same graphic symbol, will be
  presented on the screen. Clears the screen to white."
 
  | gate instance1 instance2 trans1 trans2 line arc f|
  Display fillWhite. "clear the Screen."
  f := Form extent: 2 @ 2.
  f fillBlack.
  gate:= GraphicSymbol new. "make a logic gate out of lines and arcs."
+ line:=DisplayLine new.  line beginPoint: -20 @ -20.  line endPoint: 0 @ -20. line form: f.
- line:=Line new.  line beginPoint: -20 @ -20.  line endPoint: 0 @ -20. line form: f.
  gate add: line.
 
+ line:=DisplayLine new.  line beginPoint: -20 @ 20.  line endPoint: 0 @ 20. line form: f.
- line:=Line new.  line beginPoint: -20 @ 20.  line endPoint: 0 @ 20. line form: f.
  gate add: line.
 
+ line:=DisplayLine new.  line beginPoint: 0 @ -40.  line endPoint: 0 @ 40. line form: f.
- line:=Line new.  line beginPoint: 0 @ -40.  line endPoint: 0 @ 40. line form: f.
  gate add: line.
 
+ arc := DisplayArc new. arc center: 0 @ 0 radius: 40 quadrant: 1.
- arc := Arc new. arc center: 0 @ 0 radius: 40 quadrant: 1.
  arc form: f.
  gate add: arc.
 
+ arc := DisplayArc new. arc center: 0 @ 0 radius: 40 quadrant: 4.
- arc := Arc new. arc center: 0 @ 0 radius: 40 quadrant: 4.
  arc form: f.
  gate add: arc.
 
  "one instance at 1/2 scale."
  trans1:=WindowingTransformation identity.
  trans1:= trans1 scaleBy: 0.5 @ 0.5.
  trans1:= trans1 translateBy: 100 @ 100.
 
  "the other instance at 2 times scale"
  trans2:=WindowingTransformation identity.
  trans2:= trans2 scaleBy: 2.0 @ 2.0.
  trans2:= trans2 translateBy: 200 @ 200.
 
  instance1 := GraphicSymbolInstance new.
  instance1 transformation: trans1.
  instance1 graphicSymbol: gate.
 
  instance2 := GraphicSymbolInstance new.
  instance2 transformation: trans2.
  instance2 graphicSymbol: gate.
 
  "display both instances of the logic gate"
  instance1 displayOn: Display
  transformation: WindowingTransformation identity
  clippingBox: Display boundingBox
  rule: Form under
  fillColor: nil.
  instance2 displayOn: Display
  transformation: WindowingTransformation identity
  clippingBox: Display boundingBox
  rule: Form under
  fillColor: nil
 
  "GraphicSymbolInstance example"!

Item was removed:
- Path subclass: #Line
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Line commentStamp: '<historical>' prior: 0!
- I represent the line segment specified by two points.!

Item was removed:
- ----- Method: Line class>>example (in category 'examples') -----
- example
- "Designate two places on the screen by clicking any mouse button. A
- straight path with a square black form will be displayed connecting the
- two selected points."
-
- | aLine aForm |  
- aForm := Form extent: 20@20. "make a form one quarter of inch square"
- aForm fillBlack. "turn it black"
- aLine := Line new.
- aLine form: aForm. "use the black form for display"
- aLine beginPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aLine beginPoint.
- aLine endPoint: Sensor waitButton.
- aLine displayOn: Display. "display the line"
-
- "Line example"!

Item was removed:
- ----- Method: Line class>>from:to:withForm: (in category 'instance creation') -----
- from: beginPoint to: endPoint withForm: aForm
- "Answer an instance of me with end points begingPoint and endPoint;
- the source form for displaying the line is aForm."
-
- | newSelf |
- newSelf := super new: 2.
- newSelf add: beginPoint.
- newSelf add: endPoint.
- newSelf form: aForm.
- ^newSelf!

Item was removed:
- ----- Method: Line class>>new (in category 'instance creation') -----
- new
-
- | newSelf |
- newSelf := super new: 2.
- newSelf add: 0@0.
- newSelf add: 0@0.
- ^newSelf!

Item was removed:
- ----- Method: Line>>beginPoint (in category 'accessing') -----
- beginPoint
- "Answer the first end point of the receiver."
-
- ^self first!

Item was removed:
- ----- Method: Line>>beginPoint: (in category 'accessing') -----
- beginPoint: aPoint
- "Set the first end point of the receiver to be the argument, aPoint.
- Answer aPoint."
-
- self at: 1 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Line>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
- "The form associated with this Path will be displayed, according  
- to one of the sixteen functions of two logical variables (rule), at  
- each point on the Line. Also the source form will be first anded  
- with aForm as a mask. Does not effect the state of the Path."
-
- collectionOfPoints size < 2 ifTrue: [self error: 'a line must have two points'].
- aDisplayMedium
- drawLine: self form
- from: self beginPoint + aPoint
- to: self endPoint + aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Line>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | newPath newLine |
- newPath := aTransformation applyTo: self.
- newLine := Line new.
- newLine beginPoint: newPath firstPoint.
- newLine endPoint: newPath secondPoint.
- newLine form: self form.
- newLine
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Line>>displayOnPort:at: (in category 'displaying') -----
- displayOnPort: aPort at: aPoint
- aPort sourceForm: self form; combinationRule: Form under; fillColor: nil.
- aPort drawFrom: collectionOfPoints first + aPoint
- to: collectionOfPoints last + aPoint!

Item was removed:
- ----- Method: Line>>endPoint (in category 'accessing') -----
- endPoint
- "Answer the last end point of the receiver."
-
- ^self last!

Item was removed:
- ----- Method: Line>>endPoint: (in category 'accessing') -----
- endPoint: aPoint
- "Set the first end point of the receiver to be the argument, aPoint.
- Answer aPoint."
-
- self at: 2 put: aPoint.
- ^aPoint!

Item was removed:
- Path subclass: #LinearFit
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !LinearFit commentStamp: '<historical>' prior: 0!
- I represent a piece-wise linear approximation to a set of points in the plane.!

Item was removed:
- ----- Method: LinearFit class>>example (in category 'examples') -----
- example
- "Select points on a Path using the red button. Terminate by selecting
- any other button. Creates a Path from the points and displays it as a
- piece-wise linear approximation."
-
- | aLinearFit aForm flag |
- aLinearFit := LinearFit new.
- aForm := Form extent: 1 @ 40.
- aForm  fillBlack.
- aLinearFit form: aForm.
- flag := true.
- [flag] whileTrue:
- [Sensor waitButton.
- Sensor redButtonPressed
- ifTrue: [aLinearFit add: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aLinearFit last]
- ifFalse: [flag:=false]].
- aLinearFit displayOn: Display
-
- "LinearFit example"!

Item was removed:
- ----- Method: LinearFit>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger
- fillColor: aForm
-  
- | line |
- line := Line new.
- line form: self form.
- 1 to: self size - 1 do:
- [:i |
- line beginPoint: (self at: i).
- line endPoint: (self at: i + 1).
- line displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: LinearFit>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox:
- clipRect rule: anInteger fillColor: aForm
-
- | transformedPath |
- "get the scaled and translated Path."
- transformedPath := aTransformation applyTo: self.
- transformedPath
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- DisplayObject subclass: #Path
- instanceVariableNames: 'form collectionOfPoints'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Path commentStamp: '<historical>' prior: 0!
- I am the abstract superclass of the Graphic spatial primitives. I represent an ordered sequence of Points. Spatial primitives are used to generate "trajectories" such as lines and circles.!

Item was removed:
- ----- Method: Path class>>example (in category 'examples') -----
- example
- "Creates a Path from mousePoints and displays it several ways on the display screen. Messes up the display. For learning about class Path, just select the code below and execute it to create a path and see it redisplayed in another place on the screen. Each path displays using a different form. A path is indicated by pressing the red mouse button in a sequence; press any other mouse button to terminate. "
-
- | aPath aForm pl fl flag |
- aForm := Form extent: 2 @ 40. "creates a form one inch long"
- aForm fillBlack. "turns it black"
- aPath := Path new.
- aPath form: aForm. "use the long black form for displaying"
- flag := true.
- [flag]
- whileTrue:
- [Sensor waitButton.
- Sensor redButtonPressed
- ifTrue:
- [aPath add: Sensor waitButton.
- Sensor waitNoButton.
- aForm displayOn: Display at: aPath last]
- ifFalse: [flag := false]].
- Display fillWhite.
- aPath displayOn: Display. "the original path"
- pl := aPath translateBy: 0 @ 100.
- fl := Form extent: 40 @ 40.
- fl fillGray.
- pl form: fl.
- pl displayOn: Display. "the translated path"
- Sensor waitNoButton
-
- "Path example"!

Item was removed:
- ----- Method: Path class>>new (in category 'instance creation') -----
- new
-
- ^self basicNew initializeCollectionOfPoints!

Item was removed:
- ----- Method: Path class>>new: (in category 'instance creation') -----
- new: anInteger
-
- ^self basicNew initializeCollectionOfPoints: anInteger!

Item was removed:
- ----- Method: Path>>add: (in category 'adding') -----
- add: aPoint
- "Include aPoint as one of the receiver's elements."
-
- ^collectionOfPoints add: aPoint!

Item was removed:
- ----- Method: Path>>at: (in category 'accessing') -----
- at: index
- "Answer the point on the receiver's path at position index."
-
- ^collectionOfPoints at: index!

Item was removed:
- ----- Method: Path>>at:put: (in category 'accessing') -----
- at: index put: aPoint
- "Store the argument, aPoint, as the point on the receiver's path at position
- index."
-
- ^collectionOfPoints at: index put: aPoint!

Item was removed:
- ----- Method: Path>>collect: (in category 'enumerating') -----
- collect: aBlock
- "Evaluate aBlock with each of the receiver's elements as the argument.
- Collect the resulting values into a path that is like the receiver. Answer
- the new path."
-
- | newCollection |
- newCollection := collectionOfPoints collect: aBlock.
- newCollection form: self form.
- ^newCollection!

Item was removed:
- ----- Method: Path>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
- "Refer to the comment in DisplayObject|computeBoundingBox."
-
- | box |
- box := Rectangle origin: (self at: 1) extent: 0 @ 0.
- collectionOfPoints do:
- [:aPoint | box swallow: (Rectangle origin: aPoint extent: 0 @ 0)].
- ^box!

Item was removed:
- ----- Method: Path>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
- "Display this Path--offset by aPoint, clipped by clipRect and the form
- associated with this Path will be displayedr according to one of the sixteen
- functions of two logical variables (rule). Also the source form will be first
- anded with aForm as a mask. Does not effect the state of the Path"
-
- collectionOfPoints do:
- [:element |
- self form
- displayOn: aDisplayMedium
- at: element + aDisplayPoint
- clippingBox: clipRectangle
- rule: ruleInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: Path>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
- "Displays this path, translated and scaled by aTransformation. Get the
- scaled and translated Path."
-
- | newPath transformedPath |
- transformedPath := displayTransformation applyTo: self.
- newPath := Path new.
- transformedPath do: [:point | newPath add: point].
- newPath form: self form.
- newPath
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRectangle
- rule: ruleInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Path>>first (in category 'accessing') -----
- first
- "Answer the first point on the receiver's path; included to correspond to
- OrderedCollection protocol."
-
- ^collectionOfPoints first!

Item was removed:
- ----- Method: Path>>firstPoint (in category 'accessing') -----
- firstPoint
- "Answer the first point on the receiver's path."
-
- ^collectionOfPoints first!

Item was removed:
- ----- Method: Path>>firstPoint: (in category 'accessing') -----
- firstPoint: aPoint
- "Replace the first element of the receiver with the new value aPoint.
- Answer the argument aPoint."
-
- collectionOfPoints at: 1 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Path>>form (in category 'accessing') -----
- form
- "Answer the receiver's form, or, if form is nil, then answer a 1 x 1 black
- form (a black dot)."
-
- | aForm |
- form == nil
- ifTrue:
- [aForm := Form extent: 1 @ 1.
- aForm fillBlack.
- ^aForm]
- ifFalse:
- [^form]!

Item was removed:
- ----- Method: Path>>form: (in category 'accessing') -----
- form: aForm
- "Make the argument, aForm, be the receiver's form."
-
- form := aForm!

Item was removed:
- ----- Method: Path>>initializeCollectionOfPoints (in category 'private') -----
- initializeCollectionOfPoints
-
- collectionOfPoints := OrderedCollection new!

Item was removed:
- ----- Method: Path>>initializeCollectionOfPoints: (in category 'private') -----
- initializeCollectionOfPoints: anInteger
-
- collectionOfPoints := OrderedCollection new: anInteger!

Item was removed:
- ----- Method: Path>>isEmpty (in category 'testing') -----
- isEmpty
-
- ^collectionOfPoints isEmpty!

Item was removed:
- ----- Method: Path>>last (in category 'accessing') -----
- last
- "Answer the last point on the receiver's path; included to correspond to
- OrderedCollection protocol."
-
- ^collectionOfPoints last!

Item was removed:
- ----- Method: Path>>offset (in category 'accessing') -----
- offset
- "There are basically two kinds of display objects in the system: those
- that, when asked to transform themselves, create a new object; and those
- that side effect themselves by maintaining a record of the transformation
- request (typically an offset). Path, like Rectangle and Point, is a display
- object of the first kind."
-
- self shouldNotImplement!

Item was removed:
- ----- Method: Path>>removeAllSuchThat: (in category 'removing') -----
- removeAllSuchThat: aBlock
- "Evaluate aBlock for each element of the receiver.
- Remove each element for which aBlock evaluates to true."
-
- collectionOfPoints removeAllSuchThat: aBlock.
- !

Item was removed:
- ----- Method: Path>>scaleBy: (in category 'transforming') -----
- scaleBy: aPoint
- "Answers a new Path scaled by aPoint. Does not affect the current data in
- this Path."
-
- | newPath |
- newPath := self species new: self size.
- newPath form: self form.
- collectionOfPoints do: [:element | newPath add: (element scaleBy: aPoint)].
- ^newPath!

Item was removed:
- ----- Method: Path>>secondPoint (in category 'accessing') -----
- secondPoint
- "Answer the second element of the receiver."
-
- ^collectionOfPoints at: 2!

Item was removed:
- ----- Method: Path>>secondPoint: (in category 'accessing') -----
- secondPoint: aPoint
- "Replace the second element of the receiver with the new value aPoint.
- Answer the argument aPoint."
-
- collectionOfPoints at: 2 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Path>>select: (in category 'enumerating') -----
- select: aBlock
- "Evaluate aBlock with each of the receiver's elements as the argument.
- Collect into a new path like the receiver only those elements for which
- aBlock evaluates to true. Answer the new path."
-
- | newCollection |
- newCollection := collectionOfPoints select: aBlock.
- newCollection form: self form.
- ^newCollection!

Item was removed:
- ----- Method: Path>>size (in category 'accessing') -----
- size
- "Answer the length of the receiver."
-
- ^collectionOfPoints size!

Item was removed:
- ----- Method: Path>>thirdPoint (in category 'accessing') -----
- thirdPoint
- "Answer the third element of the receiver."
-
- ^collectionOfPoints at: 3!

Item was removed:
- ----- Method: Path>>thirdPoint: (in category 'accessing') -----
- thirdPoint: aPoint
- "Replace the third element of the receiver with the new value aPoint.
- Answer the argument aPoint."
-
- collectionOfPoints at: 3 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Path>>translateBy: (in category 'transforming') -----
- translateBy: aPoint
- "Answers a new Path whose elements are translated by aPoint. Does not
- affect the elements of this Path."
-
- | newPath |
- newPath := self species new: self size.
- newPath form: self form.
- collectionOfPoints do: [:element | newPath add: (element translateBy: aPoint)].
- ^newPath!

Item was removed:
- Path subclass: #Spline
- instanceVariableNames: 'coefficients'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Spline commentStamp: '<historical>' prior: 0!
- I represent a collection of Points through which a cubic spline curve is fitted.!

Item was removed:
- ----- Method: Spline class>>example (in category 'examples') -----
- example
- "Designate points on the Path by clicking the red button. Terminate by
- pressing any other button. A curve will be displayed, through the
- selected points, using a long black form."
-
- | splineCurve aForm flag|
- aForm := Form extent: 2@2.
- aForm  fillBlack.
- splineCurve := Spline new.
- splineCurve form: aForm.
- flag := true.
- [flag] whileTrue:
- [Sensor waitButton.
- Sensor redButtonPressed
- ifTrue:
- [splineCurve add: Sensor waitButton.
- Sensor waitNoButton.
- aForm displayOn: Display at: splineCurve last]
- ifFalse: [flag:=false]].
- splineCurve computeCurve.
- splineCurve isEmpty
- ifFalse: [splineCurve displayOn: Display.
- Sensor waitNoButton].
-  
- "Spline example"!

Item was removed:
- ----- Method: Spline>>coefficients (in category 'accessing') -----
- coefficients
- "Answer an eight-element Array of Arrays each of which is the length
- of the receiver. The first four arrays are the values, first, second and
- third derivatives, respectively, for the parametric spline in x. The last
- four elements are for y."
-
- ^coefficients!

Item was removed:
- ----- Method: Spline>>computeCurve (in category 'displaying') -----
- computeCurve
- "Compute an array for the coefficients."
-
- | length extras |
- length := self size.
- extras := 0.
- coefficients := Array new: 8.
- 1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].
- 1 to: 5 by: 4 do:
- [:k |
- 1 to: length do:
- [:i | (coefficients at: k)
- at: i put: (k = 1
- ifTrue: [(self at: i) x asFloat]
- ifFalse: [(self at: i) y asFloat])].
- 1 to: extras do: [:i | (coefficients at: k)
- at: length + i put: ((coefficients at: k)
- at: i + 1)].
- self derivs: (coefficients at: k)
- first: (coefficients at: k + 1)
- second: (coefficients at: k + 2)
- third: (coefficients at: k + 3)].
- extras > 0
- ifTrue: [1 to: 8 do:
- [:i |
- coefficients at: i put: ((coefficients at: i)
- copyFrom: 2 to: length + 1)]]!

Item was removed:
- ----- Method: Spline>>derivs:first:second:third: (in category 'private') -----
- derivs: a first: point1 second: point2 third: point3
- "Compute the first, second and third derivitives (in coefficients) from
- the Points in this Path (coefficients at: 1 and coefficients at: 5)."
-
- | l v anArray |
- l := a size.
- l < 2 ifTrue: [^self].
- l > 2
-  ifTrue:
- [v := Array new: l.
- v  at:  1 put: 4.0.
- anArray := Array new: l.
- anArray  at:  1 put: (6.0 * ((a  at:  1) - ((a  at:  2) * 2.0) + (a  at:  3))).
- 2 to: l - 2 do:
- [:i |
- v  at:  i put: (4.0 - (1.0 / (v  at:  (i - 1)))).
- anArray
- at:  i
- put: (6.0 * ((a  at:  i) - ((a  at:  (i + 1)) * 2.0) + (a  at:  (i + 2)))
- - ((anArray  at:  (i - 1)) / (v  at:  (i - 1))))].
- point2  at: (l - 1) put: ((anArray  at:  (l - 2)) / (v  at:  (l - 2))).
- l - 2 to: 2 by: 0-1 do:
- [:i |
- point2
- at: i
- put: ((anArray  at:  (i - 1)) - (point2  at:  (i + 1)) / (v  at:  (i - 1)))]].
- point2 at: 1 put: (point2  at:  l put: 0.0).
- 1 to: l - 1 do:
- [:i | point1
- at: i
- put: ((a at: (i + 1)) - (a  at:  i) -
- ((point2  at:  i) * 2.0 + (point2  at:  (i + 1)) / 6.0)).
-      point3 at: i put: ((point2  at:  (i + 1)) - (point2  at:  i))]!

Item was removed:
- ----- Method: Spline>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
- "Display the receiver, a spline curve, approximated by straight line
- segments."
-
- | n line t x y x1 x2 x3 y1 y2 y3 |
- collectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point'].
- line := Line new.
- line form: self form.
- line beginPoint:
- (x := (coefficients at: 1) at: 1) rounded @ (y := (coefficients at: 5) at: 1) rounded.
- 1 to: (coefficients at: 1) size - 1 do:
- [:i |
- "taylor series coefficients"
- x1 := (coefficients at: 2) at: i.
- y1 := (coefficients at: 6) at: i.
- x2 := ((coefficients at: 3) at: i) / 2.0.
- y2 := ((coefficients at: 7) at: i) / 2.0.
- x3 := ((coefficients at: 4) at: i) / 6.0.
- y3 := ((coefficients at: 8) at: i) / 6.0.
- "guess n"
- n := 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3)
- at: i + 1) abs + ((coefficients at: 7)
- at: i + 1) abs / 100.0) rounded.
- 1 to: n - 1 do:
- [:j |
- t := j asFloat / n.
- line endPoint:
- (x3 * t + x2 * t + x1 * t + x) rounded
- @ (y3 * t + y2 * t + y1 * t + y) rounded.
- line
- displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm.
- line beginPoint: line endPoint].
- line beginPoint:
- (x := (coefficients at: 1) at: i + 1) rounded
- @ (y := (coefficients at: 5) at: i + 1) rounded.
- line
- displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: Spline>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
- "Get the scaled and translated path of newKnots."
-
- | newKnots newSpline |
- newKnots := aTransformation applyTo: self.
- newSpline := Spline new.
- newKnots do: [:knot | newSpline add: knot].
- newSpline form: self form.
- newSpline
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!


Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: ST80-mt.265.mcz

marcel.taeumel
Hi all!

I would like to merge this into Trunk in a day or two if nobody objects. :-)

See the discussion here:

Best,
Marcel

Am 09.03.2021 13:33:52 schrieb [hidden email] <[hidden email]>:

A new version of ST80 was added to project The Inbox:
http://source.squeak.org/inbox/ST80-mt.265.mcz

==================== Summary ====================

Name: ST80-mt.265
Author: mt
Time: 9 March 2021, 1:33:39.525921 pm
UUID: 1b02e796-d790-b34d-9f4f-dd406f43e130
Ancestors: ST80-mt.264

Free the names Path, Arc, Circle, Line, Spline to be used in a prospective Math package.

=============== Diff against ST80-mt.264 ===============

Item was removed:
- Path subclass: #Arc
- instanceVariableNames: 'quadrant radius center'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Arc commentStamp: '' prior: 0!
- Arcs are an unusual implementation of splines due to Ted Kaehler. Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner. Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern). By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines. Voila.!

Item was removed:
- ----- Method: Arc class>>example (in category 'examples') -----
- example
- "Click the button somewhere on the screen. The designated point will
- be the center of an Arc with radius 50 in the 4th quadrant."
-
- | anArc aForm |
- aForm := Form extent: 1 @ 30. "make a long thin Form for display"
- aForm fillBlack. "turn it black"
- anArc := Arc new.
- anArc form: aForm. "set the form for display"
- anArc radius: 50.0.
- anArc center: Sensor waitButton.
- anArc quadrant: 4.
- anArc displayOn: Display.
- Sensor waitButton
-
- "Arc example"!

Item was removed:
- ----- Method: Arc>>center (in category 'accessing') -----
- center
- "Answer the point at the center of the receiver."
-
- ^center!

Item was removed:
- ----- Method: Arc>>center: (in category 'accessing') -----
- center: aPoint
- "Set aPoint to be the receiver's center."
-
- center := aPoint!

Item was removed:
- ----- Method: Arc>>center:radius: (in category 'accessing') -----
- center: aPoint radius: anInteger
- "The receiver is defined by a point at the center and a radius. The
- quadrant is not reset."
-
- center := aPoint.
- radius := anInteger!

Item was removed:
- ----- Method: Arc>>center:radius:quadrant: (in category 'accessing') -----
- center: aPoint radius: anInteger quadrant: section
- "Set the receiver's quadrant to be the argument, section. The size of the
- receiver is defined by the center and its radius."
-
- center := aPoint.
- radius := anInteger.
- quadrant := section!

Item was removed:
- ----- Method: Arc>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
- | aRectangle aPoint |
- aRectangle := center - radius + form offset extent: form extent + (radius * 2) asPoint.
- aPoint := center + form extent.
- quadrant = 1 ifTrue: [^ aRectangle encompass: center x @ aPoint y].
- quadrant = 2 ifTrue: [^ aRectangle encompass: aPoint x @ aPoint y].
- quadrant = 3 ifTrue: [^ aRectangle encompass: aPoint x @ center y].
- quadrant = 4 ifTrue: [^ aRectangle encompass: center x @ center y]!

Item was removed:
- ----- Method: Arc>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | nSegments line angle sin cos xn yn |
- nSegments := 12.0.
- line := Line new.
- line form: self form.
- angle := (90.0 / nSegments) degreesToRadians.
- sin := angle sin.
- cos := angle cos.
- quadrant = 1
- ifTrue:
- [xn := radius asFloat.
- yn := 0.0].
- quadrant = 2
- ifTrue:
- [xn := 0.0.
- yn := 0.0 - radius asFloat].
- quadrant = 3
- ifTrue:
- [xn := 0.0 - radius asFloat.
- yn := 0.0].
- quadrant = 4
- ifTrue:
- [xn := 0.0.
- yn := radius asFloat].
- nSegments asInteger
- timesRepeat:
- [ | xn1 yn1 |
- xn1 := xn * cos + (yn * sin).
- yn1 := yn * cos - (xn * sin).
- line beginPoint: center + (xn asInteger @ yn asInteger).
- line endPoint: center + (xn1 asInteger @ yn1 asInteger).
- line
- displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm.
- xn := xn1.
- yn := yn1]!

Item was removed:
- ----- Method: Arc>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | newArc tempCenter |
- newArc := Arc new.
- tempCenter := aTransformation applyTo: self center.
- newArc center: tempCenter x asInteger @ tempCenter y asInteger.
- newArc quadrant: self quadrant.
- newArc radius: (self radius * aTransformation scale x) asInteger.
- newArc form: self form.
- newArc
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Arc>>quadrant (in category 'accessing') -----
- quadrant
- "Answer the part of the circle represented by the receiver."
- ^quadrant!

Item was removed:
- ----- Method: Arc>>quadrant: (in category 'accessing') -----
- quadrant: section
- "Set the part of the circle represented by the receiver to be the argument,
- section."
-
- quadrant := section!

Item was removed:
- ----- Method: Arc>>radius (in category 'accessing') -----
- radius
- "Answer the receiver's radius."
-
- ^radius!

Item was removed:
- ----- Method: Arc>>radius: (in category 'accessing') -----
- radius: anInteger
- "Set the receiver's radius to be the argument, anInteger."
-
- radius := anInteger!

Item was removed:
- Arc subclass: #Circle
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Circle commentStamp: '' prior: 0!
- I represent a full circle. I am made from four Arcs.!

Item was removed:
- ----- Method: Circle class>>exampleOne (in category 'examples') -----
- exampleOne
- "Click any button somewhere on the screen. The point will be the center
- of the circcle of radius 150."
-
- | aCircle aForm |
- aForm := Form extent: 1@30.
- aForm fillBlack.
- aCircle := Circle new.
- aCircle form: aForm.
- aCircle radius: 150.
- aCircle center: Sensor waitButton.
- aCircle displayOn: Display
-
- "Circle exampleOne"!

Item was removed:
- ----- Method: Circle class>>exampleTwo (in category 'examples') -----
- exampleTwo
- "Designate a rectangular area that should be used as the brush for
- displaying the circle. Click any button at a point on the screen which
- will be the center location for the circle. The curve will be displayed
- with a long black form."
-
- | aCircle aForm |
- aForm := Form fromUser.
- aCircle := Circle new.
- aCircle form: aForm.
- aCircle radius: 150.
- aCircle center: Sensor waitButton.
- aCircle displayOn: Display at: 0 @ 0 rule: Form reverse
-
- "Circle exampleTwo"!

Item was removed:
- ----- Method: Circle>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
-
- ^center - radius + form offset extent: form extent + (radius * 2) asPoint!

Item was removed:
- ----- Method: Circle>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
-
- 1 to: 4 do:
- [:i |
- super quadrant: i.
- super displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: Circle>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- 1 to: 4 do:
- [:i |
- super quadrant: i.
- super displayOn: aDisplayMedium
- transformation: aTransformation
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- Path subclass: #CurveFitter
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !CurveFitter commentStamp: '' prior: 0!
- I represent a conic section determined by three points p1, p2 and p3. I interpolate p1 and p3 and am tangent to line p1, p2 at p1 and line p3, p2 at p3.!

Item was removed:
- ----- Method: CurveFitter class>>example (in category 'examples') -----
- example
- "Designate three locations on the screen by clicking any button. The
- curve determined by the points will be displayed with a long black form."
-
- | aCurveFitter aForm |
- aForm := Form extent: 1@30. "make a long thin Form for display "
- aForm fillBlack. "turn it black"
- aCurveFitter := CurveFitter new.
- aCurveFitter form: aForm. "set the form for display"
- "collect three Points and show them on the dispaly"
- aCurveFitter firstPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aCurveFitter firstPoint.
- aCurveFitter secondPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aCurveFitter secondPoint.
- aCurveFitter thirdPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aCurveFitter thirdPoint.
-
- aCurveFitter displayOn: Display "display the CurveFitter"
-
- "CurveFitter example"!

Item was removed:
- ----- Method: CurveFitter class>>new (in category 'instance creation') -----
- new
-
- | newSelf |
- newSelf := super new: 3.
- newSelf add: 0@0.
- newSelf add: 0@0.
- newSelf add: 0@0.
- ^newSelf!

Item was removed:
- ----- Method: CurveFitter>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | pa pb k s p1 p2 p3 line |
- line := Line new.
- line form: self form.
- collectionOfPoints size < 3 ifTrue: [self error: 'Curve must have three points'].
- p1 := self firstPoint.
- p2 := self secondPoint.
- p3 := self thirdPoint.
- s := Path new.
- s add: p1.
- pa := p2 - p1.
- pb := p3 - p2.
- k := 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20.
- "k is a guess as to how many line segments to use to approximate
- the curve."
- 1 to: k do:
- [:i |
- s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) // (k - 1)].
- s add: p3.
- 1 to: s size - 1 do:
- [:i |
- line beginPoint: (s at: i).
- line endPoint: (s at: i + 1).
- line displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: CurveFitter>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | transformedPath newCurveFitter |
- transformedPath := aTransformation applyTo: self.
- newCurveFitter := CurveFitter new.
- newCurveFitter firstPoint: transformedPath firstPoint.
- newCurveFitter secondPoint: transformedPath secondPoint.
- newCurveFitter thirdPoint: transformedPath thirdPoint.
- newCurveFitter form: self form.
- newCurveFitter
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was added:
+ DisplayPath subclass: #DisplayArc
+ instanceVariableNames: 'quadrant radius center'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayArc commentStamp: '' prior: 0!
+ Arcs are an unusual implementation of splines due to Ted Kaehler. Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner. Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern). By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines. Voila.!

Item was added:
+ ----- Method: DisplayArc class>>example (in category 'examples') -----
+ example
+ "Click the button somewhere on the screen. The designated point will
+ be the center of an DisplayArc with radius 50 in the 4th quadrant."
+
+ | anDisplayArc aForm |
+ aForm := Form extent: 1 @ 30. "make a long thin Form for display"
+ aForm fillBlack. "turn it black"
+ anDisplayArc := DisplayArc new.
+ anDisplayArc form: aForm. "set the form for display"
+ anDisplayArc radius: 50.0.
+ anDisplayArc center: Sensor waitButton.
+ anDisplayArc quadrant: 4.
+ anDisplayArc displayOn: Display.
+ Sensor waitButton
+
+ "DisplayArc example"!

Item was added:
+ ----- Method: DisplayArc>>center (in category 'accessing') -----
+ center
+ "Answer the point at the center of the receiver."
+
+ ^center!

Item was added:
+ ----- Method: DisplayArc>>center: (in category 'accessing') -----
+ center: aPoint
+ "Set aPoint to be the receiver's center."
+
+ center := aPoint!

Item was added:
+ ----- Method: DisplayArc>>center:radius: (in category 'accessing') -----
+ center: aPoint radius: anInteger
+ "The receiver is defined by a point at the center and a radius. The
+ quadrant is not reset."
+
+ center := aPoint.
+ radius := anInteger!

Item was added:
+ ----- Method: DisplayArc>>center:radius:quadrant: (in category 'accessing') -----
+ center: aPoint radius: anInteger quadrant: section
+ "Set the receiver's quadrant to be the argument, section. The size of the
+ receiver is defined by the center and its radius."
+
+ center := aPoint.
+ radius := anInteger.
+ quadrant := section!

Item was added:
+ ----- Method: DisplayArc>>computeBoundingBox (in category 'display box access') -----
+ computeBoundingBox
+ | aRectangle aPoint |
+ aRectangle := center - radius + form offset extent: form extent + (radius * 2) asPoint.
+ aPoint := center + form extent.
+ quadrant = 1 ifTrue: [^ aRectangle encompass: center x @ aPoint y].
+ quadrant = 2 ifTrue: [^ aRectangle encompass: aPoint x @ aPoint y].
+ quadrant = 3 ifTrue: [^ aRectangle encompass: aPoint x @ center y].
+ quadrant = 4 ifTrue: [^ aRectangle encompass: center x @ center y]!

Item was added:
+ ----- Method: DisplayArc>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | nSegments line angle sin cos xn yn |
+ nSegments := 12.0.
+ line := DisplayLine new.
+ line form: self form.
+ angle := (90.0 / nSegments) degreesToRadians.
+ sin := angle sin.
+ cos := angle cos.
+ quadrant = 1
+ ifTrue:
+ [xn := radius asFloat.
+ yn := 0.0].
+ quadrant = 2
+ ifTrue:
+ [xn := 0.0.
+ yn := 0.0 - radius asFloat].
+ quadrant = 3
+ ifTrue:
+ [xn := 0.0 - radius asFloat.
+ yn := 0.0].
+ quadrant = 4
+ ifTrue:
+ [xn := 0.0.
+ yn := radius asFloat].
+ nSegments asInteger
+ timesRepeat:
+ [ | xn1 yn1 |
+ xn1 := xn * cos + (yn * sin).
+ yn1 := yn * cos - (xn * sin).
+ line beginPoint: center + (xn asInteger @ yn asInteger).
+ line endPoint: center + (xn1 asInteger @ yn1 asInteger).
+ line
+ displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm.
+ xn := xn1.
+ yn := yn1]!

Item was added:
+ ----- Method: DisplayArc>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | newDisplayArc tempCenter |
+ newDisplayArc := DisplayArc new.
+ tempCenter := aTransformation applyTo: self center.
+ newDisplayArc center: tempCenter x asInteger @ tempCenter y asInteger.
+ newDisplayArc quadrant: self quadrant.
+ newDisplayArc radius: (self radius * aTransformation scale x) asInteger.
+ newDisplayArc form: self form.
+ newDisplayArc
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayArc>>quadrant (in category 'accessing') -----
+ quadrant
+ "Answer the part of the circle represented by the receiver."
+ ^quadrant!

Item was added:
+ ----- Method: DisplayArc>>quadrant: (in category 'accessing') -----
+ quadrant: section
+ "Set the part of the circle represented by the receiver to be the argument,
+ section."
+
+ quadrant := section!

Item was added:
+ ----- Method: DisplayArc>>radius (in category 'accessing') -----
+ radius
+ "Answer the receiver's radius."
+
+ ^radius!

Item was added:
+ ----- Method: DisplayArc>>radius: (in category 'accessing') -----
+ radius: anInteger
+ "Set the receiver's radius to be the argument, anInteger."
+
+ radius := anInteger!

Item was added:
+ DisplayArc subclass: #DisplayCircle
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayCircle commentStamp: '' prior: 0!
+ I represent a full circle. I am made from four Arcs.!

Item was added:
+ ----- Method: DisplayCircle class>>exampleOne (in category 'examples') -----
+ exampleOne
+ "Click any button somewhere on the screen. The point will be the center
+ of the circcle of radius 150."
+
+ | aDisplayCircle aForm |
+ aForm := Form extent: 1@30.
+ aForm fillBlack.
+ aDisplayCircle := DisplayCircle new.
+ aDisplayCircle form: aForm.
+ aDisplayCircle radius: 150.
+ aDisplayCircle center: Sensor waitButton.
+ aDisplayCircle displayOn: Display
+
+ "DisplayCircle exampleOne"!

Item was added:
+ ----- Method: DisplayCircle class>>exampleTwo (in category 'examples') -----
+ exampleTwo
+ "Designate a rectangular area that should be used as the brush for
+ displaying the circle. Click any button at a point on the screen which
+ will be the center location for the circle. The curve will be displayed
+ with a long black form."
+
+ | aDisplayCircle aForm |
+ aForm := Form fromUser.
+ aDisplayCircle := DisplayCircle new.
+ aDisplayCircle form: aForm.
+ aDisplayCircle radius: 150.
+ aDisplayCircle center: Sensor waitButton.
+ aDisplayCircle displayOn: Display at: 0 @ 0 rule: Form reverse
+
+ "DisplayCircle exampleTwo"!

Item was added:
+ ----- Method: DisplayCircle>>computeBoundingBox (in category 'display box access') -----
+ computeBoundingBox
+
+ ^center - radius + form offset extent: form extent + (radius * 2) asPoint!

Item was added:
+ ----- Method: DisplayCircle>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ 1 to: 4 do:
+ [:i |
+ super quadrant: i.
+ super displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayCircle>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ 1 to: 4 do:
+ [:i |
+ super quadrant: i.
+ super displayOn: aDisplayMedium
+ transformation: aTransformation
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ DisplayPath subclass: #DisplayCurveFitter
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayCurveFitter commentStamp: '' prior: 0!
+ I represent a conic section determined by three points p1, p2 and p3. I interpolate p1 and p3 and am tangent to line p1, p2 at p1 and line p3, p2 at p3.!

Item was added:
+ ----- Method: DisplayCurveFitter class>>example (in category 'examples') -----
+ example
+ "Designate three locations on the screen by clicking any button. The
+ curve determined by the points will be displayed with a long black form."
+
+ | aDisplayCurveFitter aForm |
+ aForm := Form extent: 1@30. "make a long thin Form for display "
+ aForm fillBlack. "turn it black"
+ aDisplayCurveFitter := DisplayCurveFitter new.
+ aDisplayCurveFitter form: aForm. "set the form for display"
+ "collect three Points and show them on the dispaly"
+ aDisplayCurveFitter firstPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayCurveFitter firstPoint.
+ aDisplayCurveFitter secondPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayCurveFitter secondPoint.
+ aDisplayCurveFitter thirdPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayCurveFitter thirdPoint.
+
+ aDisplayCurveFitter displayOn: Display "display the DisplayCurveFitter"
+
+ "DisplayCurveFitter example"!

Item was added:
+ ----- Method: DisplayCurveFitter class>>new (in category 'instance creation') -----
+ new
+
+ | newSelf |
+ newSelf := super new: 3.
+ newSelf add: 0@0.
+ newSelf add: 0@0.
+ newSelf add: 0@0.
+ ^newSelf!

Item was added:
+ ----- Method: DisplayCurveFitter>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | pa pb k s p1 p2 p3 line |
+ line := DisplayLine new.
+ line form: self form.
+ collectionOfPoints size < 3 ifTrue: [self error: 'Curve must have three points'].
+ p1 := self firstPoint.
+ p2 := self secondPoint.
+ p3 := self thirdPoint.
+ s := DisplayPath new.
+ s add: p1.
+ pa := p2 - p1.
+ pb := p3 - p2.
+ k := 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20.
+ "k is a guess as to how many line segments to use to approximate
+ the curve."
+ 1 to: k do:
+ [:i |
+ s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) // (k - 1)].
+ s add: p3.
+ 1 to: s size - 1 do:
+ [:i |
+ line beginPoint: (s at: i).
+ line endPoint: (s at: i + 1).
+ line displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayCurveFitter>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | transformedPath newDisplayCurveFitter |
+ transformedPath := aTransformation applyTo: self.
+ newDisplayCurveFitter := DisplayCurveFitter new.
+ newDisplayCurveFitter firstPoint: transformedPath firstPoint.
+ newDisplayCurveFitter secondPoint: transformedPath secondPoint.
+ newDisplayCurveFitter thirdPoint: transformedPath thirdPoint.
+ newDisplayCurveFitter form: self form.
+ newDisplayCurveFitter
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ DisplayPath subclass: #DisplayLine
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayLine commentStamp: '' prior: 0!
+ I represent the line segment specified by two points.!

Item was added:
+ ----- Method: DisplayLine class>>example (in category 'examples') -----
+ example
+ "Designate two places on the screen by clicking any mouse button. A
+ straight path with a square black form will be displayed connecting the
+ two selected points."
+
+ | aDisplayLine aForm |
+ aForm := Form extent: 20@20. "make a form one quarter of inch square"
+ aForm fillBlack. "turn it black"
+ aDisplayLine := DisplayLine new.
+ aDisplayLine form: aForm. "use the black form for display"
+ aDisplayLine beginPoint: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayLine beginPoint.
+ aDisplayLine endPoint: Sensor waitButton.
+ aDisplayLine displayOn: Display. "display the line"
+
+ "DisplayLine example"!

Item was added:
+ ----- Method: DisplayLine class>>from:to:withForm: (in category 'instance creation') -----
+ from: beginPoint to: endPoint withForm: aForm
+ "Answer an instance of me with end points begingPoint and endPoint;
+ the source form for displaying the line is aForm."
+
+ | newSelf |
+ newSelf := super new: 2.
+ newSelf add: beginPoint.
+ newSelf add: endPoint.
+ newSelf form: aForm.
+ ^newSelf!

Item was added:
+ ----- Method: DisplayLine class>>new (in category 'instance creation') -----
+ new
+
+ | newSelf |
+ newSelf := super new: 2.
+ newSelf add: 0@0.
+ newSelf add: 0@0.
+ ^newSelf!

Item was added:
+ ----- Method: DisplayLine>>beginPoint (in category 'accessing') -----
+ beginPoint
+ "Answer the first end point of the receiver."
+
+ ^self first!

Item was added:
+ ----- Method: DisplayLine>>beginPoint: (in category 'accessing') -----
+ beginPoint: aPoint
+ "Set the first end point of the receiver to be the argument, aPoint.
+ Answer aPoint."
+
+ self at: 1 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayLine>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+ "The form associated with this Path will be displayed, according
+ to one of the sixteen functions of two logical variables (rule), at
+ each point on the Line. Also the source form will be first anded
+ with aForm as a mask. Does not effect the state of the Path."
+
+ collectionOfPoints size < 2 ifTrue: [self error: 'a line must have two points'].
+ aDisplayMedium
+ drawLine: self form
+ from: self beginPoint + aPoint
+ to: self endPoint + aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayLine>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+
+ | newPath newDisplayLine |
+ newPath := aTransformation applyTo: self.
+ newDisplayLine := DisplayLine new.
+ newDisplayLine beginPoint: newPath firstPoint.
+ newDisplayLine endPoint: newPath secondPoint.
+ newDisplayLine form: self form.
+ newDisplayLine
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayLine>>displayOnPort:at: (in category 'displaying') -----
+ displayOnPort: aPort at: aPoint
+ aPort sourceForm: self form; combinationRule: Form under; fillColor: nil.
+ aPort drawFrom: collectionOfPoints first + aPoint
+ to: collectionOfPoints last + aPoint!

Item was added:
+ ----- Method: DisplayLine>>endPoint (in category 'accessing') -----
+ endPoint
+ "Answer the last end point of the receiver."
+
+ ^self last!

Item was added:
+ ----- Method: DisplayLine>>endPoint: (in category 'accessing') -----
+ endPoint: aPoint
+ "Set the first end point of the receiver to be the argument, aPoint.
+ Answer aPoint."
+
+ self at: 2 put: aPoint.
+ ^aPoint!

Item was added:
+ DisplayPath subclass: #DisplayLinearFit
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayLinearFit commentStamp: '' prior: 0!
+ I represent a piece-wise linear approximation to a set of points in the plane.!

Item was added:
+ ----- Method: DisplayLinearFit class>>example (in category 'examples') -----
+ example
+ "Select points on a Path using the red button. Terminate by selecting
+ any other button. Creates a Path from the points and displays it as a
+ piece-wise linear approximation."
+
+ | aDisplayLinearFit aForm flag |
+ aDisplayLinearFit := DisplayLinearFit new.
+ aForm := Form extent: 1 @ 40.
+ aForm fillBlack.
+ aDisplayLinearFit form: aForm.
+ flag := true.
+ [flag] whileTrue:
+ [Sensor waitButton.
+ Sensor redButtonPressed
+ ifTrue: [aDisplayLinearFit add: Sensor waitButton. Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayLinearFit last]
+ ifFalse: [flag:=false]].
+ aDisplayLinearFit displayOn: Display
+
+ "DisplayLinearFit example"!

Item was added:
+ ----- Method: DisplayLinearFit>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger
+ fillColor: aForm
+
+ | line |
+ line := DisplayLine new.
+ line form: self form.
+ 1 to: self size - 1 do:
+ [:i |
+ line beginPoint: (self at: i).
+ line endPoint: (self at: i + 1).
+ line displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayLinearFit>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox:
+ clipRect rule: anInteger fillColor: aForm
+
+ | transformedPath |
+ "get the scaled and translated Path."
+ transformedPath := aTransformation applyTo: self.
+ transformedPath
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was added:
+ DisplayObject subclass: #DisplayPath
+ instanceVariableNames: 'form collectionOfPoints'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplayPath commentStamp: '' prior: 0!
+ I am the abstract superclass of the Graphic spatial primitives. I represent an ordered sequence of Points. Spatial primitives are used to generate "trajectories" such as lines and circles.!

Item was added:
+ ----- Method: DisplayPath class>>example (in category 'examples') -----
+ example
+ "Creates a DisplayPath from mousePoints and displays it several ways on the display screen. Messes up the display. For learning about class DisplayPath, just select the code below and execute it to create a path and see it redisplayed in another place on the screen. Each path displays using a different form. A path is indicated by pressing the red mouse button in a sequence; press any other mouse button to terminate. "
+
+ | aDisplayPath aForm pl fl flag |
+ aForm := Form extent: 2 @ 40. "creates a form one inch long"
+ aForm fillBlack. "turns it black"
+ aDisplayPath := DisplayPath new.
+ aDisplayPath form: aForm. "use the long black form for displaying"
+ flag := true.
+ [flag]
+ whileTrue:
+ [Sensor waitButton.
+ Sensor redButtonPressed
+ ifTrue:
+ [aDisplayPath add: Sensor waitButton.
+ Sensor waitNoButton.
+ aForm displayOn: Display at: aDisplayPath last]
+ ifFalse: [flag := false]].
+ Display fillWhite.
+ aDisplayPath displayOn: Display. "the original path"
+ pl := aDisplayPath translateBy: 0 @ 100.
+ fl := Form extent: 40 @ 40.
+ fl fillGray.
+ pl form: fl.
+ pl displayOn: Display. "the translated path"
+ Sensor waitNoButton
+
+ "DisplayPath example"!

Item was added:
+ ----- Method: DisplayPath class>>new (in category 'instance creation') -----
+ new
+
+ ^self basicNew initializeCollectionOfPoints!

Item was added:
+ ----- Method: DisplayPath class>>new: (in category 'instance creation') -----
+ new: anInteger
+
+ ^self basicNew initializeCollectionOfPoints: anInteger!

Item was added:
+ ----- Method: DisplayPath>>add: (in category 'adding') -----
+ add: aPoint
+ "Include aPoint as one of the receiver's elements."
+
+ ^collectionOfPoints add: aPoint!

Item was added:
+ ----- Method: DisplayPath>>at: (in category 'accessing') -----
+ at: index
+ "Answer the point on the receiver's path at position index."
+
+ ^collectionOfPoints at: index!

Item was added:
+ ----- Method: DisplayPath>>at:put: (in category 'accessing') -----
+ at: index put: aPoint
+ "Store the argument, aPoint, as the point on the receiver's path at position
+ index."
+
+ ^collectionOfPoints at: index put: aPoint!

Item was added:
+ ----- Method: DisplayPath>>collect: (in category 'enumerating') -----
+ collect: aBlock
+ "Evaluate aBlock with each of the receiver's elements as the argument.
+ Collect the resulting values into a path that is like the receiver. Answer
+ the new path."
+
+ | newCollection |
+ newCollection := collectionOfPoints collect: aBlock.
+ newCollection form: self form.
+ ^newCollection!

Item was added:
+ ----- Method: DisplayPath>>computeBoundingBox (in category 'display box access') -----
+ computeBoundingBox
+ "Refer to the comment in DisplayObject|computeBoundingBox."
+
+ | box |
+ box := Rectangle origin: (self at: 1) extent: 0 @ 0.
+ collectionOfPoints do:
+ [:aPoint | box swallow: (Rectangle origin: aPoint extent: 0 @ 0)].
+ ^box!

Item was added:
+ ----- Method: DisplayPath>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
+ "Display this Path--offset by aPoint, clipped by clipRect and the form
+ associated with this Path will be displayedr according to one of the sixteen
+ functions of two logical variables (rule). Also the source form will be first
+ anded with aForm as a mask. Does not effect the state of the Path"
+
+ collectionOfPoints do:
+ [:element |
+ self form
+ displayOn: aDisplayMedium
+ at: element + aDisplayPoint
+ clippingBox: clipRectangle
+ rule: ruleInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplayPath>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
+ "Displays this path, translated and scaled by aTransformation. Get the
+ scaled and translated DisplayPath."
+
+ | newDisplayPath transformedDisplayPath |
+ transformedDisplayPath := displayTransformation applyTo: self.
+ newDisplayPath := DisplayPath new.
+ transformedDisplayPath do: [:point | newDisplayPath add: point].
+ newDisplayPath form: self form.
+ newDisplayPath
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRectangle
+ rule: ruleInteger
+ fillColor: aForm!

Item was added:
+ ----- Method: DisplayPath>>first (in category 'accessing') -----
+ first
+ "Answer the first point on the receiver's path; included to correspond to
+ OrderedCollection protocol."
+
+ ^collectionOfPoints first!

Item was added:
+ ----- Method: DisplayPath>>firstPoint (in category 'accessing') -----
+ firstPoint
+ "Answer the first point on the receiver's path."
+
+ ^collectionOfPoints first!

Item was added:
+ ----- Method: DisplayPath>>firstPoint: (in category 'accessing') -----
+ firstPoint: aPoint
+ "Replace the first element of the receiver with the new value aPoint.
+ Answer the argument aPoint."
+
+ collectionOfPoints at: 1 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayPath>>form (in category 'accessing') -----
+ form
+ "Answer the receiver's form, or, if form is nil, then answer a 1 x 1 black
+ form (a black dot)."
+
+ | aForm |
+ form == nil
+ ifTrue:
+ [aForm := Form extent: 1 @ 1.
+ aForm fillBlack.
+ ^aForm]
+ ifFalse:
+ [^form]!

Item was added:
+ ----- Method: DisplayPath>>form: (in category 'accessing') -----
+ form: aForm
+ "Make the argument, aForm, be the receiver's form."
+
+ form := aForm!

Item was added:
+ ----- Method: DisplayPath>>initializeCollectionOfPoints (in category 'private') -----
+ initializeCollectionOfPoints
+
+ collectionOfPoints := OrderedCollection new!

Item was added:
+ ----- Method: DisplayPath>>initializeCollectionOfPoints: (in category 'private') -----
+ initializeCollectionOfPoints: anInteger
+
+ collectionOfPoints := OrderedCollection new: anInteger!

Item was added:
+ ----- Method: DisplayPath>>isEmpty (in category 'testing') -----
+ isEmpty
+
+ ^collectionOfPoints isEmpty!

Item was added:
+ ----- Method: DisplayPath>>last (in category 'accessing') -----
+ last
+ "Answer the last point on the receiver's path; included to correspond to
+ OrderedCollection protocol."
+
+ ^collectionOfPoints last!

Item was added:
+ ----- Method: DisplayPath>>offset (in category 'accessing') -----
+ offset
+ "There are basically two kinds of display objects in the system: those
+ that, when asked to transform themselves, create a new object; and those
+ that side effect themselves by maintaining a record of the transformation
+ request (typically an offset). Path, like Rectangle and Point, is a display
+ object of the first kind."
+
+ self shouldNotImplement!

Item was added:
+ ----- Method: DisplayPath>>removeAllSuchThat: (in category 'removing') -----
+ removeAllSuchThat: aBlock
+ "Evaluate aBlock for each element of the receiver.
+ Remove each element for which aBlock evaluates to true."
+
+ collectionOfPoints removeAllSuchThat: aBlock.
+ !

Item was added:
+ ----- Method: DisplayPath>>scaleBy: (in category 'transforming') -----
+ scaleBy: aPoint
+ "Answers a new Path scaled by aPoint. Does not affect the current data in
+ this Path."
+
+ | newPath |
+ newPath := self species new: self size.
+ newPath form: self form.
+ collectionOfPoints do: [:element | newPath add: (element scaleBy: aPoint)].
+ ^newPath!

Item was added:
+ ----- Method: DisplayPath>>secondPoint (in category 'accessing') -----
+ secondPoint
+ "Answer the second element of the receiver."
+
+ ^collectionOfPoints at: 2!

Item was added:
+ ----- Method: DisplayPath>>secondPoint: (in category 'accessing') -----
+ secondPoint: aPoint
+ "Replace the second element of the receiver with the new value aPoint.
+ Answer the argument aPoint."
+
+ collectionOfPoints at: 2 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayPath>>select: (in category 'enumerating') -----
+ select: aBlock
+ "Evaluate aBlock with each of the receiver's elements as the argument.
+ Collect into a new path like the receiver only those elements for which
+ aBlock evaluates to true. Answer the new path."
+
+ | newCollection |
+ newCollection := collectionOfPoints select: aBlock.
+ newCollection form: self form.
+ ^newCollection!

Item was added:
+ ----- Method: DisplayPath>>size (in category 'accessing') -----
+ size
+ "Answer the length of the receiver."
+
+ ^collectionOfPoints size!

Item was added:
+ ----- Method: DisplayPath>>thirdPoint (in category 'accessing') -----
+ thirdPoint
+ "Answer the third element of the receiver."
+
+ ^collectionOfPoints at: 3!

Item was added:
+ ----- Method: DisplayPath>>thirdPoint: (in category 'accessing') -----
+ thirdPoint: aPoint
+ "Replace the third element of the receiver with the new value aPoint.
+ Answer the argument aPoint."
+
+ collectionOfPoints at: 3 put: aPoint.
+ ^aPoint!

Item was added:
+ ----- Method: DisplayPath>>translateBy: (in category 'transforming') -----
+ translateBy: aPoint
+ "Answers a new Path whose elements are translated by aPoint. Does not
+ affect the elements of this Path."
+
+ | newPath |
+ newPath := self species new: self size.
+ newPath form: self form.
+ collectionOfPoints do: [:element | newPath add: (element translateBy: aPoint)].
+ ^newPath!

Item was added:
+ DisplayPath subclass: #DisplaySpline
+ instanceVariableNames: 'coefficients'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'ST80-Paths'!
+
+ !DisplaySpline commentStamp: '' prior: 0!
+ I represent a collection of Points through which a cubic spline curve is fitted.!

Item was added:
+ ----- Method: DisplaySpline class>>example (in category 'examples') -----
+ example
+ "Designate points on the Path by clicking the red button. Terminate by
+ pressing any other button. A curve will be displayed, through the
+ selected points, using a long black form."
+
+ | splineCurve aForm flag|
+ aForm := Form extent: 2@2.
+ aForm fillBlack.
+ splineCurve := DisplaySpline new.
+ splineCurve form: aForm.
+ flag := true.
+ [flag] whileTrue:
+ [Sensor waitButton.
+ Sensor redButtonPressed
+ ifTrue:
+ [splineCurve add: Sensor waitButton.
+ Sensor waitNoButton.
+ aForm displayOn: Display at: splineCurve last]
+ ifFalse: [flag:=false]].
+ splineCurve computeCurve.
+ splineCurve isEmpty
+ ifFalse: [splineCurve displayOn: Display.
+ Sensor waitNoButton].
+
+ "DisplaySpline example"!

Item was added:
+ ----- Method: DisplaySpline>>coefficients (in category 'accessing') -----
+ coefficients
+ "Answer an eight-element Array of Arrays each of which is the length
+ of the receiver. The first four arrays are the values, first, second and
+ third derivatives, respectively, for the parametric spline in x. The last
+ four elements are for y."
+
+ ^coefficients!

Item was added:
+ ----- Method: DisplaySpline>>computeCurve (in category 'displaying') -----
+ computeCurve
+ "Compute an array for the coefficients."
+
+ | length extras |
+ length := self size.
+ extras := 0.
+ coefficients := Array new: 8.
+ 1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].
+ 1 to: 5 by: 4 do:
+ [:k |
+ 1 to: length do:
+ [:i | (coefficients at: k)
+ at: i put: (k = 1
+ ifTrue: [(self at: i) x asFloat]
+ ifFalse: [(self at: i) y asFloat])].
+ 1 to: extras do: [:i | (coefficients at: k)
+ at: length + i put: ((coefficients at: k)
+ at: i + 1)].
+ self derivs: (coefficients at: k)
+ first: (coefficients at: k + 1)
+ second: (coefficients at: k + 2)
+ third: (coefficients at: k + 3)].
+ extras > 0
+ ifTrue: [1 to: 8 do:
+ [:i |
+ coefficients at: i put: ((coefficients at: i)
+ copyFrom: 2 to: length + 1)]]!

Item was added:
+ ----- Method: DisplaySpline>>derivs:first:second:third: (in category 'private') -----
+ derivs: a first: point1 second: point2 third: point3
+ "Compute the first, second and third derivitives (in coefficients) from
+ the Points in this Path (coefficients at: 1 and coefficients at: 5)."
+
+ | l v anArray |
+ l := a size.
+ l < 2 ifTrue: [^self].
+ l > 2
+ ifTrue:
+ [v := Array new: l.
+ v at: 1 put: 4.0.
+ anArray := Array new: l.
+ anArray at: 1 put: (6.0 * ((a at: 1) - ((a at: 2) * 2.0) + (a at: 3))).
+ 2 to: l - 2 do:
+ [:i |
+ v at: i put: (4.0 - (1.0 / (v at: (i - 1)))).
+ anArray
+ at: i
+ put: (6.0 * ((a at: i) - ((a at: (i + 1)) * 2.0) + (a at: (i + 2)))
+ - ((anArray at: (i - 1)) / (v at: (i - 1))))].
+ point2 at: (l - 1) put: ((anArray at: (l - 2)) / (v at: (l - 2))).
+ l - 2 to: 2 by: 0-1 do:
+ [:i |
+ point2
+ at: i
+ put: ((anArray at: (i - 1)) - (point2 at: (i + 1)) / (v at: (i - 1)))]].
+ point2 at: 1 put: (point2 at: l put: 0.0).
+ 1 to: l - 1 do:
+ [:i | point1
+ at: i
+ put: ((a at: (i + 1)) - (a at: i) -
+ ((point2 at: i) * 2.0 + (point2 at: (i + 1)) / 6.0)).
+ point3 at: i put: ((point2 at: (i + 1)) - (point2 at: i))]!

Item was added:
+ ----- Method: DisplaySpline>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
+ "Display the receiver, a spline curve, approximated by straight line
+ segments."
+
+ | n line t x y x1 x2 x3 y1 y2 y3 |
+ collectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point'].
+ line := DisplayLine new.
+ line form: self form.
+ line beginPoint:
+ (x := (coefficients at: 1) at: 1) rounded @ (y := (coefficients at: 5) at: 1) rounded.
+ 1 to: (coefficients at: 1) size - 1 do:
+ [:i |
+ "taylor series coefficients"
+ x1 := (coefficients at: 2) at: i.
+ y1 := (coefficients at: 6) at: i.
+ x2 := ((coefficients at: 3) at: i) / 2.0.
+ y2 := ((coefficients at: 7) at: i) / 2.0.
+ x3 := ((coefficients at: 4) at: i) / 6.0.
+ y3 := ((coefficients at: 8) at: i) / 6.0.
+ "guess n"
+ n := 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3)
+ at: i + 1) abs + ((coefficients at: 7)
+ at: i + 1) abs / 100.0) rounded.
+ 1 to: n - 1 do:
+ [:j |
+ t := j asFloat / n.
+ line endPoint:
+ (x3 * t + x2 * t + x1 * t + x) rounded
+ @ (y3 * t + y2 * t + y1 * t + y) rounded.
+ line
+ displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm.
+ line beginPoint: line endPoint].
+ line beginPoint:
+ (x := (coefficients at: 1) at: i + 1) rounded
+ @ (y := (coefficients at: 5) at: i + 1) rounded.
+ line
+ displayOn: aDisplayMedium
+ at: aPoint
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm]!

Item was added:
+ ----- Method: DisplaySpline>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
+ displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
+ "Get the scaled and translated path of newKnots."
+
+ | newKnots newDisplaySpline |
+ newKnots := aTransformation applyTo: self.
+ newDisplaySpline := DisplaySpline new.
+ newKnots do: [:knot | newDisplaySpline add: knot].
+ newDisplaySpline form: self form.
+ newDisplaySpline
+ displayOn: aDisplayMedium
+ at: 0 @ 0
+ clippingBox: clipRect
+ rule: anInteger
+ fillColor: aForm!

Item was changed:
----- Method: FormEditor>>curve (in category 'editing tools') -----
curve
"Conic-section specified by three points designated by: first point--press
red button second point--release red button third point--click red button.
The resultant curve on the display is displayed according to the current
form and mode."

| firstPoint secondPoint thirdPoint curve drawForm |
"sensor noButtonPressed ifTrue: [^self]."
firstPoint := self cursorPoint.
secondPoint := self rubberBandFrom: firstPoint until: [sensor noButtonPressed].
thirdPoint := self rubberBandFrom: secondPoint until: [sensor redButtonPressed].
Display depth > 1
ifTrue:
[self deleteRubberBandFrom: secondPoint to: thirdPoint.
self deleteRubberBandFrom: firstPoint to: secondPoint].
+ curve := DisplayCurveFitter new.
- curve := CurveFitter new.
curve firstPoint: firstPoint.
curve secondPoint: secondPoint.
curve thirdPoint: thirdPoint.
drawForm := form asFormOfDepth: Display depth.
Display depth > 1 ifTrue:
[drawForm mapColor: Color white to: Color transparent;
mapColor: Color black to: color].

curve form: drawForm.
curve
displayOn: Display
at: 0 @ 0
clippingBox: view insetDisplayBox
rule: (Display depth > 1 ifTrue: [mode ~= Form erase ifTrue: [Form paint] ifFalse: [mode]]
ifFalse: [mode])
fillColor: (Display depth = 1 ifTrue: [color] ifFalse: [nil]).
sensor waitNoButton.
hasUnsavedChanges contents: true.!

Item was changed:
----- Method: FormEditor>>deleteRubberBandFrom:to: (in category 'private') -----
deleteRubberBandFrom: startPoint to: endPoint

+ (DisplayLine from: startPoint to: endPoint withForm: form)
- (Line from: startPoint to: endPoint withForm: form)
displayOn: Display
at: 0 @ 0
clippingBox: view insetDisplayBox
rule: Form reverse
fillColor: (Display depth = 1 ifTrue: [Color black] ifFalse: [Color gray]).!

Item was changed:
----- Method: FormEditor>>line (in category 'editing tools') -----
line
+ "DisplayLine is specified by two points from the mouse: first point--press red
- "Line is specified by two points from the mouse: first point--press red
button; second point--release red button. The resultant line is displayed
according to the current form and mode."

| firstPoint endPoint drawForm |
drawForm := form asFormOfDepth: Display depth.

Display depth > 1
ifTrue:
[drawForm mapColor: Color white to: Color transparent;
mapColor: Color black to: color].

firstPoint := self cursorPoint.
endPoint := self rubberBandFrom: firstPoint until: [sensor noButtonPressed].
endPoint isNil ifTrue: [^self].
Display depth > 1 ifTrue: [self deleteRubberBandFrom: firstPoint to: endPoint.].
+ (DisplayLine from: firstPoint to: endPoint withForm: drawForm)
- (Line from: firstPoint to: endPoint withForm: drawForm)
displayOn: Display
at: 0 @ 0
clippingBox: view insetDisplayBox
rule: (Display depth > 1 ifTrue: [mode ~= Form erase ifTrue: [Form paint] ifFalse: [mode]]
ifFalse: [mode])
fillColor: (Display depth = 1 ifTrue: [color] ifFalse: [nil]).
hasUnsavedChanges contents: true.!

Item was changed:
----- Method: FormEditor>>rubberBandFrom:until: (in category 'private') -----
rubberBandFrom: startPoint until: aBlock

| endPoint previousEndPoint |
previousEndPoint := startPoint.
[aBlock value] whileFalse:
[(endPoint := self cursorPoint) = previousEndPoint
ifFalse:
+ [(DisplayLine from: startPoint to: previousEndPoint withForm: form)
- [(Line from: startPoint to: previousEndPoint withForm: form)
displayOn: Display
at: 0 @ 0
clippingBox: view insetDisplayBox
rule: Form reverse
fillColor: Color gray.
+ (DisplayLine from: startPoint to: endPoint withForm: form)
- (Line from: startPoint to: endPoint withForm: form)
displayOn: Display
at: 0 @ 0
clippingBox: view insetDisplayBox
rule: Form reverse
fillColor: Color gray.
previousEndPoint := endPoint]].
+ (DisplayLine from: startPoint to: previousEndPoint withForm: form)
- (Line from: startPoint to: previousEndPoint withForm: form)
displayOn: Display
at: 0 @ 0
clippingBox: view insetDisplayBox
rule: Form reverse
fillColor: (Display depth = 1 ifTrue: [Color gray] ifFalse: [Color black]).
^endPoint!

Item was changed:
----- Method: GraphicSymbolInstance class>>example (in category 'examples') -----
example
"Simply evaluate the method and two GraphicSymbolInstances, each
displaying a transformation of the same graphic symbol, will be
presented on the screen. Clears the screen to white."

| gate instance1 instance2 trans1 trans2 line arc f|
Display fillWhite. "clear the Screen."
f := Form extent: 2 @ 2.
f fillBlack.
gate:= GraphicSymbol new. "make a logic gate out of lines and arcs."
+ line:=DisplayLine new. line beginPoint: -20 @ -20. line endPoint: 0 @ -20. line form: f.
- line:=Line new. line beginPoint: -20 @ -20. line endPoint: 0 @ -20. line form: f.
gate add: line.

+ line:=DisplayLine new. line beginPoint: -20 @ 20. line endPoint: 0 @ 20. line form: f.
- line:=Line new. line beginPoint: -20 @ 20. line endPoint: 0 @ 20. line form: f.
gate add: line.

+ line:=DisplayLine new. line beginPoint: 0 @ -40. line endPoint: 0 @ 40. line form: f.
- line:=Line new. line beginPoint: 0 @ -40. line endPoint: 0 @ 40. line form: f.
gate add: line.

+ arc := DisplayArc new. arc center: 0 @ 0 radius: 40 quadrant: 1.
- arc := Arc new. arc center: 0 @ 0 radius: 40 quadrant: 1.
arc form: f.
gate add: arc.

+ arc := DisplayArc new. arc center: 0 @ 0 radius: 40 quadrant: 4.
- arc := Arc new. arc center: 0 @ 0 radius: 40 quadrant: 4.
arc form: f.
gate add: arc.

"one instance at 1/2 scale."
trans1:=WindowingTransformation identity.
trans1:= trans1 scaleBy: 0.5 @ 0.5.
trans1:= trans1 translateBy: 100 @ 100.

"the other instance at 2 times scale"
trans2:=WindowingTransformation identity.
trans2:= trans2 scaleBy: 2.0 @ 2.0.
trans2:= trans2 translateBy: 200 @ 200.

instance1 := GraphicSymbolInstance new.
instance1 transformation: trans1.
instance1 graphicSymbol: gate.

instance2 := GraphicSymbolInstance new.
instance2 transformation: trans2.
instance2 graphicSymbol: gate.

"display both instances of the logic gate"
instance1 displayOn: Display
transformation: WindowingTransformation identity
clippingBox: Display boundingBox
rule: Form under
fillColor: nil.
instance2 displayOn: Display
transformation: WindowingTransformation identity
clippingBox: Display boundingBox
rule: Form under
fillColor: nil

"GraphicSymbolInstance example"!

Item was removed:
- Path subclass: #Line
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Line commentStamp: '' prior: 0!
- I represent the line segment specified by two points.!

Item was removed:
- ----- Method: Line class>>example (in category 'examples') -----
- example
- "Designate two places on the screen by clicking any mouse button. A
- straight path with a square black form will be displayed connecting the
- two selected points."
-
- | aLine aForm |
- aForm := Form extent: 20@20. "make a form one quarter of inch square"
- aForm fillBlack. "turn it black"
- aLine := Line new.
- aLine form: aForm. "use the black form for display"
- aLine beginPoint: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aLine beginPoint.
- aLine endPoint: Sensor waitButton.
- aLine displayOn: Display. "display the line"
-
- "Line example"!

Item was removed:
- ----- Method: Line class>>from:to:withForm: (in category 'instance creation') -----
- from: beginPoint to: endPoint withForm: aForm
- "Answer an instance of me with end points begingPoint and endPoint;
- the source form for displaying the line is aForm."
-
- | newSelf |
- newSelf := super new: 2.
- newSelf add: beginPoint.
- newSelf add: endPoint.
- newSelf form: aForm.
- ^newSelf!

Item was removed:
- ----- Method: Line class>>new (in category 'instance creation') -----
- new
-
- | newSelf |
- newSelf := super new: 2.
- newSelf add: 0@0.
- newSelf add: 0@0.
- ^newSelf!

Item was removed:
- ----- Method: Line>>beginPoint (in category 'accessing') -----
- beginPoint
- "Answer the first end point of the receiver."
-
- ^self first!

Item was removed:
- ----- Method: Line>>beginPoint: (in category 'accessing') -----
- beginPoint: aPoint
- "Set the first end point of the receiver to be the argument, aPoint.
- Answer aPoint."
-
- self at: 1 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Line>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
- "The form associated with this Path will be displayed, according
- to one of the sixteen functions of two logical variables (rule), at
- each point on the Line. Also the source form will be first anded
- with aForm as a mask. Does not effect the state of the Path."
-
- collectionOfPoints size < 2 ifTrue: [self error: 'a line must have two points'].
- aDisplayMedium
- drawLine: self form
- from: self beginPoint + aPoint
- to: self endPoint + aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Line>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
-
- | newPath newLine |
- newPath := aTransformation applyTo: self.
- newLine := Line new.
- newLine beginPoint: newPath firstPoint.
- newLine endPoint: newPath secondPoint.
- newLine form: self form.
- newLine
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Line>>displayOnPort:at: (in category 'displaying') -----
- displayOnPort: aPort at: aPoint
- aPort sourceForm: self form; combinationRule: Form under; fillColor: nil.
- aPort drawFrom: collectionOfPoints first + aPoint
- to: collectionOfPoints last + aPoint!

Item was removed:
- ----- Method: Line>>endPoint (in category 'accessing') -----
- endPoint
- "Answer the last end point of the receiver."
-
- ^self last!

Item was removed:
- ----- Method: Line>>endPoint: (in category 'accessing') -----
- endPoint: aPoint
- "Set the first end point of the receiver to be the argument, aPoint.
- Answer aPoint."
-
- self at: 2 put: aPoint.
- ^aPoint!

Item was removed:
- Path subclass: #LinearFit
- instanceVariableNames: ''
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !LinearFit commentStamp: '' prior: 0!
- I represent a piece-wise linear approximation to a set of points in the plane.!

Item was removed:
- ----- Method: LinearFit class>>example (in category 'examples') -----
- example
- "Select points on a Path using the red button. Terminate by selecting
- any other button. Creates a Path from the points and displays it as a
- piece-wise linear approximation."
-
- | aLinearFit aForm flag |
- aLinearFit := LinearFit new.
- aForm := Form extent: 1 @ 40.
- aForm fillBlack.
- aLinearFit form: aForm.
- flag := true.
- [flag] whileTrue:
- [Sensor waitButton.
- Sensor redButtonPressed
- ifTrue: [aLinearFit add: Sensor waitButton. Sensor waitNoButton.
- aForm displayOn: Display at: aLinearFit last]
- ifFalse: [flag:=false]].
- aLinearFit displayOn: Display
-
- "LinearFit example"!

Item was removed:
- ----- Method: LinearFit>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger
- fillColor: aForm
-
- | line |
- line := Line new.
- line form: self form.
- 1 to: self size - 1 do:
- [:i |
- line beginPoint: (self at: i).
- line endPoint: (self at: i + 1).
- line displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: LinearFit>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox:
- clipRect rule: anInteger fillColor: aForm
-
- | transformedPath |
- "get the scaled and translated Path."
- transformedPath := aTransformation applyTo: self.
- transformedPath
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!

Item was removed:
- DisplayObject subclass: #Path
- instanceVariableNames: 'form collectionOfPoints'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Path commentStamp: '' prior: 0!
- I am the abstract superclass of the Graphic spatial primitives. I represent an ordered sequence of Points. Spatial primitives are used to generate "trajectories" such as lines and circles.!

Item was removed:
- ----- Method: Path class>>example (in category 'examples') -----
- example
- "Creates a Path from mousePoints and displays it several ways on the display screen. Messes up the display. For learning about class Path, just select the code below and execute it to create a path and see it redisplayed in another place on the screen. Each path displays using a different form. A path is indicated by pressing the red mouse button in a sequence; press any other mouse button to terminate. "
-
- | aPath aForm pl fl flag |
- aForm := Form extent: 2 @ 40. "creates a form one inch long"
- aForm fillBlack. "turns it black"
- aPath := Path new.
- aPath form: aForm. "use the long black form for displaying"
- flag := true.
- [flag]
- whileTrue:
- [Sensor waitButton.
- Sensor redButtonPressed
- ifTrue:
- [aPath add: Sensor waitButton.
- Sensor waitNoButton.
- aForm displayOn: Display at: aPath last]
- ifFalse: [flag := false]].
- Display fillWhite.
- aPath displayOn: Display. "the original path"
- pl := aPath translateBy: 0 @ 100.
- fl := Form extent: 40 @ 40.
- fl fillGray.
- pl form: fl.
- pl displayOn: Display. "the translated path"
- Sensor waitNoButton
-
- "Path example"!

Item was removed:
- ----- Method: Path class>>new (in category 'instance creation') -----
- new
-
- ^self basicNew initializeCollectionOfPoints!

Item was removed:
- ----- Method: Path class>>new: (in category 'instance creation') -----
- new: anInteger
-
- ^self basicNew initializeCollectionOfPoints: anInteger!

Item was removed:
- ----- Method: Path>>add: (in category 'adding') -----
- add: aPoint
- "Include aPoint as one of the receiver's elements."
-
- ^collectionOfPoints add: aPoint!

Item was removed:
- ----- Method: Path>>at: (in category 'accessing') -----
- at: index
- "Answer the point on the receiver's path at position index."
-
- ^collectionOfPoints at: index!

Item was removed:
- ----- Method: Path>>at:put: (in category 'accessing') -----
- at: index put: aPoint
- "Store the argument, aPoint, as the point on the receiver's path at position
- index."
-
- ^collectionOfPoints at: index put: aPoint!

Item was removed:
- ----- Method: Path>>collect: (in category 'enumerating') -----
- collect: aBlock
- "Evaluate aBlock with each of the receiver's elements as the argument.
- Collect the resulting values into a path that is like the receiver. Answer
- the new path."
-
- | newCollection |
- newCollection := collectionOfPoints collect: aBlock.
- newCollection form: self form.
- ^newCollection!

Item was removed:
- ----- Method: Path>>computeBoundingBox (in category 'display box access') -----
- computeBoundingBox
- "Refer to the comment in DisplayObject|computeBoundingBox."
-
- | box |
- box := Rectangle origin: (self at: 1) extent: 0 @ 0.
- collectionOfPoints do:
- [:aPoint | box swallow: (Rectangle origin: aPoint extent: 0 @ 0)].
- ^box!

Item was removed:
- ----- Method: Path>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
- "Display this Path--offset by aPoint, clipped by clipRect and the form
- associated with this Path will be displayedr according to one of the sixteen
- functions of two logical variables (rule). Also the source form will be first
- anded with aForm as a mask. Does not effect the state of the Path"
-
- collectionOfPoints do:
- [:element |
- self form
- displayOn: aDisplayMedium
- at: element + aDisplayPoint
- clippingBox: clipRectangle
- rule: ruleInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: Path>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
- "Displays this path, translated and scaled by aTransformation. Get the
- scaled and translated Path."
-
- | newPath transformedPath |
- transformedPath := displayTransformation applyTo: self.
- newPath := Path new.
- transformedPath do: [:point | newPath add: point].
- newPath form: self form.
- newPath
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRectangle
- rule: ruleInteger
- fillColor: aForm!

Item was removed:
- ----- Method: Path>>first (in category 'accessing') -----
- first
- "Answer the first point on the receiver's path; included to correspond to
- OrderedCollection protocol."
-
- ^collectionOfPoints first!

Item was removed:
- ----- Method: Path>>firstPoint (in category 'accessing') -----
- firstPoint
- "Answer the first point on the receiver's path."
-
- ^collectionOfPoints first!

Item was removed:
- ----- Method: Path>>firstPoint: (in category 'accessing') -----
- firstPoint: aPoint
- "Replace the first element of the receiver with the new value aPoint.
- Answer the argument aPoint."
-
- collectionOfPoints at: 1 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Path>>form (in category 'accessing') -----
- form
- "Answer the receiver's form, or, if form is nil, then answer a 1 x 1 black
- form (a black dot)."
-
- | aForm |
- form == nil
- ifTrue:
- [aForm := Form extent: 1 @ 1.
- aForm fillBlack.
- ^aForm]
- ifFalse:
- [^form]!

Item was removed:
- ----- Method: Path>>form: (in category 'accessing') -----
- form: aForm
- "Make the argument, aForm, be the receiver's form."
-
- form := aForm!

Item was removed:
- ----- Method: Path>>initializeCollectionOfPoints (in category 'private') -----
- initializeCollectionOfPoints
-
- collectionOfPoints := OrderedCollection new!

Item was removed:
- ----- Method: Path>>initializeCollectionOfPoints: (in category 'private') -----
- initializeCollectionOfPoints: anInteger
-
- collectionOfPoints := OrderedCollection new: anInteger!

Item was removed:
- ----- Method: Path>>isEmpty (in category 'testing') -----
- isEmpty
-
- ^collectionOfPoints isEmpty!

Item was removed:
- ----- Method: Path>>last (in category 'accessing') -----
- last
- "Answer the last point on the receiver's path; included to correspond to
- OrderedCollection protocol."
-
- ^collectionOfPoints last!

Item was removed:
- ----- Method: Path>>offset (in category 'accessing') -----
- offset
- "There are basically two kinds of display objects in the system: those
- that, when asked to transform themselves, create a new object; and those
- that side effect themselves by maintaining a record of the transformation
- request (typically an offset). Path, like Rectangle and Point, is a display
- object of the first kind."
-
- self shouldNotImplement!

Item was removed:
- ----- Method: Path>>removeAllSuchThat: (in category 'removing') -----
- removeAllSuchThat: aBlock
- "Evaluate aBlock for each element of the receiver.
- Remove each element for which aBlock evaluates to true."
-
- collectionOfPoints removeAllSuchThat: aBlock.
- !

Item was removed:
- ----- Method: Path>>scaleBy: (in category 'transforming') -----
- scaleBy: aPoint
- "Answers a new Path scaled by aPoint. Does not affect the current data in
- this Path."
-
- | newPath |
- newPath := self species new: self size.
- newPath form: self form.
- collectionOfPoints do: [:element | newPath add: (element scaleBy: aPoint)].
- ^newPath!

Item was removed:
- ----- Method: Path>>secondPoint (in category 'accessing') -----
- secondPoint
- "Answer the second element of the receiver."
-
- ^collectionOfPoints at: 2!

Item was removed:
- ----- Method: Path>>secondPoint: (in category 'accessing') -----
- secondPoint: aPoint
- "Replace the second element of the receiver with the new value aPoint.
- Answer the argument aPoint."
-
- collectionOfPoints at: 2 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Path>>select: (in category 'enumerating') -----
- select: aBlock
- "Evaluate aBlock with each of the receiver's elements as the argument.
- Collect into a new path like the receiver only those elements for which
- aBlock evaluates to true. Answer the new path."
-
- | newCollection |
- newCollection := collectionOfPoints select: aBlock.
- newCollection form: self form.
- ^newCollection!

Item was removed:
- ----- Method: Path>>size (in category 'accessing') -----
- size
- "Answer the length of the receiver."
-
- ^collectionOfPoints size!

Item was removed:
- ----- Method: Path>>thirdPoint (in category 'accessing') -----
- thirdPoint
- "Answer the third element of the receiver."
-
- ^collectionOfPoints at: 3!

Item was removed:
- ----- Method: Path>>thirdPoint: (in category 'accessing') -----
- thirdPoint: aPoint
- "Replace the third element of the receiver with the new value aPoint.
- Answer the argument aPoint."
-
- collectionOfPoints at: 3 put: aPoint.
- ^aPoint!

Item was removed:
- ----- Method: Path>>translateBy: (in category 'transforming') -----
- translateBy: aPoint
- "Answers a new Path whose elements are translated by aPoint. Does not
- affect the elements of this Path."
-
- | newPath |
- newPath := self species new: self size.
- newPath form: self form.
- collectionOfPoints do: [:element | newPath add: (element translateBy: aPoint)].
- ^newPath!

Item was removed:
- Path subclass: #Spline
- instanceVariableNames: 'coefficients'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'ST80-Paths'!
-
- !Spline commentStamp: '' prior: 0!
- I represent a collection of Points through which a cubic spline curve is fitted.!

Item was removed:
- ----- Method: Spline class>>example (in category 'examples') -----
- example
- "Designate points on the Path by clicking the red button. Terminate by
- pressing any other button. A curve will be displayed, through the
- selected points, using a long black form."
-
- | splineCurve aForm flag|
- aForm := Form extent: 2@2.
- aForm fillBlack.
- splineCurve := Spline new.
- splineCurve form: aForm.
- flag := true.
- [flag] whileTrue:
- [Sensor waitButton.
- Sensor redButtonPressed
- ifTrue:
- [splineCurve add: Sensor waitButton.
- Sensor waitNoButton.
- aForm displayOn: Display at: splineCurve last]
- ifFalse: [flag:=false]].
- splineCurve computeCurve.
- splineCurve isEmpty
- ifFalse: [splineCurve displayOn: Display.
- Sensor waitNoButton].
-
- "Spline example"!

Item was removed:
- ----- Method: Spline>>coefficients (in category 'accessing') -----
- coefficients
- "Answer an eight-element Array of Arrays each of which is the length
- of the receiver. The first four arrays are the values, first, second and
- third derivatives, respectively, for the parametric spline in x. The last
- four elements are for y."
-
- ^coefficients!

Item was removed:
- ----- Method: Spline>>computeCurve (in category 'displaying') -----
- computeCurve
- "Compute an array for the coefficients."
-
- | length extras |
- length := self size.
- extras := 0.
- coefficients := Array new: 8.
- 1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].
- 1 to: 5 by: 4 do:
- [:k |
- 1 to: length do:
- [:i | (coefficients at: k)
- at: i put: (k = 1
- ifTrue: [(self at: i) x asFloat]
- ifFalse: [(self at: i) y asFloat])].
- 1 to: extras do: [:i | (coefficients at: k)
- at: length + i put: ((coefficients at: k)
- at: i + 1)].
- self derivs: (coefficients at: k)
- first: (coefficients at: k + 1)
- second: (coefficients at: k + 2)
- third: (coefficients at: k + 3)].
- extras > 0
- ifTrue: [1 to: 8 do:
- [:i |
- coefficients at: i put: ((coefficients at: i)
- copyFrom: 2 to: length + 1)]]!

Item was removed:
- ----- Method: Spline>>derivs:first:second:third: (in category 'private') -----
- derivs: a first: point1 second: point2 third: point3
- "Compute the first, second and third derivitives (in coefficients) from
- the Points in this Path (coefficients at: 1 and coefficients at: 5)."
-
- | l v anArray |
- l := a size.
- l < 2 ifTrue: [^self].
- l > 2
- ifTrue:
- [v := Array new: l.
- v at: 1 put: 4.0.
- anArray := Array new: l.
- anArray at: 1 put: (6.0 * ((a at: 1) - ((a at: 2) * 2.0) + (a at: 3))).
- 2 to: l - 2 do:
- [:i |
- v at: i put: (4.0 - (1.0 / (v at: (i - 1)))).
- anArray
- at: i
- put: (6.0 * ((a at: i) - ((a at: (i + 1)) * 2.0) + (a at: (i + 2)))
- - ((anArray at: (i - 1)) / (v at: (i - 1))))].
- point2 at: (l - 1) put: ((anArray at: (l - 2)) / (v at: (l - 2))).
- l - 2 to: 2 by: 0-1 do:
- [:i |
- point2
- at: i
- put: ((anArray at: (i - 1)) - (point2 at: (i + 1)) / (v at: (i - 1)))]].
- point2 at: 1 put: (point2 at: l put: 0.0).
- 1 to: l - 1 do:
- [:i | point1
- at: i
- put: ((a at: (i + 1)) - (a at: i) -
- ((point2 at: i) * 2.0 + (point2 at: (i + 1)) / 6.0)).
- point3 at: i put: ((point2 at: (i + 1)) - (point2 at: i))]!

Item was removed:
- ----- Method: Spline>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
- "Display the receiver, a spline curve, approximated by straight line
- segments."
-
- | n line t x y x1 x2 x3 y1 y2 y3 |
- collectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point'].
- line := Line new.
- line form: self form.
- line beginPoint:
- (x := (coefficients at: 1) at: 1) rounded @ (y := (coefficients at: 5) at: 1) rounded.
- 1 to: (coefficients at: 1) size - 1 do:
- [:i |
- "taylor series coefficients"
- x1 := (coefficients at: 2) at: i.
- y1 := (coefficients at: 6) at: i.
- x2 := ((coefficients at: 3) at: i) / 2.0.
- y2 := ((coefficients at: 7) at: i) / 2.0.
- x3 := ((coefficients at: 4) at: i) / 6.0.
- y3 := ((coefficients at: 8) at: i) / 6.0.
- "guess n"
- n := 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3)
- at: i + 1) abs + ((coefficients at: 7)
- at: i + 1) abs / 100.0) rounded.
- 1 to: n - 1 do:
- [:j |
- t := j asFloat / n.
- line endPoint:
- (x3 * t + x2 * t + x1 * t + x) rounded
- @ (y3 * t + y2 * t + y1 * t + y) rounded.
- line
- displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm.
- line beginPoint: line endPoint].
- line beginPoint:
- (x := (coefficients at: 1) at: i + 1) rounded
- @ (y := (coefficients at: 5) at: i + 1) rounded.
- line
- displayOn: aDisplayMedium
- at: aPoint
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm]!

Item was removed:
- ----- Method: Spline>>displayOn:transformation:clippingBox:rule:fillColor: (in category 'displaying') -----
- displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
- "Get the scaled and translated path of newKnots."
-
- | newKnots newSpline |
- newKnots := aTransformation applyTo: self.
- newSpline := Spline new.
- newKnots do: [:knot | newSpline add: knot].
- newSpline form: self form.
- newSpline
- displayOn: aDisplayMedium
- at: 0 @ 0
- clippingBox: clipRect
- rule: anInteger
- fillColor: aForm!