Sutherland-Hodgman polygon clipping: Difference between revisions
Content added Content deleted
Line 4,085: | Line 4,085: | ||
} |
} |
||
}</syntaxhighlight> |
}</syntaxhighlight> |
||
=={{header|Scheme}}== |
|||
{{trans|ATS}} |
|||
<syntaxhighlight lang="scheme"> |
|||
;;; Sutherland-Hodgman polygon clipping. |
|||
(define (evaluate-line x1 y1 x2 y2 x) |
|||
;; Given the straight line between (x1,y1) and (x2,y2), evaluate it |
|||
;; at x. |
|||
(let ((dy (- y2 y1)) |
|||
(dx (- x2 x1))) |
|||
(let ((slope (/ dy dx)) |
|||
(intercept (/ (- (* dx y1) (* dy x1)) dx))) |
|||
(+ (* slope x) intercept)))) |
|||
(define (intersection-of-lines x1 y1 x2 y2 x3 y3 x4 y4) |
|||
;; Given the line between (x1,y1) and (x2,y2), and the line between |
|||
;; (x3,y3) and (x4,y4), find their intersection. |
|||
(cond ((= x1 x2) (list x1 (evaluate-line x3 y3 x4 y4 x1))) |
|||
((= x3 x4) (list x3 (evaluate-line x1 y1 x2 y2 x3))) |
|||
(else (let ((denominator (- (* (- x1 x2) (- y3 y4)) |
|||
(* (- y1 y2) (- x3 x4)))) |
|||
(x1*y2-y1*x2 (- (* x1 y2) (* y1 x2))) |
|||
(x3*y4-y3*x4 (- (* x3 y4) (* y3 x4)))) |
|||
(let ((xnumerator (- (* x1*y2-y1*x2 (- x3 x4)) |
|||
(* (- x1 x2) x3*y4-y3*x4))) |
|||
(ynumerator (- (* x1*y2-y1*x2 (- y3 y4)) |
|||
(* (- y1 y2) x3*y4-y3*x4)))) |
|||
(list (/ xnumerator denominator) |
|||
(/ ynumerator denominator))))))) |
|||
(define (intersection-of-edges e1 e2) |
|||
;; |
|||
;; A point is a list of two coordinates, and an edge is a list of |
|||
;; two points. |
|||
;; |
|||
;; I am not using any SRFI-9 records, or the like, that define |
|||
;; actual new types, although I would do so if writing a more |
|||
;; serious implementation. Also, I am not using any pattern matcher. |
|||
;; A pattern matcher would make this code less tedious with |
|||
;; "cadaddaddr" notations. |
|||
(let ((point1 (car e1)) |
|||
(point2 (cadr e1)) |
|||
(point3 (car e2)) |
|||
(point4 (cadr e2))) |
|||
(let ((x1 (car point1)) |
|||
(y1 (cadr point1)) |
|||
(x2 (car point2)) |
|||
(y2 (cadr point2)) |
|||
(x3 (car point3)) |
|||
(y3 (cadr point3)) |
|||
(x4 (car point4)) |
|||
(y4 (cadr point4))) |
|||
(intersection-of-lines x1 y1 x2 y2 x3 y3 x4 y4)))) |
|||
(define (point-is-left-of-edge? pt edge) |
|||
(let ((x (car pt)) |
|||
(y (cadr pt)) |
|||
(x1 (caar edge)) |
|||
(y1 (cadar edge)) |
|||
(x2 (caadr edge)) |
|||
(y2 (cadadr edge))) |
|||
;; Outer product of the vectors (x1,y1)-->(x,y) and |
|||
;; (x1,y1)-->(x2,y2) |
|||
(negative? (- (* (- x x1) (- y2 y1)) |
|||
(* (- x2 x1) (- y y1)))))) |
|||
(define (clip-subject-edge subject-edge clip-edge accum) |
|||
(define left-of? point-is-left-of-edge?) |
|||
(define (intersection) |
|||
(intersection-of-edges subject-edge clip-edge)) |
|||
(let ((s1 (car subject-edge)) |
|||
(s2 (cadr subject-edge))) |
|||
(let ((s2-is-inside? (left-of? s2 clip-edge)) |
|||
(s1-is-inside? (left-of? s1 clip-edge))) |
|||
(if s2-is-inside? |
|||
(if s1-is-inside? |
|||
(cons s2 accum) |
|||
(cons s2 (cons (intersection) accum))) |
|||
(if s1-is-inside? |
|||
(cons (intersection) accum) |
|||
accum))))) |
|||
(define (for-each-subject-edge i subject-points clip-edge accum) |
|||
(define n (vector-length subject-points)) |
|||
(if (= i n) |
|||
(list->vector (reverse accum)) |
|||
(let ((s2 (vector-ref subject-points i)) |
|||
(s1 (vector-ref subject-points |
|||
(- (if (zero? i) n i) 1)))) |
|||
(let ((accum (clip-subject-edge (list s1 s2) |
|||
clip-edge accum))) |
|||
(for-each-subject-edge (+ i 1) subject-points |
|||
clip-edge accum))))) |
|||
(define (for-each-clip-edge i subject-points clip-points) |
|||
(define n (vector-length clip-points)) |
|||
(if (= i n) |
|||
subject-points |
|||
(let ((c2 (vector-ref clip-points i)) |
|||
(c1 (vector-ref clip-points (- (if (zero? i) n i) 1)))) |
|||
(let ((subject-points |
|||
(for-each-subject-edge 0 subject-points |
|||
(list c1 c2) '()))) |
|||
(for-each-clip-edge (+ i 1) subject-points clip-points))))) |
|||
(define (clip subject-points clip-points) |
|||
(for-each-clip-edge 0 subject-points clip-points)) |
|||
(define (write-eps outp subject-points clip-points result-points) |
|||
;; I use only some of the most basic output procedures. Schemes tend |
|||
;; to include more advanced means to write output, often resembling |
|||
;; those of Common Lisp. |
|||
(define (x pt) (exact->inexact (car pt))) |
|||
(define (y pt) (exact->inexact (cadr pt))) |
|||
(define (moveto pt) |
|||
(display (x pt) outp) |
|||
(display " " outp) |
|||
(display (y pt) outp) |
|||
(display " moveto" outp) |
|||
(newline outp)) |
|||
(define (lineto pt) |
|||
(display (x pt) outp) |
|||
(display " " outp) |
|||
(display (y pt) outp) |
|||
(display " lineto" outp) |
|||
(newline outp)) |
|||
(define (setrgbcolor rgb) |
|||
(display rgb outp) |
|||
(display " setrgbcolor" outp) |
|||
(newline outp)) |
|||
(define (simple-word word) |
|||
(lambda () |
|||
(display word outp) |
|||
(newline outp))) |
|||
(define closepath (simple-word "closepath")) |
|||
(define fill (simple-word "fill")) |
|||
(define stroke (simple-word "stroke")) |
|||
(define gsave (simple-word "gsave")) |
|||
(define grestore (simple-word "grestore")) |
|||
(define (showpoly poly line-color fill-color) |
|||
(define n (vector-length poly)) |
|||
(moveto (vector-ref poly 0)) |
|||
(do ((i 1 (+ i 1))) |
|||
((= i n)) |
|||
(lineto (vector-ref poly i))) |
|||
(closepath) |
|||
(setrgbcolor line-color) |
|||
(gsave) |
|||
(setrgbcolor fill-color) |
|||
(fill) |
|||
(grestore) |
|||
(stroke)) |
|||
(define (code s) |
|||
(display s outp) |
|||
(newline outp)) |
|||
(code "%!PS-Adobe-3.0 EPSF-3.0") |
|||
(code "%%BoundingBox: 40 40 360 360") |
|||
(code "0 setlinewidth") |
|||
(showpoly clip-points ".5 0 0" "1 .7 .7") |
|||
(showpoly subject-points "0 .2 .5" ".4 .7 1") |
|||
(code "2 setlinewidth") |
|||
(code "[10 8] 0 setdash") |
|||
(showpoly result-points ".5 0 .5" ".7 .3 .8") |
|||
(code "%%EOF")) |
|||
(define (write-eps-to-file outfile subject-points clip-points |
|||
result-points) |
|||
(with-output-to-file outfile |
|||
(lambda () |
|||
(write-eps (current-output-port) |
|||
subject-points clip-points result-points)))) |
|||
(define subject-points |
|||
#((50 150) |
|||
(200 50) |
|||
(350 150) |
|||
(350 300) |
|||
(250 300) |
|||
(200 250) |
|||
(150 350) |
|||
(100 250) |
|||
(100 200))) |
|||
(define clip-points |
|||
#((100 100) |
|||
(300 100) |
|||
(300 300) |
|||
(100 300))) |
|||
(define result-points (clip subject-points clip-points)) |
|||
(display result-points) |
|||
(newline) |
|||
(write-eps-to-file "sutherland-hodgman.eps" |
|||
subject-points clip-points result-points) |
|||
(display "Wrote sutherland-hodgman.eps") |
|||
(newline) |
|||
</syntaxhighlight> |
|||
=={{header|TypeScript}}== |
=={{header|TypeScript}}== |
||
Line 4,144: | Line 4,354: | ||
return outputList |
return outputList |
||
}</syntaxhighlight> |
}</syntaxhighlight> |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |