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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <gki.h>
include <gset.h>
include <mach.h>
include "ccp.h"
# CCP_CALCSEG -- Calculate a contiguous line segment; used to return individual
# line segments under the various options of line type simulation. (Width is
# not simulated here). Each segment returned is actually drawable, guaranteeing
# constant-length dashes and gaps along the exact length of the input polyline.
# Normally called by ccp_polyline.
procedure ccp_calcseg (p, npts, ltype, curpl_pt, segsize, xseg,yseg, nsegpts)
short p[ARB] # points defining line
int npts # number of points, i.e., (x,y) pairs
int ltype # line type; CCP_CLEAR <= ltype <= CCP_DASHDOT
int curpl_pt # current polyline point; input and output
int segsize # current segment memory size
pointer xseg,yseg # plotter-unit contiguous line segment, output
int nsegpts # number of points in segment, output
int i, j
real lastp_x, lastp_y, x, y, curseglen
bool toggle
include "ccp.com"
begin
if (curpl_pt == 1) { # always start line w/beginning of dash, etc.
lastp_x = XTRAN(p[1])
lastp_y = YTRAN(p[2])
curpl_pt = curpl_pt + 1
toggle = false
}
XSEG(1) = lastp_x
YSEG(1) = lastp_y
nsegpts = 1
curseglen = 0.0
switch (ltype) {
case GL_CLEAR:
nsegpts = 0
case GL_DASHED:
# Return one contiguous polyline segment worth one dash:
call ccx_dash (p, npts, curpl_pt, curseglen, nsegpts, segsize,
xseg,yseg, lastp_x,lastp_y)
# Now increment internal counters for gap width for next call
call ccx_gap (p, npts, curpl_pt, curseglen, g_dashlen + g_gaplen,
lastp_x,lastp_y)
case GL_DOTTED:
# Since we already built one point, we need only the following gap:
call ccx_gap (p, npts, curpl_pt, curseglen, g_gaplen,
lastp_x,lastp_y)
case GL_DOTDASH:
# Implement as dash/gap/dot/gap/:
if (toggle) { # build dot/gap/
x = lastp_x #XTRAN(p[i])
y = lastp_y #YTRAN(p[i+1])
nsegpts = 0
call ccx_addsegpt (x,y, xseg,yseg, nsegpts, segsize)
toggle = false
call ccx_gap (p, npts, curpl_pt, curseglen, g_gaplen,
lastp_x,lastp_y)
} else { # build dash/gap/
call ccx_dash (p, npts, curpl_pt, curseglen, nsegpts,
segsize, xseg,yseg, lastp_x,lastp_y)
call ccx_gap (p, npts, curpl_pt, curseglen,
g_dashlen + g_gaplen, lastp_x,lastp_y)
toggle = true
}
default: # solid line
do i = curpl_pt, npts {
j = (i-1) * 2 + 1
x = XTRAN(p[j])
y = YTRAN(p[j+1])
call ccx_addsegpt (x,y, xseg,yseg, nsegpts, segsize)
}
curpl_pt = npts
}
end
# CCX_DASH -- Do the actual work of building a dashed line segment (no gap)
procedure ccx_dash (p, npts, curpl_pt, curseglen, cursegpt, segsize,
xseg,yseg, lastp_x,lastp_y)
short p[ARB] # Input: points defining line
int npts # Input: number of points, i.e., (x,y) pairs
int curpl_pt # In/Output: current polyline point
real curseglen # Output: length of current simulated ltype unit (._)
int cursegpt # Output: index of current drawable point in segment
int segsize # In/Output: current segment size
pointer xseg,yseg # Output: plotter-units, contiguous line segment
real lastp_x,lastp_y # Output: last point in segment (visible or invisible)
int i
real temppl_dis, x, y, delx, dely
real actual_dis, rem_dashlen
include "ccp.com"
begin
rem_dashlen = g_dashlen
# Build up current "dash" (may be bent any number of times).
while (curseglen + EPSILON < g_dashlen && curpl_pt <= npts) {
i = (curpl_pt-1) * 2 + 1
x = XTRAN(p[i])
y = YTRAN(p[i+1])
temppl_dis = DIS(lastp_x, lastp_y, x, y)
if (temppl_dis >= EPSILON) {
actual_dis = min (temppl_dis, rem_dashlen)
rem_dashlen = rem_dashlen - actual_dis
delx = x - lastp_x
dely = y - lastp_y
x = lastp_x + delx * actual_dis / temppl_dis
y = lastp_y + dely * actual_dis / temppl_dis
call ccx_addsegpt (x,y, xseg,yseg, cursegpt, segsize)
curseglen = curseglen + actual_dis
lastp_x = XSEG(cursegpt)
lastp_y = YSEG(cursegpt)
}
if (curseglen + EPSILON < g_dashlen)
curpl_pt = curpl_pt + 1
}
end
# CCX_GAP -- Do the actual work of building an invisible gap along original
# polyline.
procedure ccx_gap (p, npts, curpl_pt, curseglen, matchlen, lastp_x,lastp_y)
short p[ARB] # Input: points defining line
int npts # Input: number of points, i.e., (x,y) pairs
int curpl_pt # In/Output: current polyline point
real curseglen # In/Output: length of current simulated ltype unit (._)
real matchlen # Output: length to build curseglen up to
real lastp_x,lastp_y # Output: last point in segment (visible, invisible)
int i
real x, y, delx, dely
real temppl_dis, actual_dis, rem_gaplen
include "ccp.com"
begin
rem_gaplen = g_gaplen
# Build up current "gap" (may be bent any number of times).
while ((curseglen + EPSILON < (matchlen)) && (curpl_pt <= npts)) {
i = (curpl_pt-1) * 2 + 1
x = XTRAN(p[i])
y = YTRAN(p[i+1])
temppl_dis = DIS(lastp_x, lastp_y, x, y)
if (temppl_dis >= EPSILON) {
actual_dis = min (temppl_dis, rem_gaplen)
rem_gaplen = rem_gaplen - actual_dis
delx = x - lastp_x
dely = y - lastp_y
curseglen = curseglen + actual_dis
lastp_x = lastp_x + delx * actual_dis / temppl_dis
lastp_y = lastp_y + dely * actual_dis / temppl_dis
}
if (curseglen + EPSILON < matchlen)
curpl_pt = curpl_pt + 1
}
end
# CCX_ADDSEGPT -- add a point to the segment structure; handle memory needs
procedure ccx_addsegpt (x,y, xseg,yseg, cursegpt,segsize)
real x,y # point to be added to output segment
pointer xseg,yseg # NDC-coord contiguous line segment, output
int cursegpt # index of current drawable point in segment
int segsize # current segment size
begin
cursegpt = cursegpt + 1
if (cursegpt > segsize) {
segsize = segsize + SEGSIZE
call realloc (xseg, segsize, TY_REAL)
call realloc (yseg, segsize, TY_REAL)
}
XSEG(cursegpt) = x
YSEG(cursegpt) = y
end
|