line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#========================================================================== |
2
|
|
|
|
|
|
|
# Module: GD::Graph::lines3d |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Copyright (C) 1999,2001 Wadsack-Allen. All Rights Reserved. |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Based on GD::Graph::lines.pm,v 1.10 2000/04/15 mgjv |
7
|
|
|
|
|
|
|
# Copyright (c) 1995-1998 Martien Verbruggen |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
10
|
|
|
|
|
|
|
# Date Modification Author |
11
|
|
|
|
|
|
|
# ------------------------------------------------------------------------- |
12
|
|
|
|
|
|
|
# 1999SEP18 Created 3D line chart class (this module) JAW |
13
|
|
|
|
|
|
|
# 1999SEP19 Finished overwrite 1 style JAW |
14
|
|
|
|
|
|
|
# 1999SEP19 Polygon'd linewidth rendering JAW |
15
|
|
|
|
|
|
|
# 2000SEP19 Converted to a GD::Graph class JAW |
16
|
|
|
|
|
|
|
# 2000APR18 Modified for compatibility with GD::Graph 1.30 JAW |
17
|
|
|
|
|
|
|
# 2000APR24 Fixed a lot of rendering bugs JAW |
18
|
|
|
|
|
|
|
# 2000AUG19 Changed render code so lines have consitent width JAW |
19
|
|
|
|
|
|
|
# 2000AUG21 Added 3d shading JAW |
20
|
|
|
|
|
|
|
# 2000AUG24 Fixed shading top/botttom vs. postive/negative slope JAW |
21
|
|
|
|
|
|
|
# 2000SEP04 For single point "lines" made a short segment JAW |
22
|
|
|
|
|
|
|
# 2000OCT09 Fixed bug in rendering of legend JAW |
23
|
|
|
|
|
|
|
#========================================================================== |
24
|
|
|
|
|
|
|
# TODO |
25
|
|
|
|
|
|
|
# ** The new mitred corners don't work well at data anomlies. Like |
26
|
|
|
|
|
|
|
# the set (0,0,1,0,0,0,1,0,1) Looks really wrong! |
27
|
|
|
|
|
|
|
# * Write a draw_data_set that draws the line so they appear to pass |
28
|
|
|
|
|
|
|
# through one another. This means drawing a border edge at each |
29
|
|
|
|
|
|
|
# intersection of the data lines so the points of pass-through show. |
30
|
|
|
|
|
|
|
# Probably want to draw all filled polygons, then run through the data |
31
|
|
|
|
|
|
|
# again finding intersections of line segments and drawing those edges. |
32
|
|
|
|
|
|
|
#========================================================================== |
33
|
|
|
|
|
|
|
package GD::Graph::lines3d; |
34
|
|
|
|
|
|
|
|
35
|
1
|
|
|
1
|
|
1143
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
39
|
|
36
|
|
|
|
|
|
|
|
37
|
1
|
|
|
1
|
|
979
|
use GD; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
use GD::Graph::axestype3d; |
39
|
|
|
|
|
|
|
use Data::Dumper; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
@GD::Graph::lines3d::ISA = qw( GD::Graph::axestype3d ); |
42
|
|
|
|
|
|
|
$GD::Graph::lines3d::VERSION = '0.63'; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my $PI = 4 * atan2(1, 1); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
my %Defaults = ( |
47
|
|
|
|
|
|
|
# The depth of the line in their extrusion |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
line_depth => 10, |
50
|
|
|
|
|
|
|
); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub initialise() |
53
|
|
|
|
|
|
|
{ |
54
|
|
|
|
|
|
|
my $self = shift; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
my $rc = $self->SUPER::initialise(); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
while( my($key, $val) = each %Defaults ) { |
59
|
|
|
|
|
|
|
$self->{$key} = $val |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# *** [JAW] |
62
|
|
|
|
|
|
|
# Should we reset the depth_3d param based on the |
63
|
|
|
|
|
|
|
# line_depth, numsets and overwrite parameters, here? |
64
|
|
|
|
|
|
|
# |
65
|
|
|
|
|
|
|
} # end while |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
return $rc; |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
} # end initialize |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub set |
72
|
|
|
|
|
|
|
{ |
73
|
|
|
|
|
|
|
my $s = shift; |
74
|
|
|
|
|
|
|
my %args = @_; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
$s->{_set_error} = 0; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
for (keys %args) |
79
|
|
|
|
|
|
|
{ |
80
|
|
|
|
|
|
|
/^line_depth$/ and do |
81
|
|
|
|
|
|
|
{ |
82
|
|
|
|
|
|
|
$s->{line_depth} = $args{$_}; |
83
|
|
|
|
|
|
|
delete $args{$_}; |
84
|
|
|
|
|
|
|
next; |
85
|
|
|
|
|
|
|
}; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
return $s->SUPER::set(%args); |
89
|
|
|
|
|
|
|
} # end set |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# PRIVATE |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# [JAW] Changed to draw_data intead of |
94
|
|
|
|
|
|
|
# draw_data_set to allow better control |
95
|
|
|
|
|
|
|
# of multiple set rendering |
96
|
|
|
|
|
|
|
sub draw_data |
97
|
|
|
|
|
|
|
{ |
98
|
|
|
|
|
|
|
my $self = shift; |
99
|
|
|
|
|
|
|
my $d = $self->{_data}; |
100
|
|
|
|
|
|
|
my $g = $self->{graph}; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
$self->draw_data_overwrite( $g, $d ); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# redraw the 'zero' axis, front and right |
105
|
|
|
|
|
|
|
if( $self->{zero_axis} ) { |
106
|
|
|
|
|
|
|
$g->line( |
107
|
|
|
|
|
|
|
$self->{left}, $self->{zeropoint}, |
108
|
|
|
|
|
|
|
$self->{right}, $self->{zeropoint}, |
109
|
|
|
|
|
|
|
$self->{fgci} ); |
110
|
|
|
|
|
|
|
$g->line( |
111
|
|
|
|
|
|
|
$self->{right}, $self->{zeropoint}, |
112
|
|
|
|
|
|
|
$self->{right} + $self->{depth_3d}, $self->{zeropoint} - $self->{depth_3d}, |
113
|
|
|
|
|
|
|
$self->{fgci} ); |
114
|
|
|
|
|
|
|
} # end if |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# redraw the box face |
117
|
|
|
|
|
|
|
if ( $self->{box_axis} ) { |
118
|
|
|
|
|
|
|
# Axes box |
119
|
|
|
|
|
|
|
$g->rectangle($self->{left}, $self->{top}, $self->{right}, $self->{bottom}, $self->{fgci}); |
120
|
|
|
|
|
|
|
$g->line($self->{right}, $self->{top}, $self->{right} + $self->{depth_3d}, $self->{top} - $self->{depth_3d}, $self->{fgci}); |
121
|
|
|
|
|
|
|
$g->line($self->{right}, $self->{bottom}, $self->{right} + $self->{depth_3d}, $self->{bottom} - $self->{depth_3d}, $self->{fgci}); |
122
|
|
|
|
|
|
|
} # end if |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
return $self; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
} # end draw_data |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# Copied from MVERB source |
129
|
|
|
|
|
|
|
sub pick_line_type |
130
|
|
|
|
|
|
|
{ |
131
|
|
|
|
|
|
|
my $self = shift; |
132
|
|
|
|
|
|
|
my $num = shift; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
ref $self->{line_types} ? |
135
|
|
|
|
|
|
|
$self->{line_types}[ $num % (1 + $#{$self->{line_types}}) - 1 ] : |
136
|
|
|
|
|
|
|
$num % 4 ? $num % 4 : 4 |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
140
|
|
|
|
|
|
|
# Sub: draw_data_overwrite |
141
|
|
|
|
|
|
|
# |
142
|
|
|
|
|
|
|
# Args: $gd |
143
|
|
|
|
|
|
|
# $gd The GD object to draw on |
144
|
|
|
|
|
|
|
# |
145
|
|
|
|
|
|
|
# Description: Draws each line segment for each set. Runs |
146
|
|
|
|
|
|
|
# over sets, then points so that the appearance is better. |
147
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
148
|
|
|
|
|
|
|
# Date Modification Author |
149
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
150
|
|
|
|
|
|
|
# 19SEP1999 Added this for overwrite support. JW |
151
|
|
|
|
|
|
|
# 20AUG2000 Changed structure to use points 'objects' JW |
152
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
153
|
|
|
|
|
|
|
sub draw_data_overwrite { |
154
|
|
|
|
|
|
|
my $self = shift; |
155
|
|
|
|
|
|
|
my $g = shift; |
156
|
|
|
|
|
|
|
my @points_cache; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
my $i; |
159
|
|
|
|
|
|
|
for $i (0 .. $self->{_data}->num_points()) |
160
|
|
|
|
|
|
|
{ |
161
|
|
|
|
|
|
|
my $j; |
162
|
|
|
|
|
|
|
for $j (1 .. $self->{_data}->num_sets()) |
163
|
|
|
|
|
|
|
{ |
164
|
|
|
|
|
|
|
my @values = $self->{_data}->y_values($j) or |
165
|
|
|
|
|
|
|
return $self->_set_error( "Impossible illegal data set: $j", $self->{_data}->error ); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
if( $self->{_data}->num_points() == 1 && $i == 1 ) { |
168
|
|
|
|
|
|
|
# Copy the first point to the "second" |
169
|
|
|
|
|
|
|
$values[$i] = $values[0]; |
170
|
|
|
|
|
|
|
} # end if |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
next unless defined $values[$i]; |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# calculate offset of this line |
175
|
|
|
|
|
|
|
# *** Should offset be the max of line_depth |
176
|
|
|
|
|
|
|
# and depth_3d/numsets? [JAW] |
177
|
|
|
|
|
|
|
# |
178
|
|
|
|
|
|
|
my $offset = $self->{line_depth} * ($self->{_data}->num_sets() - $j); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# Get the coordinates of the previous point, if this is the first |
181
|
|
|
|
|
|
|
# point make a point object and start over (i.e. next;) |
182
|
|
|
|
|
|
|
unless( $i ) { |
183
|
|
|
|
|
|
|
my( $xb, $yb ); |
184
|
|
|
|
|
|
|
if (defined($self->{x_min_value}) && defined($self->{x_max_value})) { |
185
|
|
|
|
|
|
|
($xb, $yb) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $j ); |
186
|
|
|
|
|
|
|
} else { |
187
|
|
|
|
|
|
|
($xb, $yb) = $self->val_to_pixel( $i + 1, $values[$i], $j ); |
188
|
|
|
|
|
|
|
} # end if |
189
|
|
|
|
|
|
|
$xb += $offset; |
190
|
|
|
|
|
|
|
$yb -= $offset; |
191
|
|
|
|
|
|
|
$points_cache[$i][$j] = { coords => [$xb, $yb] }; |
192
|
|
|
|
|
|
|
next; |
193
|
|
|
|
|
|
|
} # end unless |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# Pick a data colour, calc shading colors too, if requested |
196
|
|
|
|
|
|
|
my( @rgb ) = $self->pick_data_clr( $j ); |
197
|
|
|
|
|
|
|
my $dsci = $self->set_clr( @rgb ); |
198
|
|
|
|
|
|
|
if( $self->{'3d_shading'} ) { |
199
|
|
|
|
|
|
|
$self->{'3d_highlights'}[$dsci] = $self->set_clr( $self->_brighten( @rgb ) ); |
200
|
|
|
|
|
|
|
$self->{'3d_shadows'}[$dsci] = $self->set_clr( $self->_darken( @rgb ) ); |
201
|
|
|
|
|
|
|
} # end if |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Get the type |
204
|
|
|
|
|
|
|
my $type = $self->pick_line_type($j); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# Get the coordinates of the this point |
207
|
|
|
|
|
|
|
unless( ref $points_cache[$i][$j] ) { |
208
|
|
|
|
|
|
|
my( $xe, $ye ); |
209
|
|
|
|
|
|
|
if( defined($self->{x_min_value}) && defined($self->{x_max_value}) ) { |
210
|
|
|
|
|
|
|
( $xe, $ye ) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $j ); |
211
|
|
|
|
|
|
|
} else { |
212
|
|
|
|
|
|
|
( $xe, $ye ) = $self->val_to_pixel($i + 1, $values[$i], $j); |
213
|
|
|
|
|
|
|
} # end if |
214
|
|
|
|
|
|
|
$xe += $offset; |
215
|
|
|
|
|
|
|
$ye -= $offset; |
216
|
|
|
|
|
|
|
$points_cache[$i][$j] = { coords => [$xe, $ye] }; |
217
|
|
|
|
|
|
|
} # end if |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# Find the coordinates of the next point |
220
|
|
|
|
|
|
|
if( defined $values[$i + 1] ) { |
221
|
|
|
|
|
|
|
my( $xe, $ye ); |
222
|
|
|
|
|
|
|
if( defined($self->{x_min_value}) && defined($self->{x_max_value}) ) { |
223
|
|
|
|
|
|
|
( $xe, $ye ) = $self->val_to_pixel( $self->{_data}->get_x($i + 1), $values[$i + 1], $j ); |
224
|
|
|
|
|
|
|
} else { |
225
|
|
|
|
|
|
|
( $xe, $ye ) = $self->val_to_pixel($i + 2, $values[$i + 1], $j); |
226
|
|
|
|
|
|
|
} # end if |
227
|
|
|
|
|
|
|
$xe += $offset; |
228
|
|
|
|
|
|
|
$ye -= $offset; |
229
|
|
|
|
|
|
|
$points_cache[$i + 1][$j] = { coords => [$xe, $ye] }; |
230
|
|
|
|
|
|
|
} # end if |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
if( $self->{_data}->num_points() == 1 && $i == 1 ) { |
233
|
|
|
|
|
|
|
# Nudge the x coords back- and forwards |
234
|
|
|
|
|
|
|
my $n = int(($self->{right} - $self->{left}) / 30); |
235
|
|
|
|
|
|
|
$n = 2 if $n < 2; |
236
|
|
|
|
|
|
|
$points_cache[$i][$j]{coords}[0] = $points_cache[$i - 1][$j]{coords}[0] + $n; |
237
|
|
|
|
|
|
|
$points_cache[$i - 1][$j]{coords}[0] -= $n; |
238
|
|
|
|
|
|
|
} # end if |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# Draw the line segment |
241
|
|
|
|
|
|
|
$self->draw_line( $points_cache[$i - 1][$j], |
242
|
|
|
|
|
|
|
$points_cache[$i][$j], |
243
|
|
|
|
|
|
|
$points_cache[$i + 1][$j], |
244
|
|
|
|
|
|
|
$type, |
245
|
|
|
|
|
|
|
$dsci ); |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# Draw the end cap if last segment |
248
|
|
|
|
|
|
|
if( $i >= $self->{_data}->num_points() - 1 ) { |
249
|
|
|
|
|
|
|
my $poly = new GD::Polygon; |
250
|
|
|
|
|
|
|
$poly->addPt( $points_cache[$i][$j]{face}[0], $points_cache[$i][$j]{face}[1] ); |
251
|
|
|
|
|
|
|
$poly->addPt( $points_cache[$i][$j]{face}[2], $points_cache[$i][$j]{face}[3] ); |
252
|
|
|
|
|
|
|
$poly->addPt( $points_cache[$i][$j]{face}[2] + $self->{line_depth}, $points_cache[$i][$j]{face}[3] - $self->{line_depth} ); |
253
|
|
|
|
|
|
|
$poly->addPt( $points_cache[$i][$j]{face}[0] + $self->{line_depth}, $points_cache[$i][$j]{face}[1] - $self->{line_depth} ); |
254
|
|
|
|
|
|
|
if( $self->{'3d_shading'} ) { |
255
|
|
|
|
|
|
|
$g->filledPolygon( $poly, $self->{'3d_shadows'}[$dsci] ); |
256
|
|
|
|
|
|
|
} else { |
257
|
|
|
|
|
|
|
$g->filledPolygon( $poly, $dsci ); |
258
|
|
|
|
|
|
|
} # end if |
259
|
|
|
|
|
|
|
$g->polygon( $poly, $self->{fgci} ); |
260
|
|
|
|
|
|
|
} # end if |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
} # end for -- $self->{_data}->num_sets() |
263
|
|
|
|
|
|
|
} # end for -- $self->{_data}->num_points() |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
} # end sub draw_data_overwrite |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
268
|
|
|
|
|
|
|
# Sub: draw_line |
269
|
|
|
|
|
|
|
# |
270
|
|
|
|
|
|
|
# Args: $prev, $this, $next, $type, $clr |
271
|
|
|
|
|
|
|
# $prev A hash ref for the prev point's object |
272
|
|
|
|
|
|
|
# $this A hash ref for this point's object |
273
|
|
|
|
|
|
|
# $next A hash ref for the next point's object |
274
|
|
|
|
|
|
|
# $type A predefined line type (2..4) = (dashed, dotted, dashed & dotted) |
275
|
|
|
|
|
|
|
# $clr The color (colour) index to use for the fill |
276
|
|
|
|
|
|
|
# |
277
|
|
|
|
|
|
|
# Point "Object" has these properties: |
278
|
|
|
|
|
|
|
# coords A 2 element array of the coordinates for the line |
279
|
|
|
|
|
|
|
# (this should be filled in before calling) |
280
|
|
|
|
|
|
|
# face An 4 element array of end points for the face |
281
|
|
|
|
|
|
|
# polygon. This will be populated by this method. |
282
|
|
|
|
|
|
|
# |
283
|
|
|
|
|
|
|
# Description: Draws a line segment in 3d extrusion that |
284
|
|
|
|
|
|
|
# connects the prev point the the this point. The next point |
285
|
|
|
|
|
|
|
# is used to calculate the mitre at the joint. |
286
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
287
|
|
|
|
|
|
|
# Date Modification Author |
288
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
289
|
|
|
|
|
|
|
# 18SEP1999 Modified MVERB source to work on data |
290
|
|
|
|
|
|
|
# point, not data set for better rendering JAW |
291
|
|
|
|
|
|
|
# 19SEP1999 Ploygon'd line rendering for better effect JAW |
292
|
|
|
|
|
|
|
# 19AUG2000 Made line width perpendicular JAW |
293
|
|
|
|
|
|
|
# 19AUG2000 Changed parameters to use %line_seg hash/obj JAW |
294
|
|
|
|
|
|
|
# 20AUG2000 Mitred joints of line segments JAW |
295
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
296
|
|
|
|
|
|
|
sub draw_line |
297
|
|
|
|
|
|
|
{ |
298
|
|
|
|
|
|
|
my $self = shift; |
299
|
|
|
|
|
|
|
my( $prev, $this, $next, $type, $clr ) = @_; |
300
|
|
|
|
|
|
|
my $xs = $prev->{coords}[0]; |
301
|
|
|
|
|
|
|
my $ys = $prev->{coords}[1]; |
302
|
|
|
|
|
|
|
my $xe = $this->{coords}[0]; |
303
|
|
|
|
|
|
|
my $ye = $this->{coords}[1]; |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
my $lw = $self->{line_width}; |
306
|
|
|
|
|
|
|
my $lts = $self->{line_type_scale}; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
my $style = gdStyled; |
309
|
|
|
|
|
|
|
my @pattern = (); |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
LINE: { |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
($type == 2) && do { |
314
|
|
|
|
|
|
|
# dashed |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
for (1 .. $lts) { push @pattern, $clr } |
317
|
|
|
|
|
|
|
for (1 .. $lts) { push @pattern, gdTransparent } |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
$self->{graph}->setStyle(@pattern); |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
last LINE; |
322
|
|
|
|
|
|
|
}; |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
($type == 3) && do { |
325
|
|
|
|
|
|
|
# dotted, |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
for (1 .. 2) { push @pattern, $clr } |
328
|
|
|
|
|
|
|
for (1 .. 2) { push @pattern, gdTransparent } |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
$self->{graph}->setStyle(@pattern); |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
last LINE; |
333
|
|
|
|
|
|
|
}; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
($type == 4) && do { |
336
|
|
|
|
|
|
|
# dashed and dotted |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
for (1 .. $lts) { push @pattern, $clr } |
339
|
|
|
|
|
|
|
for (1 .. 2) { push @pattern, gdTransparent } |
340
|
|
|
|
|
|
|
for (1 .. 2) { push @pattern, $clr } |
341
|
|
|
|
|
|
|
for (1 .. 2) { push @pattern, gdTransparent } |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
$self->{graph}->setStyle(@pattern); |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
last LINE; |
346
|
|
|
|
|
|
|
}; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# default: solid |
349
|
|
|
|
|
|
|
$style = $clr; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# [JAW] Removed the dataset loop for better results. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# Need the setstyle to reset |
355
|
|
|
|
|
|
|
$self->{graph}->setStyle(@pattern) if (@pattern); |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# |
358
|
|
|
|
|
|
|
# Find the x and y offsets for the edge of the front face |
359
|
|
|
|
|
|
|
# Do this by adjusting them perpendicularly from the line |
360
|
|
|
|
|
|
|
# half the line width in front and in back. |
361
|
|
|
|
|
|
|
# |
362
|
|
|
|
|
|
|
my( $lwyoff, $lwxoff ); |
363
|
|
|
|
|
|
|
if( $xe == $xs ) { |
364
|
|
|
|
|
|
|
$lwxoff = $lw / 2; |
365
|
|
|
|
|
|
|
$lwyoff = 0; |
366
|
|
|
|
|
|
|
} elsif( $ye == $ys ) { |
367
|
|
|
|
|
|
|
$lwxoff = 0; |
368
|
|
|
|
|
|
|
$lwyoff = $lw / 2; |
369
|
|
|
|
|
|
|
} else { |
370
|
|
|
|
|
|
|
my $ln = sqrt( ($ys-$ye)**2 + ($xe-$xs)**2 ); |
371
|
|
|
|
|
|
|
$lwyoff = ($xe-$xs) / $ln * $lw / 2; |
372
|
|
|
|
|
|
|
$lwxoff = ($ys-$ye) / $ln * $lw / 2; |
373
|
|
|
|
|
|
|
} # end if |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# For first line, figure beginning point |
376
|
|
|
|
|
|
|
unless( defined $prev->{face}[0] ) { |
377
|
|
|
|
|
|
|
$prev->{face} = []; |
378
|
|
|
|
|
|
|
$prev->{face}[0] = $xs - $lwxoff; |
379
|
|
|
|
|
|
|
$prev->{face}[1] = $ys - $lwyoff; |
380
|
|
|
|
|
|
|
$prev->{face}[2] = $xs + $lwxoff; |
381
|
|
|
|
|
|
|
$prev->{face}[3] = $ys + $lwyoff; |
382
|
|
|
|
|
|
|
} # end unless |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Calc and store this point's face coords |
385
|
|
|
|
|
|
|
unless( defined $this->{face}[0] ) { |
386
|
|
|
|
|
|
|
$this->{face} = []; |
387
|
|
|
|
|
|
|
$this->{face}[0] = $xe - $lwxoff; |
388
|
|
|
|
|
|
|
$this->{face}[1] = $ye - $lwyoff; |
389
|
|
|
|
|
|
|
$this->{face}[2] = $xe + $lwxoff; |
390
|
|
|
|
|
|
|
$this->{face}[3] = $ye + $lwyoff; |
391
|
|
|
|
|
|
|
} # end if |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# Now find next point and nudge these coords to mitre |
394
|
|
|
|
|
|
|
if( ref $next->{coords} eq 'ARRAY' ) { |
395
|
|
|
|
|
|
|
my( $lwyo2, $lwxo2 ); |
396
|
|
|
|
|
|
|
my( $x2, $y2 ) = @{$next->{coords}}; |
397
|
|
|
|
|
|
|
if( $x2 == $xe ) { |
398
|
|
|
|
|
|
|
$lwxo2 = $lw / 2; |
399
|
|
|
|
|
|
|
$lwyo2 = 0; |
400
|
|
|
|
|
|
|
} elsif( $y2 == $ye ) { |
401
|
|
|
|
|
|
|
$lwxo2 = 0; |
402
|
|
|
|
|
|
|
$lwyo2 = $lw / 2; |
403
|
|
|
|
|
|
|
} else { |
404
|
|
|
|
|
|
|
my $ln2 = sqrt( ($ye-$y2)**2 + ($x2-$xe)**2 ); |
405
|
|
|
|
|
|
|
$lwyo2 = ($x2-$xe) / $ln2 * $lw / 2; |
406
|
|
|
|
|
|
|
$lwxo2 = ($ye-$y2) / $ln2 * $lw / 2; |
407
|
|
|
|
|
|
|
} # end if |
408
|
|
|
|
|
|
|
$next->{face} = []; |
409
|
|
|
|
|
|
|
$next->{face}[0] = $x2 - $lwxo2; |
410
|
|
|
|
|
|
|
$next->{face}[1] = $y2 - $lwyo2; |
411
|
|
|
|
|
|
|
$next->{face}[2] = $x2 + $lwxo2; |
412
|
|
|
|
|
|
|
$next->{face}[3] = $y2 + $lwyo2; |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
# Now get the intersecting coordinates |
415
|
|
|
|
|
|
|
my $mt = ($ye - $ys)/($xe - $xs); |
416
|
|
|
|
|
|
|
my $mn = ($y2 - $ye)/($x2 - $xe); |
417
|
|
|
|
|
|
|
my $bt = $this->{face}[1] - $this->{face}[0] * $mt; |
418
|
|
|
|
|
|
|
my $bn = $next->{face}[1] - $next->{face}[0] * $mn; |
419
|
|
|
|
|
|
|
if( $mt != $mn ) { |
420
|
|
|
|
|
|
|
$this->{face}[0] = ($bn - $bt) / ($mt - $mn); |
421
|
|
|
|
|
|
|
} # end if |
422
|
|
|
|
|
|
|
$this->{face}[1] = $mt * $this->{face}[0] + $bt; |
423
|
|
|
|
|
|
|
$bt = $this->{face}[3] - $this->{face}[2] * $mt; |
424
|
|
|
|
|
|
|
$bn = $next->{face}[3] - $next->{face}[2] * $mn; |
425
|
|
|
|
|
|
|
if( $mt != $mn ) { |
426
|
|
|
|
|
|
|
$this->{face}[2] = ($bn - $bt) / ($mt - $mn); |
427
|
|
|
|
|
|
|
} # end if |
428
|
|
|
|
|
|
|
$this->{face}[3] = $mt * $this->{face}[2] + $bt; |
429
|
|
|
|
|
|
|
} # end if |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
# Make the top/bottom polygon |
433
|
|
|
|
|
|
|
my $poly = new GD::Polygon; |
434
|
|
|
|
|
|
|
if( ($ys-$ye)/($xe-$xs) > 1 ) { |
435
|
|
|
|
|
|
|
$poly->addPt( $prev->{face}[2], $prev->{face}[3] ); |
436
|
|
|
|
|
|
|
$poly->addPt( $this->{face}[2], $this->{face}[3] ); |
437
|
|
|
|
|
|
|
$poly->addPt( $this->{face}[2] + $self->{line_depth}, $this->{face}[3] - $self->{line_depth} ); |
438
|
|
|
|
|
|
|
$poly->addPt( $prev->{face}[2] + $self->{line_depth}, $prev->{face}[3] - $self->{line_depth} ); |
439
|
|
|
|
|
|
|
if( $self->{'3d_shading'} && $style == $clr ) { |
440
|
|
|
|
|
|
|
if( ($ys-$ye)/($xe-$xs) > 0 ) { |
441
|
|
|
|
|
|
|
$self->{graph}->filledPolygon( $poly, $self->{'3d_shadows'}[$clr] ); |
442
|
|
|
|
|
|
|
} else { |
443
|
|
|
|
|
|
|
$self->{graph}->filledPolygon( $poly, $self->{'3d_highlights'}[$clr] ); |
444
|
|
|
|
|
|
|
} # end if |
445
|
|
|
|
|
|
|
} else { |
446
|
|
|
|
|
|
|
$self->{graph}->filledPolygon( $poly, $style ); |
447
|
|
|
|
|
|
|
} # end if |
448
|
|
|
|
|
|
|
} else { |
449
|
|
|
|
|
|
|
$poly->addPt( $prev->{face}[0], $prev->{face}[1] ); |
450
|
|
|
|
|
|
|
$poly->addPt( $this->{face}[0], $this->{face}[1] ); |
451
|
|
|
|
|
|
|
$poly->addPt( $this->{face}[0] + $self->{line_depth}, $this->{face}[1] - $self->{line_depth} ); |
452
|
|
|
|
|
|
|
$poly->addPt( $prev->{face}[0] + $self->{line_depth}, $prev->{face}[1] - $self->{line_depth} ); |
453
|
|
|
|
|
|
|
if( $self->{'3d_shading'} && $style == $clr ) { |
454
|
|
|
|
|
|
|
if( ($ys-$ye)/($xe-$xs) < 0 ) { |
455
|
|
|
|
|
|
|
$self->{graph}->filledPolygon( $poly, $self->{'3d_shadows'}[$clr] ); |
456
|
|
|
|
|
|
|
} else { |
457
|
|
|
|
|
|
|
$self->{graph}->filledPolygon( $poly, $self->{'3d_highlights'}[$clr] ); |
458
|
|
|
|
|
|
|
} # end if |
459
|
|
|
|
|
|
|
} else { |
460
|
|
|
|
|
|
|
$self->{graph}->filledPolygon( $poly, $style ); |
461
|
|
|
|
|
|
|
} # end if |
462
|
|
|
|
|
|
|
} # end if |
463
|
|
|
|
|
|
|
$self->{graph}->polygon( $poly, $self->{fgci} ); |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
# *** This paints dashed and dotted patterns on the faces of |
466
|
|
|
|
|
|
|
# the polygons. They don't look very good though. Would it |
467
|
|
|
|
|
|
|
# be better to extrude the style as well as the lines? |
468
|
|
|
|
|
|
|
# Otherwise could also be improved by using gdTiled instead of |
469
|
|
|
|
|
|
|
# gdStyled and making the tile a transform of the line style |
470
|
|
|
|
|
|
|
# for each face. [JAW] |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
# Make the face polygon |
473
|
|
|
|
|
|
|
$poly = new GD::Polygon; |
474
|
|
|
|
|
|
|
$poly->addPt( $prev->{face}[0], $prev->{face}[1] ); |
475
|
|
|
|
|
|
|
$poly->addPt( $this->{face}[0], $this->{face}[1] ); |
476
|
|
|
|
|
|
|
$poly->addPt( $this->{face}[2], $this->{face}[3] ); |
477
|
|
|
|
|
|
|
$poly->addPt( $prev->{face}[2], $prev->{face}[3] ); |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
$self->{graph}->filledPolygon( $poly, $style ); |
480
|
|
|
|
|
|
|
$self->{graph}->polygon( $poly, $self->{fgci} ); |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
} # end draw line |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
485
|
|
|
|
|
|
|
# Sub: draw_legend_marker |
486
|
|
|
|
|
|
|
# |
487
|
|
|
|
|
|
|
# Args: $dsn, $x, $y |
488
|
|
|
|
|
|
|
# $dsn The dataset number to draw the marker for |
489
|
|
|
|
|
|
|
# $x The x position of the marker |
490
|
|
|
|
|
|
|
# $y The y position of the marker |
491
|
|
|
|
|
|
|
# |
492
|
|
|
|
|
|
|
# Description: Draws the legend marker for the specified |
493
|
|
|
|
|
|
|
# dataset number at the given coordinates |
494
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
495
|
|
|
|
|
|
|
# Date Modification Author |
496
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
497
|
|
|
|
|
|
|
# 2000OCT06 Fixed rendering bugs JW |
498
|
|
|
|
|
|
|
# ---------------------------------------------------------- |
499
|
|
|
|
|
|
|
sub draw_legend_marker |
500
|
|
|
|
|
|
|
{ |
501
|
|
|
|
|
|
|
my $self = shift; |
502
|
|
|
|
|
|
|
my ($n, $x, $y) = @_; |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
my $ci = $self->set_clr($self->pick_data_clr($n)); |
505
|
|
|
|
|
|
|
my $type = $self->pick_line_type($n); |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
$y += int($self->{lg_el_height}/2); |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
# Joe Smith |
510
|
|
|
|
|
|
|
local($self->{line_width}) = 2; # Make these show up better |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
$self->draw_line( |
513
|
|
|
|
|
|
|
{ coords => [$x, $y] }, |
514
|
|
|
|
|
|
|
{ coords => [$x + $self->{legend_marker_width}, $y] }, |
515
|
|
|
|
|
|
|
undef, |
516
|
|
|
|
|
|
|
$type, |
517
|
|
|
|
|
|
|
$ci |
518
|
|
|
|
|
|
|
); |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
} # end draw_legend_marker |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
1; |