var _____WB$wombat$assign$function_____ = function(name) {return (self._wb_wombat && self._wb_wombat.local_init && self._wb_wombat.local_init(name)) || self[name]; }; if (!self.__WB_pmw) { self.__WB_pmw = function(obj) { this.__WB_source = obj; return this; } } { let window = _____WB$wombat$assign$function_____("window"); let self = _____WB$wombat$assign$function_____("self"); let document = _____WB$wombat$assign$function_____("document"); let location = _____WB$wombat$assign$function_____("location"); let top = _____WB$wombat$assign$function_____("top"); let parent = _____WB$wombat$assign$function_____("parent"); let frames = _____WB$wombat$assign$function_____("frames"); let opener = _____WB$wombat$assign$function_____("opener"); function ChartHitRectangle(left, top, right, bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } ChartHitRectangle.prototype = { IsVisible: function(x, y) { return (x >= this.left) && (x < this.right) && (y >= this.top) && (y < this.bottom); } } ChartHitRectangle.prototype.constructor = ChartHitRectangle; function ChartHitEmpty() { } ChartHitEmpty.prototype = { IsVisible: function(x, y) { return false; } } ChartHitEmpty.prototype.constructor = ChartHitEmpty; function ChartHitExpression(leftOperand, rightOperand) { if(ChartHitExpression.AsProrotype) return delete ChartHitExpression.AsProrotype; this.leftOperand = leftOperand; this.rightOperand = rightOperand; } ChartHitExpression.prototype = { IsVisible: function(x, y) { throw "ChartHitExpression abstract error"; } } ChartHitExpression.prototype.constructor = ChartHitExpression; function ChartHitUnion(leftOperand, rightOperand) { ChartHitExpression.call(this, leftOperand, rightOperand); } ChartHitExpression.AsPrototype = true; ChartHitUnion.prototype = new ChartHitExpression(); ChartHitUnion.prototype.constructor = ChartHitUnion; ChartHitUnion.prototype.IsVisible = function(x, y) { return this.leftOperand.IsVisible(x, y) || this.rightOperand.IsVisible(x, y); } function ChartHitIntersection(leftOperand, rightOperand) { ChartHitExpression.call(this, leftOperand, rightOperand); } ChartHitExpression.AsPrototype = true; ChartHitIntersection.prototype = new ChartHitExpression(); ChartHitIntersection.prototype.constructor = ChartHitIntersection; ChartHitIntersection.prototype.IsVisible = function(x, y) { return this.leftOperand.IsVisible(x, y) && this.rightOperand.IsVisible(x, y); } function ChartHitExclusion(leftOperand, rightOperand) { ChartHitExpression.call(this, leftOperand, rightOperand); } ChartHitExpression.AsPrototype = true; ChartHitExclusion.prototype = new ChartHitExpression(); ChartHitExclusion.prototype.constructor = ChartHitExclusion; ChartHitExclusion.prototype.IsVisible = function(x, y) { return this.leftOperand.IsVisible(x, y) && !this.rightOperand.IsVisible(x, y); } function ChartHitXor(leftOperand, rightOperand) { ChartHitExpression.call(this, leftOperand, rightOperand); } ChartHitExpression.AsPrototype = true; ChartHitXor.prototype = new ChartHitExpression(); ChartHitXor.prototype.constructor = ChartHitXor; ChartHitXor.prototype.IsVisible = function(x, y) { return this.leftOperand.IsVisible(x, y) ^ this.rightOperand.IsVisible(x, y); } function ChartHitPath(lineSegments, alternate) { this.lineSegments = lineSegments; this.alternate = alternate; } ChartHitPath.prototype = { IsVisible: function(x, y) { if(this.lineSegments.length == 0) return false; var isVisible = this.IsVisibleInternal(x - 0.01, y); if(!isVisible) isVisible = this.IsVisibleInternal(x + 0.01, y); return isVisible; }, IsVisibleInternal: function(x, y) { var filteredLineSegments = this.FilterLineSegments(x, y); if(filteredLineSegments.length == 0) return false; var xIntersections = new ChartXIntersections(filteredLineSegments, x); var indicator = this.CalcIndicator(filteredLineSegments, xIntersections, y); return this.alternate ? (indicator % 2) != 0 : indicator != 0; }, FilterLineSegments: function(x, y) { var filteredLineSegments = new Array(); for(var i = 0; i < this.lineSegments.length; i++) { var lineSegment = this.lineSegments[i]; if(this.ShouldFilterLineSegmentByX(lineSegment, x)) continue; if(this.ShouldFilterLineSegmentByY(lineSegment, y)) continue; filteredLineSegments.push(lineSegment); } return filteredLineSegments; }, ShouldFilterLineSegmentByX: function(lineSegment, x) { return ((lineSegment.startX < x) && (lineSegment.finishX < x)) || ((lineSegment.startX > x) && (lineSegment.finishX > x)); }, ShouldFilterLineSegmentByY: function(lineSegment, y) { return (lineSegment.startY < y) && (lineSegment.finishY < y); }, CalcIndicator: function(lineSegments, xIntersections, y) { var indicator = 0; for(var i = 0; i < xIntersections.intersections.length; i++) { if(xIntersections.intersections[i] < y) continue; if(lineSegments[i].LeftToRight()) indicator++; else if(lineSegments[i].RightToLeft()) indicator--; else throw ChartLineSegment.err; } return indicator; } } ChartHitPath.prototype.constructor = ChartHitPath; function ChartLineSegment(startX, startY, finishX, finishY) { this.startX = startX; this.startY = startY; this.finishX = finishX; this.finishY = finishY; } ChartLineSegment.err = "Invalid line segment"; ChartLineSegment.prototype = { LeftToRight : function() { return this.startX < this.finishX; }, RightToLeft : function() { return this.startX > this.finishX; } } ChartLineSegment.prototype.constructor = ChartLineSegment; function ChartXIntersections(lineSegments, x) { this.intersections = new Array(lineSegments.length); for(var i = 0; i < lineSegments.length; i++) this.intersections[i] = this.CalcIntersection(lineSegments[i], x); } ChartXIntersections.prototype = { CalcIntersection: function(lineSegment, x) { var delta = lineSegment.finishX - lineSegment.startX; if(delta == 0) throw ChartLineSegment.err; var k = (lineSegment.finishY - lineSegment.startY) / delta; var b = (lineSegment.startY * lineSegment.finishX - lineSegment.finishY * lineSegment.startX) / delta; return k * x + b; } } ChartXIntersections.prototype.constructor = ChartXIntersections; function ChartHitTestController(hitInfo) { this.objects = new Array(); this.additionalObjects = new Array(); var hitInfoLoader = new ChartHitInfoLoader(hitInfo); this.regions = hitInfoLoader.regions; } ChartHitTestController.prototype = { HitTest: function(x, y) { var hitRegions = this.CreateHitRegions(x, y); return this.CreateHitObjects(hitRegions); }, CreateHitRegions: function(x, y) { var hitRegions = new Array(); for(var i = 0; i < this.regions.length; i++) if(this.regions[i].IsVisible(x, y)) hitRegions.push(this.regions[i]); return hitRegions; }, CreateHitObjects: function(hitRegions) { var hitObjects = new Array(); for(var i = 0; i < hitRegions.length; i++) { var hitRegion = hitRegions[i]; hitObjects.push(this.CreateHitObject(hitRegion)); } return hitObjects; }, CreateHitObject: function(hitRegion) { var hitObject = this.objects[hitRegion.id]; var additionalHitObject = hitRegion.additionalId != -1 ? this.additionalObjects[hitRegion.additionalId] : null; if (_aspxIsExists(hitRegion.toolTipPoint) && additionalHitObject != null) additionalHitObject.toolTipPoint = hitRegion.toolTipPoint; return new ASPxClientHitObject(hitObject, additionalHitObject); } } ChartHitTestController.prototype.constructor = ChartHitTestController; function ChartHitRegion(primitive, id, additionalId, toolTipPoint) { this.primitive = primitive; this.id = id; this.additionalId = additionalId; this.toolTipPoint = toolTipPoint; } ChartHitRegion.prototype = { IsVisible: function(x, y) { return this.primitive.IsVisible(x, y); } } ChartHitRegion.prototype.constructor = ChartHitRegion; function ChartHitInfoLoader(hitInfo) { this.regions = new Array(); this.LoadHitInfo(hitInfo); } ChartHitInfoLoader.errPrefix = "ChartHitTestController loading error: "; ChartHitInfoLoader.errRegionType = ChartHitTestController.errPrefix + "Invalid hit region type"; ChartHitInfoLoader.errRegionFormat = ChartHitTestController.errPrefix + "Invalid hit region format"; ChartHitInfoLoader.prototype = { LoadHitInfo: function(hitInfo) { for(var i = 0; i < hitInfo.length; i++) this.LoadHitRegion(hitInfo[i]); }, LoadHitRegion: function(interimHitRegion) { var id = interimHitRegion.hi; var additionalId = _aspxIsExists(interimHitRegion.hia) ? interimHitRegion.hia: -1; var primitive = this.LoadPrimitive(interimHitRegion.r); var toolTipPoint = interimHitRegion.ttp; this.regions.unshift(new ChartHitRegion(primitive, id, additionalId, toolTipPoint)); }, LoadPrimitive: function(interimPrimitive) { if(interimPrimitive.t == "R") return this.LoadRectangle(interimPrimitive); else if(interimPrimitive.t == "O") return new ChartHitEmpty(); else if(interimPrimitive.t == "U") return this.LoadUnion(interimPrimitive); else if(interimPrimitive.t == "I") return this.LoadIntersection(interimPrimitive); else if(interimPrimitive.t == "E") return this.LoadExclusion(interimPrimitive); else if(interimPrimitive.t == "X") return this.LoadXor(interimPrimitive); else if(interimPrimitive.t == "P") return this.LoadPath(interimPrimitive); throw ChartHitInfoLoader.errRegionType; }, LoadRectangle: function(interimRectangle) { if(interimRectangle.r.length != 4) throw ChartHitInfoLoader.errRegionFormat; return new ChartHitRectangle(interimRectangle.r[0], interimRectangle.r[1], interimRectangle.r[2], interimRectangle.r[3]); }, LoadUnion: function(interimExpression) { var leftOperand = this.LoadPrimitive(interimExpression.l); var rightOperand = this.LoadPrimitive(interimExpression.r); return new ChartHitUnion(leftOperand, rightOperand); }, LoadIntersection: function(interimExpression) { var leftOperand = this.LoadPrimitive(interimExpression.l); var rightOperand = this.LoadPrimitive(interimExpression.r); return new ChartHitIntersection(leftOperand, rightOperand); }, LoadExclusion: function(interimExpression) { var leftOperand = this.LoadPrimitive(interimExpression.l); var rightOperand = this.LoadPrimitive(interimExpression.r); return new ChartHitExclusion(leftOperand, rightOperand); }, LoadXor: function(interimExpression) { var leftOperand = this.LoadPrimitive(interimExpression.l); var rightOperand = this.LoadPrimitive(interimExpression.r); return new ChartHitXor(leftOperand, rightOperand); }, LoadPath: function(interimPath) { var lineSegments = new Array(); var points = new Array(); var bezierPoints = new Array(); var indexInStartArray = 0; var indexInBezierArray = 0; for(var pointIndex = 0; pointIndex < interimPath.p.length; pointIndex++) { if(this.IsStartPoint(interimPath, pointIndex, indexInStartArray)) { indexInStartArray++; this.UpdateLineSegments(lineSegments, points); points.length = 0; } else if(this.IsBezierPoint(interimPath, pointIndex, indexInBezierArray)) { indexInBezierArray++; if(bezierPoints.length == 0) bezierPoints.push(interimPath.p[pointIndex - 1]); bezierPoints.push(interimPath.p[pointIndex]); if(bezierPoints.length == 4) { this.CalcBezierApproximation( bezierPoints[0][0], bezierPoints[0][1], bezierPoints[1][0], bezierPoints[1][1], bezierPoints[2][0], bezierPoints[2][1], bezierPoints[3][0], bezierPoints[3][1], points); bezierPoints.length = 0; } continue; } points.push(interimPath.p[pointIndex]); } this.UpdateLineSegments(lineSegments, points); return new ChartHitPath(lineSegments, interimPath.a); }, UpdateLineSegments: function(lineSegments, points) { if(points.length < 2) return; for(var i = 0; i < points.length - 1; i++) lineSegments.push(new ChartLineSegment( points[i][0], points[i][1], points[i + 1][0], points[i + 1][1])); lineSegments.push(new ChartLineSegment( points[points.length - 1][0], points[points.length - 1][1], points[0][0], points[0][1])); }, CreatePoint: function(x, y) { return [x, y]; }, IsStartPoint: function(interimPath, pointIndex, indexInStartArray) { return (indexInStartArray < interimPath.s.length) && (interimPath.s[indexInStartArray] == pointIndex); }, IsBezierPoint: function(interimPath, pointIndex, indexInBezierArray) { return (indexInBezierArray < interimPath.b.length) && (interimPath.b[indexInBezierArray] == pointIndex); }, CalcBezierApproximation: function(x1, y1, x2, y2, x3, y3, x4, y4, points) { var dx1 = x2 - x1; var dy1 = y2 - y1; var dx2 = x3 - x2; var dy2 = y3 - y2; var dx3 = x4 - x3; var dy3 = y4 - y3; var length = Math.sqrt(dx1 * dx1 + dy1 * dy1) + Math.sqrt(dx2 * dx2 + dy2 * dy2) + Math.sqrt(dx3 * dx3 + dy3 * dy3); var stepCount = Math.round(length * 0.25); var step = 1 / (stepCount + 1); var step2 = step * step; var step3 = step * step * step; var step13 = step * 3; var step23 = step2 * 3; var step26 = step2 * 6; var step36 = step3 * 6; var tempX1 = x1 - x2 * 2 + x3; var tempY1 = y1 - y2 * 2 + y3; var tempX2 = (x2 - x3) * 3 - x1 + x4; var tempY2 = (y2 - y3) * 3 - y1 + y4; var dx = (x2 - x1) * step13 + tempX1 * step23 + tempX2 * step3; var dy = (y2 - y1) * step13 + tempY1 * step23 + tempY2 * step3; var ddx = tempX1 * step26 + tempX2 * step36; var ddy = tempY1 * step26 + tempY2 * step36; var dddx = tempX2 * step36; var dddy = tempY2 * step36; var x = x1; var y = y1; for(var i = 0; i < stepCount; i++) { x += dx; y += dy; points.push(this.CreatePoint(x, y)); dx += ddx; dy += ddy; ddx += dddx; ddy += dddy; } points.push(this.CreatePoint(x4, y4)); } } ChartHitInfoLoader.prototype.constructor = ChartHitInfoLoader; } /* playback timings (ms): CDXLines.iter: 19.325 (3) exclusion.robots: 0.247 captures_list: 74.837 RedisCDXSource: 0.72 esindex: 0.015 load_resource: 61.969 PetaboxLoader3.datanode: 70.378 (4) PetaboxLoader3.resolve: 23.004 LoadShardBlock: 50.28 (3) exclusion.robots.policy: 0.23 */