-
Notifications
You must be signed in to change notification settings - Fork 228
/
clipping.coffee
93 lines (79 loc) · 2.73 KB
/
clipping.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
kartograph - a svg mapping library
Copyright (C) 2011 Gregor Aisch
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 3 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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
root = (exports ? this)
kartograph = root.kartograph ?= {}
kartograph.geom ?= {}
kartograph.geom.clipping ?= {}
class CohenSutherland
INSIDE = 0
LEFT = 1
RIGHT = 2
BOTTOM = 4
TOP = 8
compute_out_code: (bbox, x, y) ->
self = @
code = self.INSIDE
if x < bbox.left then code |= self.LEFT
else if x > bbox.right then code |= self.RIGHT
if y < bbox.top then code |= self.TOP
else if y > bbox.bottom
code |= self.BOTTOM
code
clip: (bbox, x0, y0, x1, y1) ->
self = @
code0 = self.compute_out_code(bbox, x0, y0)
code1 = self.compute_out_code(bbox, x1, y1)
accept = False
while True
if not (code0 | code1)
# Bitwise OR is 0. Trivially accept and get out of loop
accept = True
break
else if code0 & code1
# Bitwise AND is not 0. Trivially reject and get out of loop
break
else
# At least one endpoint is outside the clip rectangle; pick it
cout = if code == 0 then code1 else code0
# Now find the intersection point;
# use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
if cout & self.TOP
# point is above the clip rectangle
x = x0 + (x1 - x0) * (bbox.top - y0) / (y1 - y0)
y = bbox.top
else if cout & self.BOTTOM
# point is below the clip rectangle
x = x0 + (x1 - x0) * (bbox.bottom - y0) / (y1 - y0)
y = bbox.bottom
else if cout & self.RIGHT
# point is to the right of clip rectangle
y = y0 + (y1 - y0) * (bbox.right - x0) / (x1 - x0)
x = bbox.right
else if cout & self.LEFT
# point is to the left of clip rectangle
y = y0 + (y1 - y0) * (bbox.left - x0) / (x1 - x0)
x = bbox.left
# Now we move outside point to intersection point to clip
# and get ready for next pass.
if cout == code0
x0 = x
y0 = y
code0 = self.compute_out_code(bbox, x0, y0)
else
x1 = x
y1 = y
code1 = self.compute_out_code(bbox, x1, y1)
if accept then [x0, y0, x1, y1] else null
kartograph.geom.clipping.CohenSutherland = CohenSutherland