source: code/Website/open-flash-chart/ScreenCoords.as

Last change on this file was 7849, checked in by dennisw, 15 years ago
File size: 10.9 KB
Line 
1package {
2 import flash.geom.Point;
3 import charts.series.dots.Point;
4
5 public class ScreenCoords extends ScreenCoordsBase
6 {
7 private var x_range:Range;
8 private var y_range:Range;
9 private var y_right_range:Range;
10
11 // position of the zero line
12 //public var zero:Number=0;
13 //public var steps:Number=0;
14
15 // tick_offset is set by 3D axis
16 public var tick_offset:Number;
17 private var x_offset:Boolean;
18 private var y_offset:Boolean;
19 private var bar_groups:Number;
20
21
22 public function ScreenCoords( top:Number, left:Number, right:Number, bottom:Number,
23 y_axis_range:Range,
24 y_axis_right_range:Range,
25 x_axis_range:Range,
26 x_left_label_width:Number, x_right_label_width:Number,
27 three_d:Boolean )
28 {
29 super( top, left, right, bottom );
30
31 var tmp_left:Number = left;
32
33 this.x_range = x_axis_range;
34 this.y_range = y_axis_range;
35 this.y_right_range = y_axis_right_range;
36
37 // tr.ace( '-----' );
38 // tr.ace( this.x_range.count() );
39 // tr.ace( this.y_range.count() );
40
41
42 if( x_range ) {
43 right = this.jiggle( left, right, x_right_label_width, x_axis_range.count() );
44 tmp_left = this.shrink_left( left, right, x_left_label_width, x_axis_range.count() );
45 }
46
47 this.top = top;
48 this.left = Math.max(left, tmp_left);
49
50 // round this down to the nearest int:
51 this.right = Math.floor( right );
52 this.bottom = bottom;
53 this.width = this.right-this.left;
54 this.height = bottom-top;
55
56 if( three_d )
57 {
58 // tell the box object that the
59 // X axis labels need to be offset
60 this.tick_offset = 12;
61 }
62 else
63 this.tick_offset = 0;
64
65 //
66 // x_offset:
67 //
68 // False True
69 //
70 // | |
71 // | |
72 // | |
73 // +--+--+--+ |-+--+--+--+-+
74 // 0 1 2 3 0 1 2 3
75 //
76
77 // PIE charts don't have these:
78 if( x_axis_range ) {
79 this.x_offset = x_axis_range.offset;
80 }
81 if( y_axis_range ) {
82 // tr.aces( 'YYYY', y_axis_range.offset );
83 this.y_offset = y_axis_range.offset;
84 }
85
86 this.bar_groups = 1;
87 }
88
89 //
90 // if the last X label is wider than the chart area, the last few letters will
91 // be outside the drawing area. So we make the chart width smaller so the label
92 // will fit into the screen.
93 //
94 //DZ: this implementation chops off the last label on scatter charts because it
95 // assumes the label is centered on the last "item" (like a bar) instead of
96 // at the max edge of the plot.
97 public function jiggle_original( left:Number, right:Number, x_label_width:Number, count:Number ): Number {
98 var r:Number = 0;
99
100 if( x_label_width != 0 )
101 {
102 var item_width:Number = (right-left) / count;
103 r = right - (item_width / 2);
104 var new_right:Number = right;
105
106 // while the right most X label is off the edge of the
107 // Stage, move the box.right - 1
108 while( r+(x_label_width/2) > right )
109 {
110 new_right -= 1;
111 // changing the right also changes the item_width:
112 item_width = (new_right-left) / count;
113 r = new_right-(item_width/2);
114 }
115 right = new_right;
116 }
117 return right;
118 }
119
120 //DZ: this implementation probably add white space on the right side of a
121 // non-scatter type plot because it assumes that the label is centered at
122 // the max edge of the plot instead of centered on the last "item"
123 // (like a bar)
124 public function jiggle( left:Number, right:Number, x_label_width:Number, count:Number ): Number {
125 return right - (x_label_width / 2);
126 }
127
128 //
129 // if the left label is truncated, shrink the box until
130 // it fits onto the screen
131 //
132 public function shrink_left( left:Number, right:Number, x_label_width:Number, count:Number ): Number {
133 var pos:Number = 0;
134
135 if( x_label_width != 0 )
136 {
137 var item_width:Number = (right-left) / count;
138 pos = left+(item_width/2);
139 var new_left:Number = left;
140
141 // while the left most label is hanging off the Stage
142 // move the box.left in one pixel:
143 while( pos-(x_label_width/2) < 0 )
144 {
145 new_left += 1;
146 // changing the left also changes the item_width:
147 item_width = (right-new_left) / count;
148 pos = new_left+(item_width/2);
149 }
150 left = new_left;
151 }
152
153 return left;
154
155 }
156
157 //
158 // the bottom point of a bar:
159 // min=-100 and max=100, use b.zero
160 // min = 10 and max = 20, use b.bottom
161 //
162 public override function get_y_bottom( right_axis:Boolean = false ):Number
163 {
164 //
165 // may have min=10, max=20, or
166 // min = 20, max = -20 (upside down chart)
167 //
168 var r:Range = right_axis ? this.y_right_range : this.y_range;
169
170 var min:Number = r.min;
171 var max:Number = r.max;
172 min = Math.min( min, max );
173
174 return this.get_y_from_val( Math.max(0,min), right_axis );
175 }
176
177 // takes a value and returns the screen Y location
178 public function getY_old( i:Number, right_axis:Boolean ):Number
179 {
180 var r:Range = right_axis ? this.y_right_range : this.y_range;
181
182 var steps:Number = this.height / (r.count());// ( right_axis ));
183
184 // find Y pos for value=zero
185 var y:Number = this.bottom-(steps*(r.min*-1));
186
187 // move up (-Y) to our point (don't forget that y_min will shift it down)
188 y -= i*steps;
189 return y;
190 }
191
192 //
193 // takes a value and returns the screen Y location
194 // what is the Y range?
195 //
196 // Horizontal bar charts are offset. Note:
197 // step = 1
198 // and step/2 is offset at the bottom and top
199 // so we add 1*step so we can calculate:
200 //
201 // offset = true
202 //
203 // |
204 // X -|==========
205 // |
206 // Y -|===
207 // |
208 // Z -|========
209 // +--+--+--+--+--+--
210 //
211 // offset = false
212 //
213 // 2 -|
214 // |
215 // 1 -| 0--0--0--0--0
216 // |
217 // 0 -+--+--+--+--+--+--
218 //
219 public override function get_y_from_val( i:Number, right_axis:Boolean = false ):Number {
220
221 var r:Range = right_axis ? this.y_right_range : this.y_range;
222
223 var steps:Number = this.height / r.count();
224
225 // tr.ace( 'off' );
226 // tr.ace( this.y_offset.offset );
227 // tr.ace( count );
228
229 var tmp:Number = 0;
230 if( this.y_offset )
231 tmp = (steps / 2);
232
233 // move up (-Y) to our point (don't forget that y_min will shift it down)
234 return this.bottom-tmp-(r.min-i)*steps*-1;
235 }
236
237 public override function get_get_x_from_pos_and_y_from_val( index:Number, y:Number, right_axis:Boolean = false ):flash.geom.Point {
238
239 return new flash.geom.Point(
240 this.get_x_from_pos( index ),
241 this.get_y_from_val( y, right_axis ) );
242 }
243
244 public function width_():Number
245 {
246 return this.right-this.left_();
247 }
248
249 private function left_():Number
250 {
251 var padding_left:Number = this.tick_offset;
252 return this.left+padding_left;
253 }
254
255 //
256 // Scatter and Horizontal Bar charts use this:
257 //
258 // get the x position by value
259 // (e.g. what is the x position for -5 ?)
260 //
261 public override function get_x_from_val( i:Number ):Number {
262 // Patch from DZ:
263 var rev:Boolean = this.x_range.min > this.x_range.max;
264 var count:Number = this.x_range.count();
265 count += (rev && this.x_range.offset) ? -2 : 0;
266 var item_width:Number = this.width_() / count;
267 // end DZ
268
269
270 var pos:Number = i-this.x_range.min;
271
272 var tmp:Number = 0;
273 if( this.x_offset )
274 tmp = Math.abs(item_width/2);
275
276 return this.left_()+tmp+(pos*item_width);
277 }
278
279 //
280 // get the x location of the n'th item
281 //
282 public override function get_x_from_pos( i:Number ):Number {
283 // DZ:
284// var item_width:Number = Math.abs(this.width_() / this.x_range.count());
285 var rev:Boolean = this.x_range.min > this.x_range.max;
286 var count:Number = this.x_range.count();
287 count += (rev && this.x_range.offset) ? -2 : 0;
288 var item_width:Number = Math.abs(this.width_() / count);
289
290 var tmp:Number = 0;
291 if( this.x_offset )
292 tmp = (item_width/2);
293
294 return this.left_()+tmp+(i*item_width);
295 }
296
297 //
298 // get the position of the n'th X axis tick
299 //
300 public function get_x_tick_pos( i:Number ):Number
301 {
302 return this.get_x_from_pos(i) - this.tick_offset;
303 }
304
305
306 //
307 // make a point object, using the absolute values (e.g. -5,-5 )
308 /*
309 public function make_point_2( x:Number, y:Number, right_axis:Boolean ):charts.Elements.Point
310 {
311 return new charts.Elements.Point(
312 this.get_x_from_val( x ),
313 this.get_y_from_val( y, right_axis )
314
315 // whats this for?
316 //,y
317 );
318 }*/
319
320 public function set_bar_groups( n:Number ): void {
321 this.bar_groups = n;
322 }
323
324 //
325 // index: the n'th bar from the left
326 //
327 public function get_bar_coords( index:Number, group:Number ):Object {
328 var item_width:Number = this.width_() / this.x_range.count();
329
330 // the bar(s) have gaps between them:
331 var bar_set_width:Number = item_width*0.8;
332
333 // get the margin between sets of bars:
334 var tmp:Number = 0;
335 if( this.x_offset )
336 tmp = item_width;
337
338 // 1 bar == 100% wide, 2 bars = 50% wide each
339 var bar_width:Number = bar_set_width / this.bar_groups;
340 //bar_width -= 0.001; // <-- hack so bars don't quite touch
341
342 var bar_left:Number = this.left_()+((tmp-bar_set_width)/2);
343 var left:Number = bar_left+(index*item_width);
344 left += bar_width * group;
345
346 return { x:left, width:bar_width };
347 }
348
349 public function get_horiz_bar_coords( index:Number, group:Number ):Object {
350
351 // split the height into equal heights for each bar
352 var bar_width:Number = this.height / this.y_range.count();
353
354 // the bar(s) have gaps between them:
355 var bar_set_width:Number = bar_width*0.8;
356
357 // 1 bar == 100% wide, 2 bars = 50% wide each
358 var group_width:Number = bar_set_width / this.bar_groups;
359
360 var bar_top:Number = this.top+((bar_width-bar_set_width)/2);
361 var top:Number = bar_top+(index*bar_width);
362 top += group_width * group;
363
364 return { y:top, width:group_width };
365 }
366
367
368 public function makePointHLC( x:Number, high:Number, close:Number, low:Number, right_axis:Boolean, group:Number, group_count:Number )
369 :PointHLC {
370
371 var item_width:Number = this.width_() / this.x_range.count();
372 // the bar(s) have gaps between them:
373 var bar_set_width:Number = item_width*1;
374
375 // get the margin between sets of bars:
376 var bar_left:Number = this.left_()+((item_width-bar_set_width)/2);
377 // 1 bar == 100% wide, 2 bars = 50% wide each
378 var bar_width:Number = bar_set_width/group_count;
379
380 var left:Number = bar_left+(x*item_width);
381 left += bar_width*group;
382
383 return new PointHLC(
384 left,
385 this.get_y_from_val( high, right_axis ),
386 this.get_y_from_val( close, right_axis ),
387 this.get_y_from_val( low, right_axis ),
388 high,
389 bar_width
390// ,close
391 );
392
393 }
394 }
395}
Note: See TracBrowser for help on using the repository browser.