Created
January 30, 2020 06:39
-
-
Save abhilashak/59a1cb54913a6b4f91f2e51b1c544766 to your computer and use it in GitHub Desktop.
Gimp Arrow Function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Berengar W. Lehr ([email protected]) | |
; Medical Physics Group, Department of Diagnostic and Interventional Radiology | |
; Jena University Hospital, 07743 Jena, Thueringen, Germany | |
; | |
; This program 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 2 of the License, or | |
; (at your option) any later version. | |
; | |
; This program 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. | |
; | |
; If you use this script and/or like it the author would be happy to | |
; receive a postcard from you: | |
; | |
; You should have received a copy of the GNU General Public License | |
; along with this program; if not, write to the Free Software | |
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
; | |
; Versionhistory: | |
; 11/10/2009 first release | |
; 11/15/2009 Added fixed brush width and double headed error, removed bug 1) one-point-paths, 2) horizontal paths | |
; 11/16/2009 Fixed image type restriction string | |
; 11/19/2009 Added feature for absolute wing length, fixed handling gray-scale images | |
; 25/01/2010 Fixed fixed opacity bug (thanks to Richard) | |
(define pi (* 4 (atan 1.0))) | |
(define | |
(script-fu-help-1Arrow | |
inPointToX | |
inPointToY | |
inPointFromX | |
inPointFromY | |
theWingLength | |
WingAngle | |
drawable | |
image | |
FullHead | |
MiddlePoint | |
) | |
(let* | |
( | |
; calculate absolute angle of both wings in image from relative angle | |
; between wings and arrow-tail and absolut angle of arrow-tail | |
(theArrowAngle (if (= (- inPointToY inPointFromY) 0) | |
(/ pi (if (< (- inPointToX inPointFromX) 0) 2 -2)) | |
(+ (atan (/ (- inPointToX inPointFromX) (- inPointToY inPointFromY))) (if (> inPointToY inPointFromY) pi 0)) | |
)) | |
(theLeftAngle (+ theArrowAngle WingAngle)) | |
(theRightAngle (- theArrowAngle WingAngle)) | |
; calculate end points of both wings | |
(theLeftWingEndPointX (+ inPointToX (* theWingLength (sin theLeftAngle)))) | |
(theLeftWingEndPointY (+ inPointToY (* theWingLength (cos theLeftAngle)))) | |
(theRightWingEndPointX (+ inPointToX (* theWingLength (sin theRightAngle)))) | |
(theRightWingEndPointY (+ inPointToY (* theWingLength (cos theRightAngle)))) | |
(points (cons-array 4 'double)) | |
(theMiddleWingEndPointX 0) (theMiddleWingEndPointY 0) | |
(PreviousOpacity 100.0) | |
) | |
(begin | |
(set! PreviousOpacity (car (gimp-context-get-opacity))) | |
(gimp-context-set-opacity 100.0) | |
; collect points for arrow-tail and draw them | |
(aset points 0 inPointToX) (aset points 1 inPointToY) | |
(aset points 2 inPointFromX) (aset points 3 inPointFromY) | |
(gimp-paintbrush-default drawable 4 points) (set! points (cons-array 4 'double)) | |
; accordingly for left wing | |
(aset points 0 inPointToX) (aset points 1 inPointToY) | |
(aset points 2 theLeftWingEndPointX) (aset points 3 theLeftWingEndPointY) | |
(gimp-paintbrush-default drawable 4 points) (set! points (cons-array 4 'double)) | |
; accordingly for right wing | |
(aset points 0 inPointToX) (aset points 1 inPointToY) | |
(aset points 2 theRightWingEndPointX) (aset points 3 theRightWingEndPointY) | |
(gimp-paintbrush-default drawable 4 points) | |
; only if head is to be filled | |
(if (= FullHead 1) (begin | |
; calculate intersection of connection between the wings end points and arrow tail | |
; shrink distance between this point and arrow head if MiddlePoint < 100 | |
(set! theMiddleWingEndPointX (+ inPointToX | |
(* (/ MiddlePoint 100) (- (/ (+ theLeftWingEndPointX theRightWingEndPointX) 2) inPointToX)) | |
)) | |
(set! theMiddleWingEndPointY (+ inPointToY | |
(* (/ MiddlePoint 100) (- (/ (+ theLeftWingEndPointY theRightWingEndPointY) 2) inPointToY)) | |
)) | |
; collect points for left wing end - intersection - right wing end & draw it | |
(set! points (cons-array 6 'double)) | |
(aset points 0 theLeftWingEndPointX) (aset points 1 theLeftWingEndPointY) | |
(aset points 2 theMiddleWingEndPointX) (aset points 3 theMiddleWingEndPointY) | |
(aset points 4 theRightWingEndPointX) (aset points 5 theRightWingEndPointY) | |
(gimp-paintbrush-default drawable 6 points) | |
; collect points to create selection which will be filled with FG color | |
(set! points (cons-array 8 'double)) | |
(aset points 0 inPointToX) (aset points 1 inPointToY) | |
(aset points 2 theLeftWingEndPointX) (aset points 3 theLeftWingEndPointY) | |
(aset points 4 theMiddleWingEndPointX) (aset points 5 theMiddleWingEndPointY) | |
(aset points 6 theRightWingEndPointX) (aset points 7 theRightWingEndPointY) | |
(gimp-free-select image 8 points CHANNEL-OP-REPLACE TRUE FALSE 0) | |
(gimp-edit-bucket-fill drawable FG-BUCKET-FILL NORMAL-MODE 100 0 FALSE 0 0) | |
(gimp-selection-none image) | |
)) | |
(gimp-context-set-opacity PreviousOpacity) | |
) ; begin | |
) ; let | |
) ; define | |
(define | |
(script-fu-draw-arrow | |
image drawable | |
WingLengthRatio | |
WingAngle | |
FullHead | |
MiddlePoint | |
BrushThicknessOrRatio | |
; LineThicknessRatio | |
; BrushThickness | |
useFirstPointArrowAsHead | |
usePathThenRemove | |
useNewLayer | |
useDoubleHeadArrow | |
useless | |
) | |
(let* | |
( | |
(theActiveVector (car (gimp-image-get-active-vectors image))) | |
(theFirstStroke 0) (theStrokePoints 0) | |
(theNumPoints 0) | |
(inPoint_1X 0) (inPoint_1Y 0) | |
(inPoint_2X 0) (inPoint_2Y 0) | |
(theArrowLength 0) (theWingLength 0) | |
(oldLayer (car (gimp-image-get-active-layer image))) | |
(brushName "arrowBrush") | |
(oldBrushName (car (gimp-context-get-brush))) | |
) | |
(if (not (= theActiveVector -1)) (begin | |
(gimp-image-undo-group-start image) | |
; create new layer if asked to do so | |
(if (= useNewLayer 1) (begin | |
(set! drawable (car (gimp-layer-new image (car (gimp-image-width image)) | |
(car (gimp-image-height image)) | |
(+ 1 (* 2 (car (gimp-image-base-type image)))) | |
"Arrow" 100 NORMAL-MODE ))) | |
(gimp-image-add-layer image drawable 0) | |
; set new layer completely transparent | |
(gimp-layer-add-mask drawable (car (gimp-layer-create-mask drawable ADD-BLACK-MASK))) | |
(gimp-layer-remove-mask drawable MASK-APPLY) | |
)) | |
; get path/vector points | |
(set! theFirstStroke (aref (cadr (gimp-vectors-get-strokes theActiveVector)) 0)) | |
(set! theStrokePoints (caddr (gimp-vectors-stroke-get-points theActiveVector theFirstStroke))) | |
(set! theNumPoints (cadr (gimp-vectors-stroke-get-points theActiveVector theFirstStroke))) | |
; get position of arrow head and arrow tail from active vector | |
(set! inPoint_1X (aref theStrokePoints 2)) | |
(set! inPoint_1Y (aref theStrokePoints 3)) | |
(set! inPoint_2X (aref theStrokePoints (- theNumPoints 4))) | |
(set! inPoint_2Y (aref theStrokePoints (- theNumPoints 3))) | |
; calculate length of arrows depending on the length of the whole arrow | |
(define (sqr x) (* x x)) | |
(set! theArrowLength (exp (* 0.5 (log (+ (sqr (- inPoint_1X inPoint_2X)) (sqr (- inPoint_1Y inPoint_2Y))))))) | |
(if (< WingLengthRatio 0) | |
(set! theWingLength (* theArrowLength (/ -1 WingLengthRatio))) | |
(set! theWingLength WingLengthRatio) | |
) | |
; define new brush for drawing operation | |
(gimp-brush-new brushName) | |
(gimp-brush-set-shape brushName BRUSH-GENERATED-CIRCLE) (gimp-brush-set-spikes brushName 2) | |
(gimp-brush-set-hardness brushName 1.00) (gimp-brush-set-aspect-ratio brushName 1.0) | |
(gimp-brush-set-angle brushName 0.0) (gimp-brush-set-spacing brushName 1.0) | |
; set radius of brush according to length of arrow | |
(if (< BrushThicknessOrRatio 0) | |
(gimp-brush-set-radius brushName (/ theArrowLength (* BrushThicknessOrRatio -1))) | |
(gimp-brush-set-radius brushName BrushThicknessOrRatio) | |
) | |
(gimp-context-set-brush brushName) | |
(if (or (= useFirstPointArrowAsHead 1) (= useDoubleHeadArrow 1)) | |
(script-fu-help-1Arrow inPoint_1X inPoint_1Y inPoint_2X inPoint_2Y theWingLength (* (/ WingAngle 180) pi) drawable image FullHead MiddlePoint)) | |
(if (or (= useFirstPointArrowAsHead 0) (= useDoubleHeadArrow 1)) | |
(script-fu-help-1Arrow inPoint_2X inPoint_2Y inPoint_1X inPoint_1Y theWingLength (* (/ WingAngle 180) pi) drawable image FullHead MiddlePoint)) | |
(gimp-context-set-brush oldBrushName) | |
(gimp-brush-delete brushName) | |
(if (= usePathThenRemove 1) (gimp-image-remove-vectors image theActiveVector)) | |
(if (= useNewLayer 1) (begin | |
(plug-in-autocrop-layer TRUE image drawable) | |
(gimp-image-set-active-layer image oldLayer) | |
)) | |
(gimp-displays-flush) | |
(gimp-image-undo-group-end image) | |
)(gimp-message "This script needs a path with two points\nto position the arrow head and tail (first and last point of path is used)")) | |
) ; let* | |
); define | |
; Register the function with GIMP: | |
(script-fu-register "script-fu-draw-arrow" | |
_"_Arrow..." | |
_"Draw a nearly arbitrary arrow in your image" | |
"Berengar W. Lehr <[email protected]>" | |
"2009, Berengar W. Lehr / MPG@IDIR, UH Jena, Germany." | |
"19th November 2009" | |
"*" | |
SF-IMAGE "The image" 0 | |
SF-DRAWABLE "The drawable" 0 | |
SF-ADJUSTMENT "Length of wings (LoW = AL/X) *" '(-2.5 -100 500 10 1 1 1) | |
SF-ADJUSTMENT "Angle between arrow and wing in degree" '(25 5 85 5 15 0 0) | |
SF-TOGGLE "Fill head of arrow?" TRUE | |
SF-ADJUSTMENT "Percentage size of notch of arrow head\n(only valid if head of arrow is filled)" '(75 0 100 1 10 0 1) | |
SF-ADJUSTMENT "Brush Thickness* (BS = AL/X)" '(-25 -500 500 1 10 0 1) | |
SF-TOGGLE "Use first path point as arrow head?\n(if not the last path point of is used as arrow head)" TRUE | |
SF-TOGGLE "Delete path after arrow was drawn?" FALSE | |
SF-TOGGLE "Use new layer for arrow?" TRUE | |
SF-TOGGLE "Draw double headed arrow?" FALSE | |
SF-TOGGLE "*) Positive values stand for absolute pixel size,\nnegative for values relative to arrow length\n(the value of this checkbox is ignored)" FALSE | |
) | |
(script-fu-menu-register "script-fu-draw-arrow" "<Image>/Tools/") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment