PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/src/arc.sc

https://bitbucket.org/bunny351/ezd
Scala | 316 lines | 289 code | 27 blank | 0 comment | 5 complexity | c05c1fb6300fb2e102ece11108b5b787 MD5 | raw file
  1. ;;; ezd - easy drawing for X11 displays.
  2. ;;;
  3. ;;; The procedures in this module generate the GRAPHIC objects representing
  4. ;;; arcs.
  5. ;* Copyright 1990-1993 Digital Equipment Corporation
  6. ;* All Rights Reserved
  7. ;*
  8. ;* Permission to use, copy, and modify this software and its documentation is
  9. ;* hereby granted only under the following terms and conditions. Both the
  10. ;* above copyright notice and this permission notice must appear in all copies
  11. ;* of the software, derivative works or modified versions, and any portions
  12. ;* thereof, and both notices must appear in supporting documentation.
  13. ;*
  14. ;* Users of this software agree to the terms and conditions set forth herein,
  15. ;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
  16. ;* right and license under any changes, enhancements or extensions made to the
  17. ;* core functions of the software, including but not limited to those affording
  18. ;* compatibility with other hardware or software environments, but excluding
  19. ;* applications which incorporate this software. Users further agree to use
  20. ;* their best efforts to return to Digital any such changes, enhancements or
  21. ;* extensions that they make and inform Digital of noteworthy uses of this
  22. ;* software. Correspondence should be provided to Digital at:
  23. ;*
  24. ;* Director of Licensing
  25. ;* Western Research Laboratory
  26. ;* Digital Equipment Corporation
  27. ;* 250 University Avenue
  28. ;* Palo Alto, California 94301
  29. ;*
  30. ;* This software may be distributed (but not offered for sale or transferred
  31. ;* for compensation) to third parties, provided such third parties agree to
  32. ;* abide by the terms and conditions of this notice.
  33. ;*
  34. ;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  35. ;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  36. ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  37. ;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  38. ;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  39. ;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  40. ;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  41. ;* SOFTWARE.
  42. (module arc)
  43. (include "struct.sch")
  44. (include "commands.sch")
  45. (include "ginfo.sch")
  46. (include "display.sch")
  47. (include "view.sch")
  48. (include "psdraw.sch")
  49. (include "drawing.sch")
  50. (include "graphic.sch")
  51. (include "xternal.sch")
  52. ;;; Drawing arcs in Postscript may require the saving and restoration of the
  53. ;;; current transformation. This is done by the following procedures.
  54. (define (ARC-IN scale-y)
  55. (if (= scale-y 1)
  56. "newpath"
  57. `("newpath" "matrix" "currentmatrix" 1 ,scale-y "scale")))
  58. (define (ARC-OUT scale-y)
  59. (if (= scale-y 1) "" "setmatrix"))
  60. ;;; Any of the types of arcs are drawn in X by the following procedure.
  61. (define (XDRAW-ANY-ARC todraw gc x y width height angle1 angle2)
  62. (let ((ux1 (user->x x))
  63. (ux2 (user->x (+ x width)))
  64. (uy1 (user->y y))
  65. (uy2 (user->y (+ y height)))
  66. (a1 angle1)
  67. (a2 angle2))
  68. (if (<= ux1 ux2)
  69. (if (<= uy1 uy2)
  70. (begin (set! a1 (- a1))
  71. (set! a2 (- a2)))
  72. #f)
  73. (if (<= uy1 uy2)
  74. (set! a1 (+ a1 180))
  75. (begin (set! a1 (- 180 a1))
  76. (set! a2 (- a2)))))
  77. (todraw *dpy* *xwindow* gc (min ux1 ux2) (min uy1 uy2)
  78. (user->width width) (user->height height)
  79. (* 64 a1) (* 64 a2))))
  80. ;;; An arc is created by the following procedure.
  81. (define (ARC x y width height angle1 angle2 line-width color dash)
  82. (make-graphic
  83. #f
  84. (lambda ()
  85. (let ((ux1 (user->x x))
  86. (ux2 (user->x (+ x width)))
  87. (uy1 (user->y y))
  88. (uy2 (user->y (+ y height)))
  89. (lwdiv2 (quotient (user->lw line-width) 2)))
  90. (list (- (min ux1 ux2) lwdiv2)
  91. (- (min uy1 uy2) lwdiv2)
  92. (+ (max ux1 ux2) lwdiv2 1)
  93. (+ (max uy1 uy2) lwdiv2 1))))
  94. (if (eq? color 'clear)
  95. draw-clear
  96. (lambda ()
  97. (xdraw-any-arc xdrawarc
  98. (cv-gc (user->lw line-width) color #f dash #f #f)
  99. x y width height angle1 angle2)))
  100. (if (eq? color 'clear)
  101. draw-clear
  102. (lambda ()
  103. (let ((scale-y (/ height width))
  104. (correct-y (/ width height)))
  105. (pscolor color)
  106. (pscommand (arc-in scale-y)
  107. (+ x (/ width 2))
  108. (* (+ y (/ height 2)) correct-y)
  109. (/ width 2) angle1 (+ angle1 angle2) "arc"
  110. (arc-out scale-y))
  111. (psstroke (user->lw line-width) dash))))
  112. (lambda (minx miny maxx maxy)
  113. (let* ((lwdiv2 (quotient (user->lw line-width) 2))
  114. (dx (width->user (max lwdiv2 2)))
  115. (dy (height->user (max lwdiv2 2)))
  116. (fx (- maxx minx))
  117. (fy (- maxy miny)))
  118. (and (in-arc-angle? minx miny maxx maxy x y
  119. width height angle1 angle2)
  120. (in-radius? minx miny maxx maxy (- x dx) (- y dy)
  121. (+ width dx dx) (+ height dy dy))
  122. (not (in-radius? minx miny maxx maxy
  123. (+ x dx fx) (+ y dy fy)
  124. (- width dx dx fx fx)
  125. (- height dy dy fy fy))))))))
  126. (define-ezd-command
  127. `(arc ,number? ,number? ,non-negative? ,non-negative? ,non-negative?
  128. ,non-negative? (optional ,non-negative?) (optional ,color?)
  129. (optional ,dash?))
  130. "(arc x y width height angle1 angle2 [<line width>] [<color>] [dash])"
  131. arc)
  132. ;;; An filled-arc is created by the following procedure.
  133. (define (FILL-ARC x y width height angle1 angle2 color stipple)
  134. (make-graphic
  135. #f
  136. (lambda ()
  137. (let ((ux1 (user->x x))
  138. (ux2 (user->x (+ x width 1)))
  139. (uy1 (user->y y))
  140. (uy2 (user->y (+ y height 1))))
  141. (list (min ux1 ux2) (min uy1 uy2) (max ux1 ux2)
  142. (max uy1 uy2))))
  143. (if (eq? color 'clear)
  144. draw-clear
  145. (lambda ()
  146. (xdraw-any-arc xfillarc
  147. (cv-gc #f color stipple #f #f arcchord)
  148. x y width height angle1 angle2)))
  149. (if (eq? color 'clear)
  150. draw-clear
  151. (lambda ()
  152. (let ((scale-y (/ height width))
  153. (correct-y (/ width height)))
  154. (pscolor color)
  155. (pscommand (arc-in scale-y)
  156. (+ x (/ width 2))
  157. (* (+ y (/ height 2)) correct-y)
  158. (/ width 2) angle1 (+ angle1 angle2) "arc"
  159. "closepath" "fill" (arc-out scale-y)))))
  160. (lambda (minx miny maxx maxy)
  161. (let ((aok (in-arc-angle? minx miny maxx maxy x y width height
  162. angle1 angle2))
  163. (rok (in-radius? minx miny maxx maxy x y width height)))
  164. (or (and (< angle2 180) aok rok
  165. (in-segment? minx miny maxx maxy x y
  166. width height angle1 angle2))
  167. (and (<= 180 angle2 360) aok rok)
  168. (and (< 180 angle2 360) (not aok) rok
  169. (not (in-segment? minx miny maxx maxy x y width
  170. height (+ angle1 angle2)
  171. (- 360 angle2))))
  172. (and (>= angle2 360) rok))))))
  173. (define-ezd-command
  174. `(fill-arc ,number? ,number? ,non-negative? ,non-negative? ,number?
  175. ,number? (optional ,color?) (optional ,stipple?))
  176. "(fill-arc x y width height angle1 angle2 [<color>] [<stipple>])"
  177. fill-arc)
  178. ;;; An pie-slice-arc is created by the following procedure.
  179. (define (PIE-ARC x y width height angle1 angle2 color stipple)
  180. (make-graphic
  181. #f
  182. (lambda ()
  183. (let ((ux1 (user->x x))
  184. (ux2 (user->x (+ x width 1)))
  185. (uy1 (user->y y))
  186. (uy2 (user->y (+ y height 1))))
  187. (list (min ux1 ux2) (min uy1 uy2) (max ux1 ux2)
  188. (max uy1 uy2))))
  189. (if (eq? color 'clear)
  190. draw-clear
  191. (lambda ()
  192. (xdraw-any-arc xfillarc
  193. (cv-gc #f color stipple #f #f arcpieslice)
  194. x y width height angle1 angle2)))
  195. (if (eq? color 'clear)
  196. draw-clear
  197. (lambda ()
  198. (let ((scale-y (/ height width))
  199. (correct-y (/ width height)))
  200. (pscolor color)
  201. (pscommand (arc-in scale-y)
  202. (+ x (/ width 2))
  203. (* (+ y (/ height 2)) correct-y)
  204. "moveto"
  205. (+ x (/ width 2))
  206. (* (+ y (/ height 2)) correct-y)
  207. (/ width 2)
  208. angle1 (+ angle1 angle2) "arc" "closepath"
  209. "fill" (arc-out scale-y)))))
  210. (lambda (minx miny maxx maxy)
  211. (and (in-arc-angle? minx miny maxx maxy x y width height
  212. angle1 angle2)
  213. (in-radius? minx miny maxx maxy x y width height)))))
  214. (define-ezd-command
  215. `(pie-arc ,number? ,number? ,non-negative? ,non-negative?
  216. ,number? ,number? (optional ,color?) (optional ,stipple?))
  217. "(pie-arc x y width height angle1 angle2 [<color>] [<stipple>])"
  218. pie-arc)
  219. ;;; Intersection computation is done by the following procedures. The first
  220. ;;; is a boolean that decides whether or not the bounding box is within the
  221. ;;; angle of the arc.
  222. (define (IN-ARC-ANGLE? minx miny maxx maxy x y width height angle1 angle2)
  223. (let ((cx (+ x (/ width 2)))
  224. (cy (+ y (/ height 2))))
  225. (define (IN? x y)
  226. (let ((correct (if (< x cx)
  227. 180
  228. (if (< y cy)
  229. 360
  230. 0)))
  231. (alpha (if (= x cx)
  232. 90
  233. (* (/ 180 3.14159 )
  234. (atan (/ (- y cy) (- x cx)))))))
  235. (if (> (+ angle1 angle2) 360)
  236. (not (< (- (+ angle1 angle2) 360) (+ correct alpha)
  237. angle1))
  238. (<= angle1 (+ correct alpha) (+ angle1 angle2)))))
  239. (or (in? minx miny) (in? minx maxy) (in? maxx miny) (in? maxx maxy)
  240. (in? (+ minx (/ (- maxx minx) 2)) (+ miny (/ (- maxy miny) 2))))))
  241. ;;; IN-RADIUS? determines whether or not the point is within radial distance
  242. ;;; of the center of the arc.
  243. (define (IN-RADIUS? minx miny maxx maxy x y width height)
  244. (let* ((h (+ x (/ width 2)))
  245. (k (+ y (/ height 2)))
  246. (a (/ width 2))
  247. (b (/ height 2)))
  248. (define (IN? x y)
  249. (<= (+ (/ (* (- x h) (- x h)) (* a a))
  250. (/ (* (- y k) (- y k)) (* b b)))
  251. 1))
  252. (or (in? minx miny) (in? minx maxy) (in? maxx miny) (in? maxx maxy)
  253. (in? (+ minx (/ (- maxx minx) 2))
  254. (+ miny (/ (- maxy miny) 2))))))
  255. ;;; IN-SEGMENT? determines for points within the arc, whether or not they are
  256. ;;; actually in the segment of the filled arc.
  257. ;;;
  258. ;;; xc, yc = center of arc
  259. ;;; x1, y1 = point at one end of the arc
  260. ;;; x2, y2 = point at the other end of the arc
  261. ;;; slope = slope of the line between x1,y1 and x2,y2
  262. ;;; y - yc = slope*(x - xc) line parallel to x1,y1 x2,y2 through xc,yc
  263. ;;; -slope*x + y + slope*xc-yc = 0 general form for the above
  264. (define (IN-SEGMENT? minx miny maxx maxy x y width height angle1 angle2)
  265. (let* ((w2 (/ width 2))
  266. (h2 (/ height 2))
  267. (radians1 (* angle1 (/ 3.14159 180)))
  268. (radians2 (* angle2 (/ 3.14159 180)))
  269. (xc (+ x w2))
  270. (yc (+ y h2))
  271. (x1 (+ xc (* (cos radians1) w2)))
  272. (y1 (+ yc (* (sin radians1) h2)))
  273. (x2 (+ xc (* (cos (+ radians1 radians2)) w2)))
  274. (y2 (+ yc (* (sin (+ radians1 radians2)) h2)))
  275. (slope (if (= x1 x2) #f (/ (- y2 y1) (- x2 x1))))
  276. (yp (lambda (x) (if slope (+ (* slope (- x xc)) yc) yc)))
  277. (distance (lambda (x y)
  278. (if slope
  279. (abs
  280. (/ (+ (* (- slope) x)
  281. y
  282. (- (* slope xc) yc))
  283. (sqrt (+ (* slope slope) 1))))
  284. (abs (- y yc)))))
  285. (d1 (distance x1 y1)))
  286. (or (< d1 (distance minx miny)) (< d1 (distance minx maxy))
  287. (< d1 (distance maxx miny)) (< d1 (distance maxx maxy))
  288. (< d1 (distance (+ minx (/ (- maxx minx) 2))
  289. (+ miny (/ (- maxy miny) 2)))))))