1 /** This file is part of Shapes.
3 ** Shapes is free software: you can redistribute it and/or modify
4 ** it under the terms of the GNU General Public License as published by
5 ** the Free Software Foundation, either version 3 of the License, or
8 ** Shapes is distributed in the hope that it will be useful,
9 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ** GNU General Public License for more details.
13 ** You should have received a copy of the GNU General Public License
14 ** along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 ** Copyright 2009, 2014, 2015 Henrik Tidefelt
19 /** This examples shows how to compute the integral of argument variation for an open path, based on
20 ** the kernel function that computes winding numbers for closed paths.
24 ##lookin ..Shapes..Geometry
26 /** This function implements the integral of argument variation.
27 ** It constructs a closed path by adding a counter-clockwise segment, gets its winding number, and compensates for the closing segment.
28 ** The closing segment is computed as four straight line segments, at the biggest of the radii of the original path's endpoints.
30 argumentVariation: \ pth origin →
32 360° * [Geometry..winding pth origin]
34 pth0: [[shift ~origin] pth]
37 aStart: [angle dStart]
38 aEnd: { tmp: [angle dEnd]
39 [if tmp ≥ aStart tmp tmp+360°] }
40 aStep: (aEnd - aStart) / 4
41 d: [Numeric..Math..max [Numeric..Math..abs dStart] [Numeric..Math..abs dEnd]] * [normalized dStart]
42 360° * [Geometry..winding [[Data..range '1 '3].foldl \ p e → (p--[[rotate e*aStep] d]) pth0]--cycle (0m,0m)] - ( aEnd - aStart )
45 /** Just for illustration, the path used to compute the winding number is extracted from the function body above.
47 closedPath: \ pth origin →
49 dStart: pth.end.p - origin
50 dEnd: pth.begin.p - origin
51 aStart: [angle dStart]
52 aEnd: { tmp: [angle dEnd]
53 [if tmp ≥ aStart tmp tmp+360°] }
54 aStep: (aEnd - aStart) / 4
55 d: [Numeric..Math..max [Numeric..Math..abs dStart] [Numeric..Math..abs dEnd]] * [normalized dStart]
57 [[Data..range '1 '3].foldl \ p e → (p--[[rotate e*aStep] d]) [[shift ~origin] pth]]--cycle]
60 /** This helper function makes an illustration for a single path.
61 ** It marks the origin, strokes the path, strokes the closed path for which the winding number is computed, and prints the argument variation near the origin.
65 << @stroking:Traits..RGB..RED | [Graphics..stroke [Geometry..circle 1mm]]
66 << @dash:[dashpattern 2bp 2bp] | [Graphics..stroke [closedPath pth (0m,0m)]]
67 << [Graphics..stroke pth head:[Graphics..ShapesArrow width:10 ...]]
68 << [[shift (0cm,~1cm)] (Text..newText << [String..sprintf `%.1f°´ [argumentVariation pth (0m,0m)]/1°])])
70 /** All examples will be constructed as simple variations of this path.
72 pth: (~1cm,~1cm)>(1%C^100°)--(1%C^)<(2cm,2cm)>(1%C^)--(1%C^)<(1cm,1cm)>(1%C^)--(1%C^)<(3cm,3cm)>(1%C^)--(1%C^45°)<(2cm,~2cm)
74 /** Finally, apply the helper on some paths.
76 IO..•page << [helper pth]
77 << [helper [Geometry..reverse pth]] >> [shift (7cm,0cm)]
78 << [helper [[shift (~1.5cm,~1cm)] pth]] >> [shift (0cm,~7cm)]
79 << [helper [Geometry..reverse [[shift (~1.5cm,~1cm)] pth]]] >> [shift (7cm,~7cm)]