1 | package {
|
---|
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 | }
|
---|