package com{ import mx.charts.HitData; import mx.charts.chartClasses.CartesianTransform; import mx.charts.series.LineSeries; import mx.charts.series.items.LineSeriesItem; import mx.graphics.IStroke; import mx.graphics.LinearGradientStroke; import mx.graphics.Stroke; public class FilterLineSeries extends LineSeries{ public function FilterLineSeries(){ super(); } override public function findDataPoints(x:Number, y:Number, sensitivity:Number):Array{ // esg, 8/7/06: if your mouse is over a series when it gets added and displayed for the first time, this can get called // before updateData, and before and render data is constructed. The right long term fix is to make sure a stubbed out // render data is _always_ present, but that's a little disruptive right now. if (interactive == false || !renderData) return []; var pr:Number = getStyle("radius"); var minDist2:Number = pr + sensitivity; minDist2 *= minDist2; var minItem:LineSeriesItem = null; var pr2:Number = pr * pr; var n:int; if(renderData.filteredCache) n = renderData.filteredCache.length; else return []; if (n == 0) return []; if (sortOnXField == true) { var low:Number = 0; var high:Number = n; var cur:Number = Math.floor((low+high)/2); var bFirstIsNaN:Boolean = isNaN(renderData.filteredCache[0]); while (true) { var v:LineSeriesItem = renderData.filteredCache[cur]; if (!isNaN(v.yNumber) && !isNaN(v.xNumber)) { var dist:Number = (v.x - x)*(v.x - x) + (v.y - y)*(v.y -y); if (dist <= minDist2) { minDist2 = dist; minItem = v; } } var a:Number; var b:Number; /*if(dataTransform && dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS) is NumericAxis && (dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS) as NumericAxis).direction == "inverted") { a = x; b = v.x; } else {*/ a = v.x; b = x; //} // if there are NaNs in this array, it's for one of a couple of reasons: // 1) there were NaNs in the data, which menas an xField was provided, which means they got sorted to the end // 2) some values got filtered out, in which case we can (sort of) safely assumed that the got filtered from one side, the other, or the entire thing. // we'll assume that an axis hasn't filtered a middle portion of the array. // since we can assume that any NaNs are at the beginning or the end, we'll rely on that in our binary search. If there was a NaN in the first slot, // then we'll assume it's safe to move up the array if we encounter a NaN. It's possible the entire array is NaN, but then nothing will match, so that's ok. if (a < b || (isNaN(v.x) && bFirstIsNaN)) { low = cur; cur = Math.floor((low + high)/2); if (cur == low) break; } else { high = cur; cur = Math.floor((low + high)/2); if (cur == high) break; } } } else { var i:uint; for (i = 0; i < n; i++) { v = renderData.filteredCache[i]; if (!isNaN(v.yNumber) && !isNaN(v.xNumber)) { dist = (v.x - x)*(v.x - x) + (v.y - y)*(v.y -y); if (dist <= minDist2) { minDist2 = dist; minItem = v; } } } } if (minItem) { var hd:HitData = new HitData(createDataID(minItem.index),Math.sqrt(minDist2),minItem.x,minItem.y,minItem); var istroke:IStroke = getStyle("lineStroke"); if (istroke is Stroke) hd.contextColor = Stroke(istroke).color; else if (istroke is LinearGradientStroke) { var gb:LinearGradientStroke = LinearGradientStroke(istroke); if (gb.entries.length > 0) hd.contextColor = gb.entries[0].color; } hd.dataTipFunction = formatDataTip; return [ hd ]; } return []; } private function formatDataTip(hd:HitData):String{ var dt:String = ""; var n:String = displayName; if (n && n != "") dt += "" + n + "
"; var xName:String = dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS).displayName; if (xName != "") dt += "" + xName+ ": "; dt += dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS).formatForScreen( LineSeriesItem(hd.chartItem).xValue) + "\n"; var yName:String = dataTransform.getAxis(CartesianTransform.VERTICAL_AXIS).displayName; if (yName != "") dt += "" + yName + ": "; dt += dataTransform.getAxis(CartesianTransform.VERTICAL_AXIS).formatForScreen( LineSeriesItem(hd.chartItem).yValue) + "\n"; return dt; } } }