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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
# GTR_POLYCLIP -- Clip a convex polygon to a box. If the polygon is entirely
# outside the box 0 is returned; if the polygon is entirely within the box 1
# is returned, otherwise the polygon is clipped and a value other than 0 or 1
# is returned. This is based on code by Paul Heckbert from Graphics Gems,
# 1985/1989.
int procedure gtr_polyclip (pv, npts, x1, x2, y1, y2)
short pv[ARB] #U polygon to be clipped
int npts #U number of points in polygon
int x1,x2,y1,y2 #I clipping box
pointer sp, p1, p2, pt
int x1out, x2out, y1out, y2out, i
int gtr_cliptoplane()
define nopts_ 91
begin
x1out = 0; x2out = 0
y1out = 0; y2out = 0
# Count vertices which are outside with respect to each of the
# four planes.
do i = 1, npts*2, 2 {
if (pv[i+0] < x1) x1out = x1out + 1
if (pv[i+0] > x2) x2out = x2out + 1
if (pv[i+1] < y1) y1out = y1out + 1
if (pv[i+1] > y2) y2out = y2out + 1
}
# Is the polygon entirely inside the clipping box?
if (x1out + x2out + y1out + y2out == 0)
return (1)
# Is the polygon entirely outside the clipping box?
if (x1out == npts || x2out == npts || y1out == npts || y2out == npts)
return (0)
# If we get here the polygon partially intersects the clipping box.
# Clip against each of the planes that might cut the polygon, clipping
# the previously clipped polygon in each step. This is done in
# floating point to minimize accumulation of error when interpolating
# to the clipping plane to compute a new polygon vertex when the plane
# is crossed.
call smark (sp)
call salloc (p1, npts * 4, TY_REAL)
p2 = p1 + npts * 2
call achtsr (pv, Memr[p1], npts * 2)
if (x1out > 0)
if (gtr_cliptoplane (p1, p2, npts, 0, -1.0, real(x1)) == 0)
goto nopts_
else {
pt = p1; p1 = p2; p2 = pt
}
if (x2out > 0)
if (gtr_cliptoplane (p1, p2, npts, 0, 1.0, real(x2)) == 0)
goto nopts_
else {
pt = p1; p1 = p2; p2 = pt
}
if (y1out > 0)
if (gtr_cliptoplane (p1, p2, npts, 1, -1.0, real(y1)) == 0)
goto nopts_
else {
pt = p1; p1 = p2; p2 = pt
}
if (y2out > 0)
if (gtr_cliptoplane (p1, p2, npts, 1, 1.0, real(y2)) == 0)
goto nopts_
else {
pt = p1; p1 = p2; p2 = pt
}
call achtrs (Memr[p1], pv, npts * 2)
call sfree (sp)
return (npts)
nopts_
call sfree (sp)
return (0)
end
# GTR_CLIPTOPLANE -- Clip the convex polygon P1 against a plane, copying
# the inbounds portion to the output polygon P2.
int procedure gtr_cliptoplane (p1, p2, npts, index, s, ref)
pointer p1 #I pointer to input polygon
pointer p2 #I pointer to output polygon
int npts #U number of polygon points or vertices
int index #I index of coordinate to be tested
real s #I sign for comparison
real ref #I value to compare against
int nout, i
pointer op, u, v
real tu, tv, t
begin
nout = 0
op = p2
u = p1 + (npts - 1) * 2
tu = s * Memr[u+index] - ref
v = p1
do i = 1, npts {
# On old polygon P1, U is previous vertex, V is current vertex,
# TV is negative if vertex V is in.
tv = s * Memr[v+index] - ref
if (! ((tu <= 0 && tv <= 0) || (tu > 0 && tv > 0))) {
# Edge crosses plane; add intersection point to P2.
t = tu / (tu - tv)
Memr[op+0] = Memr[u+0] + t * (Memr[v+0] - Memr[u+0])
Memr[op+1] = Memr[u+1] + t * (Memr[v+1] - Memr[u+1])
nout = nout + 1
op = op + 2
}
if (tv <= 0) {
# Vertex V is in, copy it out.
Memr[op+0] = Memr[v+0]
Memr[op+1] = Memr[v+1]
nout = nout + 1
op = op + 2
}
u = v
tu = tv
v = v + 2
}
npts = nout
return (nout)
end
|