10. Computational geometry¶
10.1. Parametric curves¶
We work with points
and think them as elements of an Euclidean space \({\mathbb E}^2\) which has a metric \(d({\bf v}_1,{\bf v}_2)=\vert \vert {\bf v}_1-{\bf v}_2 \vert \vert\).
A curve \({\bf C}\) is represented in parametric form when the coordinates of each of its points are expressed separately as a function of a third variable \(u\) called parameter,
where \(u \in [a,b]\). Finally, many of such curves don’t admit a functional representation.
10.1.1. Neile parabola¶
Described in [Pei75], the Neil parabola \({\bf C}(u)=(u^2, u^3)\), where \(u \in [-2,2]\), has the graphical representation
produced by the message
"RSTParametricXYLines, protocol lines"
lineParametricNeil
^ RSParametricXYLine new
parameterization: (RSLinspaceParameterization new
from: -2 to: 2 samples: 100;
yourself);
x: [ :t | t raisedTo: 2 ] y: [ :t | t raisedTo: 3 ];
scale: 10
A little variation to the second component \({\bf C}(u)=(u^2, u^3-u)\), where \(u \in [-2,2]\), has the graphical representation
produced by the message
"RSTParametricXYLines, protocol lines"
lineParametricNeil2
^ RSParametricXYLine new
parameterization: (RSLinspaceParameterization new
from: -2 to: 2 samples: 100;
yourself);
x: [ :t | t raisedTo: 2 ] y: [ :t | (t raisedTo: 3) - t ];
scale: 10
Now consider the curve \({\bf C}(u)=(cos(u), sin(u))\) where \(u \in [0,2\pi]\) has the graphical
and is coded as
"RSTParametricXYLines, protocol lines"
lineParametricUnitCircle
^ RSParametricXYLine new
parameterization: (RSLinspaceParameterization new
from: 0 to: Float pi * 2 samples: 100;
yourself);
x: [ :t | t cos ] y: [ :t | t sin ];
scale: 100
Another trigonometric curve \({\bf C}(u)=(cos(3u) cos(u), sin(u) cos(3u))\) where \(\ u \in [0,\pi]\), aka trochoid, has the graphical
and is coded as
"RSTParametricXYLines, protocol lines"
lineParametricTrochoid
^ RSParametricXYLine new
parameterization: (RSLinspaceParameterization new
from: 0 to: Float pi samples: 100;
yourself);
x: [ :t | t cos * (3 * t) cos ] y: [ :t | t sin * (3 * t) cos ];
scale: 100
Another trigonometric curve \({\bf C}(u)=(cos(3u) cos(u), sin(u) cos(3u))\) where \(\ u \in [0,\pi]\), aka trochoid, has the graphical
and is coded as
"RSTParametricXYLines, protocol lines"
lineParametricLissajous
^ RSParametricXYLine new
parameterization: (RSLinspaceParameterization new
from: 0 to: Float pi * 2 samples: 1000;
yourself);
x: [ :t | (3 * t) cos ] y: [ :t | (2 * t) sin ];
scale: 100
Another trigonometric curve \({\bf C}(u)=(cos(3u) cos(u), sin(u) cos(3u))\) where \(\ u \in [0,\pi]\), aka trochoid, has the graphical
and is coded as
"RSTParametricXYLines, protocol lines"
lineParametricHypotrochoid
| s r d a b |
s := 5.
r := 3.
d := 5.
a := s - r.
b := a / r.
^ RSParametricXYLine new
parameterization: (RSLinspaceParameterization new
from: -10 to: 10 samples: 10000;
yourself);
x: [ :t | a * t cos + (d * (b * t) cos) ]
y: [ :t | a * t sin - (d * (b * t) sin) ];
scale: 10
10.1.2. Butterfly curve¶
Introduced in [Fay89], the butterfly curve \({\bf C}(u)\) where \(\ u \in [0, 12\pi]\), has the graphical
and is coded as
"RSTParametricXYLines, protocol lines"
parametricXYlineButterfly
^ RSParametricXYLine new
parameterization: (RSLinspaceParameterization new
from: 0 to: Float pi * 12 samples: 10000;
yourself);
x: [ :t |
t sin
* (t cos exp - (2 * (4 * t) cos) - ((t / 12) sin raisedTo: 5)) ]
y: [ :t |
t cos
* (t cos exp - (2 * (4 * t) cos) - ((t / 12) sin raisedTo: 5)) ];
scale: 30
according to [Wika].
10.2. Bezier curves¶
10.2.1. Baricentric coordinates and affine transforms¶
Given two points \({\bf v}_1\) and \({\bf v}_2\), let
where \(w_1\in[0,1]\) and \(w_2=1-w_1\) are the baricentric coordinates of \({\bf v}\) with respect to \({\bf v}_1\) and \({\bf v}_2\), respectively. The message
"Point, protocol *Containers-Essentials"
unitAffine: aPoint at: aParam
| t |
t := aParam min: 1 max: 0.
^ self * t + (1 - t * aPoint)
implements such combination. For the sake of clarity, the shapes
shows the baricentric coordinates \({{1}\over{4}}\) and \({{3}\over{4}}\) of the point \((250, 325)\) with respect to \((100, 100)\) and \((300, 400)\), as the test
"RSParametricCurveTest, protocol systems under tests"
sutBaricentricCoordinates: aBlock
| aPoint anotherPoint param baricentricPoint |
aPoint := 100 @ 100.
anotherPoint := 300 @ 400.
param := 1 / 4.
baricentricPoint := aPoint unitAffine: anotherPoint at: param.
self assert: baricentricPoint equals: 250 @ 325.
^ aBlock
value: {
aPoint.
anotherPoint.
baricentricPoint }
value: param
ensures. We can do one more step, given three points \({\bf v}_1\), \({\bf v}_2\) and \({\bf v}_3\), let
where \(w_1, w_2\in[0,1]\) and \(w_3=1-w_1-w_2\) are the baricentric coordinates of \({\bf v}\) with respect to \({\bf v}_1\), \({\bf v}_2\) and \({\bf v}_3\), respectively. The message
"Point, protocol *Containers-Essentials"
unitAffine: aPoint at: aParam and: anotherPoint at: anotherParam
| t s |
t := aParam min: 1 max: 0.
s := anotherParam min: 1 max: 0.
^ self * t + (aPoint * s) + (1 - t - s * anotherPoint)
implements such combination. For the sake of clarity, the shapes
shows the baricentric coordinates \({{1}\over{6}}\), \({{1}\over{2}}\) and \({{1}\over{3}}\) of the point \(\left({{400}\over{3}}, 300\right)\) with respect to \((100, 100)\), \((300, 400)\) and \((-100, 250)\), as the test
"RSParametricCurveTest, protocol systems under tests"
sutBaricentricCoordinatesTriangle: aBlock
| aPoint anotherPoint param baricentricPoint yetAnotherPoint anotherParam |
aPoint := 100 @ 100.
anotherPoint := 300 @ 400.
yetAnotherPoint := -100 @ 250.
param := 1 / 6.
anotherParam := 1 / 2.
baricentricPoint := aPoint
unitAffine: anotherPoint
at: param
and: yetAnotherPoint
at: anotherParam.
self assert: baricentricPoint equals: 400 / 3 @ 300.
^ aBlock
value: {
aPoint.
anotherPoint.
yetAnotherPoint.
baricentricPoint }
value: param
value: anotherParam
ensures. Finally, a function \(\Phi: {\mathbb E}^2\rightarrow {\mathbb E}^2\) is an affine transformation if it lefts baricentric combinations untouched; for the sake of clarity, given \({\bf v}=\sum_{i=1}^n w_i {\bf v}_i\) and \(\sum_{i=1}^n w_i=1\) then \(\Phi\) is affine if and only if
10.2.2. Closed control net¶
and is coded as
"RSBasicShapeExamples, protocol lines"
lineDeCasteljauLineClosedControlPoints
| points |
points := {
(1 @ 1).
(3 @ 4).
(5 @ 6).
(7 @ 8).
(10 @ 2).
(1 @ 1) }.
^ RSdeCasteljauLine new
samplesLinspace: 100;
controlPoints: points;
scale: 100
10.2.3. Degree elevation¶
and is coded as
"RSBasicShapeExamples, protocol lines"
linesDeCasteljauLineDegreeElevation
| points bspline1 bspline2 bspline3 bspline4 |
points := {
(1 @ 1).
(3 @ 4).
(5 @ 6).
(7 @ (3 / 2)).
(10 @ 2) }.
bspline1 := RSdeCasteljauLine new
controlPoints: points;
scale: 100.
bspline2 := bspline1 increment.
bspline3 := bspline2 increment.
bspline4 := bspline3 increment.
^ RSGroup
with: bspline1
with: bspline2
with: bspline3
with: bspline4
10.2.4. Designing notes¶
and is coded as
"RSBasicShapeExamples, protocol lines"
lineDeCasteljauLineNoteBox
^ RSdeCasteljauLine new
samplesLinspace: 10;
controlPoints: {
(0 @ 0).
(8.461 @ 36.411).
(0.6 @ 129.887).
(25.3 @ 195.304).
(-67.3 @ 222.719).
(16.72 @ 245.576).
(-55.8 @ 178.406).
(60 @ 136.3).
(136 @ 136).
(142.2 @ 222.332).
(393.292 @ 192.739).
(247.8 @ 244.8).
(179.5 @ 201.105).
(221.9 @ 163.04).
(200 @ 125.8).
(204.4 @ 101.697).
(210.405 @ 85.124).
(217.89 @ 18.03).
(151.73 @ 29.54).
(244.5 @ -26.58).
(318.633 @ -42.131).
(145.27 @ 1.9).
(52.05 @ 8.718).
(0 @ 0) };
yourself
and is coded as
"RSBasicShapeExamples, protocol lines"
noteLoremIpsum
^ RSLabel new
text: (String loremIpsum: 50);
useDefaultCodeFont;
padded: Float goldenPlatinumRatio
withNoteDo: [ :aBox | aBox color: Color yellow translucent ]
and is coded as
"RSBasicShapeExamples, protocol lines"
noteInteger
^ RSLabel new
model: 541;
useDefaultCodeFont;
notedWithPad: Float goldenPlatinumRatio