/** This file is part of Shapes. ** ** Shapes is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** any later version. ** ** Shapes is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Shapes. If not, see . ** ** Copyright 2009, 2014, 2015 Henrik Tidefelt **/ /** This examples shows how to compute the integral of argument variation for an open path, based on ** the kernel function that computes winding numbers for closed paths. **/ ##lookin ..Shapes ##lookin ..Shapes..Geometry /** This function implements the integral of argument variation. ** It constructs a closed path by adding a counter-clockwise segment, gets its winding number, and compensates for the closing segment. ** The closing segment is computed as four straight line segments, at the biggest of the radii of the original path's endpoints. **/ argumentVariation: \ pth origin → [if pth.closed? 360° * [Geometry..winding pth origin] { pth0: [[shift ~origin] pth] dStart: pth0.end.p dEnd: pth0.begin.p aStart: [angle dStart] aEnd: { tmp: [angle dEnd] [if tmp ≥ aStart tmp tmp+360°] } aStep: (aEnd - aStart) / 4 d: [Numeric..Math..max [Numeric..Math..abs dStart] [Numeric..Math..abs dEnd]] * [normalized dStart] 360° * [Geometry..winding [[Data..range '1 '3].foldl \ p e → (p--[[rotate e*aStep] d]) pth0]--cycle (0m,0m)] - ( aEnd - aStart ) }] /** Just for illustration, the path used to compute the winding number is extracted from the function body above. **/ closedPath: \ pth origin → { dStart: pth.end.p - origin dEnd: pth.begin.p - origin aStart: [angle dStart] aEnd: { tmp: [angle dEnd] [if tmp ≥ aStart tmp tmp+360°] } aStep: (aEnd - aStart) / 4 d: [Numeric..Math..max [Numeric..Math..abs dStart] [Numeric..Math..abs dEnd]] * [normalized dStart] [[shift origin] [[Data..range '1 '3].foldl \ p e → (p--[[rotate e*aStep] d]) [[shift ~origin] pth]]--cycle] } /** This helper function makes an illustration for a single path. ** 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. **/ helper: \ pth → ( Graphics..newGroup << Traits..@stroking:Traits..RGB..RED | [Graphics..stroke [Geometry..circle 1mm]] << Traits..@dash:[Traits..dashpattern 2bp 2bp] | [Graphics..stroke [closedPath pth (0m,0m)]] << [Graphics..stroke pth head:[Graphics..ShapesArrow width:10 ...]] << [[shift (0cm,~1cm)] (Text..newText << [String..sprintf `%.1f°´ [argumentVariation pth (0m,0m)]/1°])]) /** All examples will be constructed as simple variations of this path. **/ 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) /** Finally, apply the helper on some paths. **/ IO..•page << [helper pth] << [helper [Geometry..reverse pth]] >> [shift (7cm,0cm)] << [helper [[shift (~1.5cm,~1cm)] pth]] >> [shift (0cm,~7cm)] << [helper [Geometry..reverse [[shift (~1.5cm,~1cm)] pth]]] >> [shift (7cm,~7cm)]