/// <summary> /// Renders the polygon annotation. /// </summary> /// <param name="rc">The render context.</param> /// <param name="model">The plot model.</param> public override void Render(IRenderContext rc, PlotModel model) { base.Render(rc, model); this.screenPosition = this.Transform(this.X, this.Y); // clip to the area defined by the axes var clippingRectangle = this.GetClippingRect(); rc.DrawMarker(clippingRectangle, this.screenPosition, this.Shape, this.CustomOutline, this.Size, this.Fill, this.Stroke, this.StrokeThickness); if (!string.IsNullOrEmpty(this.Text)) { var dx = -(int)this.TextHorizontalAlignment * (this.Size + this.TextMargin); var dy = -(int)this.TextVerticalAlignment * (this.Size + this.TextMargin); var textPosition = this.screenPosition + new ScreenVector(dx, dy); rc.DrawClippedText( clippingRectangle, textPosition, this.Text, this.ActualTextColor, this.ActualFont, this.ActualFontSize, this.ActualFontWeight, this.TextRotation, this.TextHorizontalAlignment, this.TextVerticalAlignment); } }
/// <summary> /// Erzeugt eine neue Instanz eines ColorPicker-Objekts und initialisiert diese /// mit der Farbe, auf welche der Farbwähler beim Aufruf aus Sicht des Spielers zeigt. /// </summary> public ColorPicker(IScreen screen, DisplayLayer drawOrder, Color def) : base(screen, drawOrder) { tileSize = new ScreenPoint (screen, 0.032f, 0.032f); // Widget-Attribute BackgroundColorFunc = (s) => Design.WidgetBackground; ForegroundColorFunc = (s) => Design.WidgetForeground; AlignX = HorizontalAlignment.Left; AlignY = VerticalAlignment.Top; // die Farb-Tiles colors = new List<Color> (CreateColors (64)); colors.Sort (ColorHelper.SortColorsByLuminance); tiles = new List<ScreenPoint> (CreateTiles (colors)); // einen Spritebatch spriteBatch = new SpriteBatch (screen.GraphicsDevice); // Position und Größe Bounds.Position = ScreenPoint.Centered (screen, Bounds); Bounds.Size.RelativeFunc = () => { float sqrt = (float)Math.Ceiling (Math.Sqrt (colors.Count)); return tileSize * sqrt; }; // Die Callback-Funktion zur Selektion setzt das SelectedColor-Attribut ColorSelected += (color, time) => { SelectedColor = color; }; }
private static DataPoint? GetNearestPoint(ISeries s, ScreenPoint point, bool snap, bool pointsOnly) { if (s == null) return null; if (snap || pointsOnly) { ScreenPoint spn; DataPoint dpn; if (s.GetNearestPoint(point, out dpn, out spn) && snap) { if (spn.DistanceTo(point) < 20) return dpn; } } ScreenPoint sp; DataPoint dp; if (!pointsOnly) if (s.GetNearestInterpolatedPoint(point, out dp, out sp)) return dp; return null; }
/// <summary> /// Initializes a new instance of the <see cref="HitTestResult" /> class. /// </summary> /// <param name="element">The element that was hit.</param> /// <param name="nearestHitPoint">The nearest hit point.</param> /// <param name="item">The item.</param> /// <param name="index">The index.</param> public HitTestResult(UIElement element, ScreenPoint nearestHitPoint, object item = null, double index = 0) { this.Element = element; this.NearestHitPoint = nearestHitPoint; this.Item = item; this.Index = index; }
/// <summary> /// Initializes a new instance of the <see cref="OxyTouchEventArgs" /> class. /// </summary> /// <param name="currentTouches">The current touches.</param> /// <param name="previousTouches">The previous touches.</param> public OxyTouchEventArgs(ScreenPoint[] currentTouches, ScreenPoint[] previousTouches) { this.Position = currentTouches[0]; if (currentTouches.Length == previousTouches.Length) { this.DeltaTranslation = currentTouches[0] - previousTouches[0]; } double scale = 1; if (currentTouches.Length > 1 && currentTouches.Length == previousTouches.Length) { var currentDistance = (currentTouches[1] - currentTouches[0]).Length; var previousDistance = (previousTouches[1] - previousTouches[0]).Length; scale = currentDistance / previousDistance; if (scale < 0.5) { scale = 0.5; } if (scale > 2) { scale = 2; } } this.DeltaScale = new ScreenVector(scale, scale); }
public void EndpointsOutsideArea() { var clipping = new CohenSutherlandClipping(new OxyRect(0, 0, 1, 1)); var p0 = new ScreenPoint(0.3, -0.2); var p1 = new ScreenPoint(0.6, 1.3); Assert.IsTrue(clipping.ClipLine(ref p0, ref p1)); Assert.AreEqual(0, p0.Y); Assert.AreEqual(1, p1.Y); }
public void EndpointsOutsideArea2() { var clipping = new CohenSutherlandClipping(new OxyRect(0.3, -0.5, 0.5, 1)); var p0 = new ScreenPoint(0, 0); var p1 = new ScreenPoint(1, 0); Assert.IsTrue(clipping.ClipLine(ref p0, ref p1)); Assert.AreEqual(new ScreenPoint(0.3, 0), p0); Assert.AreEqual(new ScreenPoint(0.8, 0), p1); }
public void ClipLine_EndpointsInsideArea() { var clipping = new CohenSutherlandClipping(0, 1, 0, 1); var p0 = new ScreenPoint(0.3, 0.2); var p1 = new ScreenPoint(0.6, 0.8); Assert.IsTrue(clipping.ClipLine(ref p0, ref p1)); Assert.AreEqual(0.2, p0.Y); Assert.AreEqual(0.8, p1.Y); }
public TweenEffect(ScreenPoint startpoint, ScreenPoint endpoint, int time) { this.StartLocation = startpoint; this.EndLocation = endpoint; this.CurrentLocation = new ScreenPoint(this.StartLocation.X, this.StartLocation.Y); this.Time = time; this.Finished = (endpoint.X == startpoint.X && endpoint.Y == startpoint.Y); }
public override void OnMouseMove(ScreenPoint pt, bool control, bool shift) { if (currentSeries == null) return; var current = GetNearestPoint(currentSeries, pt, !control, shift); if (current != null) pc.ShowSlider(currentSeries, current.Value); }
public void ClipLine_LineOutsideArea() { var clipping = new CohenSutherlandClipping(0, 1, 0, 1); var p0 = new ScreenPoint(0.3, -0.2); var p1 = new ScreenPoint(0.6, -0.2); Assert.IsFalse(clipping.ClipLine(ref p0, ref p1)); Assert.AreEqual(-0.2, p0.Y); Assert.AreEqual(-0.2, p1.Y); }
public void EmptyArray() { var points = new ScreenPoint[0]; var clippingRectangle = new OxyRect(0.3, -0.5, 0.5, 1); var rc = Substitute.For<IRenderContext>(); var received = new List<ScreenPoint>(); rc.DrawClippedLine(clippingRectangle, points, 1, OxyColors.Black, 1, null, LineJoin.Miter, false, null, received.AddRange); Assert.AreEqual(0, received.Count); }
/// <summary> /// Gets the touch points from the specified <see cref="MotionEvent" /> argument. /// </summary> /// <param name="e">The event arguments.</param> /// <param name = "scale">The resolution scale factor.</param> /// <returns>The touch points.</returns> public static ScreenPoint[] GetTouchPoints(this MotionEvent e, double scale) { var result = new ScreenPoint[e.PointerCount]; for (int i = 0; i < e.PointerCount; i++) { result[i] = new ScreenPoint(e.GetX(i) / scale, e.GetY(i) / scale); } return result; }
/// <summary> /// Initializes a new instance of the <see cref="ImageAnnotation"/> class. /// </summary> /// <param name="image"> /// The image. /// </param> /// <param name="position"> /// The position in screen coordinates. /// </param> /// <param name="horizontalAlignment"> /// The horizontal alignment. /// </param> /// <param name="verticalAlignment"> /// The vertical alignment. /// </param> public ImageAnnotation( OxyImage image, ScreenPoint position, HorizontalAlignment horizontalAlignment = OxyPlot.HorizontalAlignment.Center, VerticalAlignment verticalAlignment = OxyPlot.VerticalAlignment.Middle) : this() { this.ImageSource = image; this.X = new PlotLength(position.X, PlotLengthUnit.ScreenUnits); this.Y = new PlotLength(position.Y, PlotLengthUnit.ScreenUnits); this.HorizontalAlignment = horizontalAlignment; this.VerticalAlignment = verticalAlignment; }
public BaseCamera(int x, int y, int width, int height) { this.screen = new Rectangle(x, y, width, height); this.halfscreen = new ScreenPoint(screen.Width / 2, screen.Height / 2); this.Viewport = new Viewport() { X = x, Y = y, Width = width, Height = height }; }
/// <summary> /// Gets the point on the series that is nearest the specified point. /// </summary> /// <param name="point">The point.</param> /// <param name="interpolate">Interpolate the series if this flag is set to <c>true</c>.</param> /// <returns>A TrackerHitResult for the current hit.</returns> public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { if (this.XAxis == null || this.YAxis == null) { return null; } if (interpolate) { return null; } TrackerHitResult result = null; // http://paulbourke.net/geometry/pointlineplane/ double minimumDistance = double.MaxValue; var points = this.ActualPoints; for (int i = 0; i < points.Count; i++) { var p1 = points[i]; var basePoint = new DataPoint(p1.X, this.Base); var sp1 = this.Transform(p1); var sp2 = this.Transform(basePoint); var u = ScreenPointHelper.FindPositionOnLine(point, sp1, sp2); if (double.IsNaN(u)) { continue; } if (u < 0 || u > 1) { continue; // outside line } var sp = sp1 + ((sp2 - sp1) * u); double distance = (point - sp).LengthSquared; if (distance < minimumDistance) { result = new TrackerHitResult( this, new DataPoint(p1.X, p1.Y), new ScreenPoint(sp1.x, sp1.y), this.GetItem(i)); minimumDistance = distance; } } return result; }
/// <summary> /// Occurs when the input device changes position during a manipulation. /// </summary> /// <param name="e">The <see cref="OxyPlot.OxyMouseEventArgs" /> instance containing the event data.</param> public override void Delta(OxyMouseEventArgs e) { base.Delta(e); if (this.XAxis != null) { this.XAxis.Pan(this.PreviousPosition, e.Position); } if (this.YAxis != null) { this.YAxis.Pan(this.PreviousPosition, e.Position); } this.PlotView.InvalidatePlot(false); this.PreviousPosition = e.Position; }
/// <summary> /// Occurs when the input device changes position during a manipulation. /// </summary> /// <param name="e"> /// The <see cref="OxyPlot.ManipulationEventArgs"/> instance containing the event data. /// </param> public override void Delta(ManipulationEventArgs e) { base.Delta(e); if (this.XAxis != null) { this.PlotControl.Pan(this.XAxis, this.PreviousPosition, e.CurrentPosition); } if (this.YAxis != null) { this.PlotControl.Pan(this.YAxis, this.PreviousPosition, e.CurrentPosition); } this.PlotControl.RefreshPlot(false); this.PreviousPosition = e.CurrentPosition; }
public void DrawLines(IEnumerable<ScreenPoint> points, OxyColor stroke, double thickness, double[] dashArray, OxyPenLineJoin lineJoin, bool aliased) { var startPoint = new ScreenPoint(); bool first = true; foreach (var p in points) { if (!first) { Add(new Line { X1 = startPoint.X, Y1 = startPoint.Y, X2 = p.X, Y2 = p.Y }); } else { startPoint = p; } first = !first; } }
public override void OnMouseDown(ScreenPoint pt, OxyMouseButton button, int clickCount, bool control, bool shift) { base.OnMouseDown(pt, button, clickCount, control, shift); if (button != OxyMouseButton.Left) return; // Middle button double click adds an annotation if (clickCount == 2) { // pc.Annotations. pc.Refresh(); } currentSeries = pc.GetSeriesFromPoint(pt) as DataSeries; OnMouseMove(pt, control, shift); //pc.CaptureMouse(); // pc.Cursor = Cursors.Cross; }
/// <summary> /// Converts a <see cref="T:Point" /> array to a <see cref="ScreenPoint" /> array. /// </summary> /// <param name="points">The points.</param> /// <returns>A <see cref="ScreenPoint" /> array.</returns> public static ScreenPoint[] ToScreenPointArray(this Point[] points) { if (points == null) { return null; } var pts = new ScreenPoint[points.Length]; for (int i = 0; i < points.Length; i++) { pts[i] = points[i].ToScreenPoint(); } return pts; }
/// <summary> /// Gets the point in the dataset that is nearest the specified point. /// </summary> /// <param name="point"> /// The point. /// </param> /// <param name="interpolate"> /// The interpolate. /// </param> /// <returns> /// A TrackerHitResult for the current hit. /// </returns> public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { for (int i = 0; i < this.ActualMinimumBarRectangles.Count; i++) { var r = this.ActualMinimumBarRectangles[i]; if (r.Contains(point)) { var item = (TornadoBarItem)this.GetItem(this.ValidItemsIndexInversion[i]); var categoryIndex = item.GetCategoryIndex(i); var value = this.ValidItems[i].Minimum; var dp = new DataPoint(categoryIndex, value); var text = StringHelper.Format(this.ActualCulture, this.TrackerFormatString, item, value); return new TrackerHitResult(this, dp, point, item, i, text); } r = this.ActualMaximumBarRectangles[i]; if (r.Contains(point)) { var item = (TornadoBarItem)this.GetItem(this.ValidItemsIndexInversion[i]); var categoryIndex = item.GetCategoryIndex(i); var value = this.ValidItems[i].Maximum; var dp = new DataPoint(categoryIndex, value); var text = StringHelper.Format(this.ActualCulture, this.TrackerFormatString, item, value); return new TrackerHitResult(this, dp, point, item, i, text); } } return null; }
/// <summary> /// Applies an offset to a screen point. /// </summary> /// <param name="screenPoint">The screen point.</param> /// <param name="offset">The offset.</param> /// <returns>The translated screen point.</returns> private static ScreenPoint Translate(ScreenPoint screenPoint, double offset) { return(new ScreenPoint(screenPoint.X + offset, screenPoint.Y)); }
/// <summary> /// Transforms from a screen point to a data point by the axes of this series. /// </summary> /// <param name="p">The screen point.</param> /// <returns>A data point.</returns> public DataPoint InverseTransform(ScreenPoint p) { return(this.XAxis.InverseTransform(p.X, p.Y, this.YAxis)); }
/// <summary> /// Gets the nearest point. /// </summary> /// <param name="points">The points (data coordinates).</param> /// <param name="point">The point (screen coordinates).</param> /// <returns>A <see cref="TrackerHitResult" /> if a point was found, <c>null</c> otherwise.</returns> /// <remarks>The Text property of the result will not be set, since the formatting depends on the various series.</remarks> protected TrackerHitResult GetNearestPointInternal(IEnumerable <DataPoint> points, ScreenPoint point) { var spn = default(ScreenPoint); var dpn = default(DataPoint); double index = -1; double minimumDistance = double.MaxValue; int i = 0; foreach (var p in points) { if (!this.IsValidPoint(p)) { i++; continue; } var sp = this.XAxis.Transform(p.x, p.y, this.YAxis); double d2 = (sp - point).LengthSquared; if (d2 < minimumDistance) { dpn = p; spn = sp; minimumDistance = d2; index = i; } i++; } if (minimumDistance < double.MaxValue) { var item = this.GetItem((int)Math.Round(index)); return(new TrackerHitResult { Series = this, DataPoint = dpn, Position = spn, Item = item, Index = index }); } return(null); }
private static Point ToPoint(ScreenPoint point) { return new Point(point.X, point.Y); }
/// <summary> /// Transforms orientated screen space coordinates to data space coordinates. /// </summary> /// <param name="point">The point to inverse transform.</param> /// <returns>The inverse transformed point.</returns> public new DataPoint InverseTransform(ScreenPoint point) { return(base.InverseTransform(this.Orientate(point))); }
/// <summary> /// Transforms the specified screen position to a data point. /// </summary> /// <param name="position">The position.</param> /// <returns>A data point</returns> public DataPoint InverseTransform(ScreenPoint position) { return(this.XAxis.InverseTransform(position.X, position.Y, this.YAxis)); }
/// <summary> /// Gets the point on the series that is nearest the specified point. /// </summary> /// <param name="point">The point.</param> /// <param name="interpolate">Interpolate the series if this flag is set to <c>true</c>.</param> /// <returns>A TrackerHitResult for the current hit.</returns> public virtual TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { return(null); }
/// <summary> /// Renders by an image sized from the available plot area. /// </summary> /// <param name="rc">The rc.</param> /// <param name="model">The model.</param> public void RenderDynamic(IRenderContext rc, PlotModel model) { int m = this.Data.GetLength(0); int n = this.Data.GetLength(1); // get the available plot area var dest = model.PlotArea; int width = (int)dest.Width; int height = (int)dest.Height; if (width == 0 || height == 0) { return; } if (this.pixels == null || this.pixels.GetLength(0) != height || this.pixels.GetLength(1) != width) { this.pixels = new OxyColor[width, height]; } var p = this.pixels; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // transform from screen to magnitude/angle var sp = new ScreenPoint(dest.Left + x, dest.Top + y); var xy = this.InverseTransform(sp); double angle; double magnitude; if (this.PlotModel.PlotType != PlotType.Polar) { angle = Math.Atan2(xy.Y, xy.X) / Math.PI * 180; magnitude = Math.Sqrt((xy.X * xy.X) + (xy.Y * xy.Y)); } else { angle = xy.Y / Math.PI * 180; magnitude = xy.X; if (angle < 0) { angle += 360; } } // transform to indices in the Data array var ii = (angle - this.Angle0) / (this.Angle1 - this.Angle0) * m; var jj = (magnitude - this.Magnitude0) / (this.Magnitude1 - this.Magnitude0) * n; if (ii >= 0 && ii < m && jj >= 0 && jj < n) { // get the (interpolated) value var value = this.GetValue(ii, jj); // use the color axis to get the color p[x, y] = OxyColor.FromAColor(160, this.ColorAxis.GetColor(value)); } else { // outside the range of the Data array p[x, y] = OxyColors.Transparent; } } } // Create the PNG image this.image = OxyImage.Create(p, ImageFormat.Png); // Render the image var clip = this.GetClippingRect(); rc.DrawClippedImage(clip, this.image, dest.Left, dest.Top, dest.Width, dest.Height, 1, false); }
/// <summary> /// Gets the point on the series that is nearest the specified point. /// </summary> /// <param name="point">The point.</param> /// <param name="interpolate">Interpolate the series if this flag is set to <c>true</c>.</param> /// <returns>A TrackerHitResult for the current hit.</returns> public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { if (this.XAxis == null || this.YAxis == null || interpolate || this.Items.Count == 0) { return(null); } var nbars = this.Items.Count; var xy = this.InverseTransform(point); var targetX = xy.X; // punt if beyond start & end of series if (targetX > (this.Items[nbars - 1].X + this.minDx) || targetX < (this.Items[0].X - this.minDx)) { return(null); } var pidx = this.FindWindowStartIndex(this.Items, item => item.X, targetX, this.WindowStartIndex); var nidx = ((pidx + 1) < this.Items.Count) ? pidx + 1 : pidx; Func <HighLowItem, double> distance = bar => { var dx = bar.X - xy.X; var dyo = bar.Open - xy.Y; var dyh = bar.High - xy.Y; var dyl = bar.Low - xy.Y; var dyc = bar.Close - xy.Y; var d2O = (dx * dx) + (dyo * dyo); var d2H = (dx * dx) + (dyh * dyh); var d2L = (dx * dx) + (dyl * dyl); var d2C = (dx * dx) + (dyc * dyc); return(Math.Min(d2O, Math.Min(d2H, Math.Min(d2L, d2C)))); }; // determine closest point var midx = distance(this.Items[pidx]) <= distance(this.Items[nidx]) ? pidx : nidx; var mbar = this.Items[midx]; var hit = new DataPoint(mbar.X, mbar.Close); return(new TrackerHitResult { Series = this, DataPoint = hit, Position = this.Transform(hit), Item = mbar, Index = midx, Text = StringHelper.Format( this.ActualCulture, this.TrackerFormatString, mbar, this.Title, this.XAxis.Title ?? DefaultXAxisTitle, this.XAxis.GetValue(mbar.X), this.YAxis.GetValue(mbar.High), this.YAxis.GetValue(mbar.Low), this.YAxis.GetValue(mbar.Open), this.YAxis.GetValue(mbar.Close)) }); }
/// <summary> /// Renders the series on the specified rendering context. /// </summary> /// <param name="rc">The rendering context.</param> // ReSharper disable once FunctionComplexityOverflow public override void Render(IRenderContext rc) { if (this.data == null || this.data.Count == 0) { return; } var items = this.data; var nitems = this.data.Count; this.VerifyAxes(); var clippingBar = this.GetClippingRect(this.BarAxis); var clippingSep = this.GetSeparationClippingRect(); var clippingVol = this.GetClippingRect(this.VolumeAxis); var datacandlewidth = (this.CandleWidth > 0) ? this.CandleWidth : this.minDx * 0.80; var candlewidth = this.XAxis.Transform(items[0].X + datacandlewidth) - this.XAxis.Transform(items[0].X) - this.StrokeThickness; // colors var fillUp = this.GetSelectableFillColor(this.PositiveColor); var fillDown = this.GetSelectableFillColor(this.NegativeColor); var barfillUp = this.PositiveHollow ? OxyColors.Transparent : fillUp; var barfillDown = this.NegativeHollow ? OxyColors.Transparent : fillDown; var lineUp = this.GetSelectableColor(this.PositiveColor.ChangeIntensity(this.StrokeIntensity)); var lineDown = this.GetSelectableColor(this.NegativeColor.ChangeIntensity(this.StrokeIntensity)); // determine render range var xmin = this.XAxis.ActualMinimum; var xmax = this.XAxis.ActualMaximum; this.winIndex = OhlcvItem.FindIndex(items, xmin, this.winIndex); for (int i = this.winIndex; i < nitems; i++) { var bar = items[i]; // if item beyond visible range, done if (bar.X > xmax) { break; } // check to see whether is valid if (!bar.IsValid()) { continue; } var fillColor = bar.Close > bar.Open ? barfillUp : barfillDown; var lineColor = bar.Close > bar.Open ? lineUp : lineDown; var high = this.Transform(bar.X, bar.High); var low = this.Transform(bar.X, bar.Low); var open = this.Transform(bar.X, bar.Open); var close = this.Transform(bar.X, bar.Close); var max = new ScreenPoint(open.X, Math.Max(open.Y, close.Y)); var min = new ScreenPoint(open.X, Math.Min(open.Y, close.Y)); // Bar part rc.DrawClippedLine( clippingBar, new[] { high, min }, 0, lineColor, this.StrokeThickness, null, LineJoin.Miter, true); // Lower extent rc.DrawClippedLine( clippingBar, new[] { max, low }, 0, lineColor, this.StrokeThickness, null, LineJoin.Miter, true); // Body var openLeft = open + new ScreenVector(-candlewidth * 0.5, 0); if (max.Y - min.Y < 1.0) { var leftPoint = new ScreenPoint(openLeft.X - this.StrokeThickness, min.Y); var rightPoint = new ScreenPoint(openLeft.X + this.StrokeThickness + candlewidth, min.Y); rc.DrawClippedLine(clippingBar, new[] { leftPoint, rightPoint }, leftPoint.DistanceToSquared(rightPoint), lineColor, this.StrokeThickness, null, LineJoin.Miter, true); leftPoint = new ScreenPoint(openLeft.X - this.StrokeThickness, max.Y); rightPoint = new ScreenPoint(openLeft.X + this.StrokeThickness + candlewidth, max.Y); rc.DrawClippedLine(clippingBar, new[] { leftPoint, rightPoint }, leftPoint.DistanceToSquared(rightPoint), lineColor, this.StrokeThickness, null, LineJoin.Miter, true); } else { var rect = new OxyRect(openLeft.X, min.Y, candlewidth, max.Y - min.Y); rc.DrawClippedRectangleAsPolygon(clippingBar, rect, fillColor, lineColor, this.StrokeThickness); } // Volume Part if (this.VolumeAxis == null || this.VolumeStyle == VolumeStyle.None) { continue; } var iY0 = this.VolumeAxis.Transform(0); switch (this.VolumeStyle) { case VolumeStyle.Combined: { var adj = this.VolumeAxis.Transform(Math.Abs(bar.BuyVolume - bar.SellVolume)); var fillcolor = (bar.BuyVolume > bar.SellVolume) ? barfillUp : barfillDown; var linecolor = (bar.BuyVolume > bar.SellVolume) ? lineUp : lineDown; var rect1 = new OxyRect(openLeft.X, adj, candlewidth, Math.Abs(adj - iY0)); rc.DrawClippedRectangleAsPolygon(clippingVol, rect1, fillcolor, linecolor, this.StrokeThickness); } break; case VolumeStyle.PositiveNegative: { var buyY = this.VolumeAxis.Transform(bar.BuyVolume); var sellY = this.VolumeAxis.Transform(-bar.SellVolume); var rect1 = new OxyRect(openLeft.X, buyY, candlewidth, Math.Abs(buyY - iY0)); rc.DrawClippedRectangleAsPolygon(clippingVol, rect1, fillUp, lineUp, this.StrokeThickness); var rect2 = new OxyRect(openLeft.X, iY0, candlewidth, Math.Abs(sellY - iY0)); rc.DrawClippedRectangleAsPolygon(clippingVol, rect2, fillDown, lineDown, this.StrokeThickness); } break; case VolumeStyle.Stacked: if (bar.BuyVolume > bar.SellVolume) { var buyY = this.VolumeAxis.Transform(bar.BuyVolume); var sellY = this.VolumeAxis.Transform(bar.SellVolume); var dyoffset = sellY - iY0; var rect2 = new OxyRect(openLeft.X, sellY, candlewidth, Math.Abs(sellY - iY0)); rc.DrawClippedRectangleAsPolygon(clippingVol, rect2, fillDown, lineDown, this.StrokeThickness); var rect1 = new OxyRect(openLeft.X, buyY + dyoffset, candlewidth, Math.Abs(buyY - iY0)); rc.DrawClippedRectangleAsPolygon(clippingVol, rect1, fillUp, lineUp, this.StrokeThickness); } else { var buyY = this.VolumeAxis.Transform(bar.BuyVolume); var sellY = this.VolumeAxis.Transform(bar.SellVolume); var dyoffset = buyY - iY0; var rect1 = new OxyRect(openLeft.X, buyY, candlewidth, Math.Abs(buyY - iY0)); rc.DrawClippedRectangleAsPolygon(clippingVol, rect1, fillUp, lineUp, this.StrokeThickness); var rect2 = new OxyRect(openLeft.X, sellY + dyoffset, candlewidth, Math.Abs(sellY - iY0)); rc.DrawClippedRectangleAsPolygon(clippingVol, rect2, fillDown, lineDown, this.StrokeThickness); } break; } } if (this.SeparatorStrokeThickness > 0 && this.SeparatorLineStyle != LineStyle.None) { // draw volume & bar separation line if (this.VolumeStyle != VolumeStyle.None) { var ysep = (clippingSep.Bottom + clippingSep.Top) / 2.0; rc.DrawClippedLine( clippingSep, new[] { new ScreenPoint(clippingSep.Left, ysep), new ScreenPoint(clippingSep.Right, ysep) }, 0, this.SeparatorColor, this.SeparatorStrokeThickness, this.SeparatorLineStyle.GetDashArray(), LineJoin.Miter, true); } // draw volume y=0 line if (this.VolumeAxis != null && this.VolumeStyle == VolumeStyle.PositiveNegative) { var y0 = this.VolumeAxis.Transform(0); rc.DrawClippedLine( clippingVol, new[] { new ScreenPoint(clippingVol.Left, y0), new ScreenPoint(clippingVol.Right, y0) }, 0, OxyColors.Goldenrod, this.SeparatorStrokeThickness, this.SeparatorLineStyle.GetDashArray(), LineJoin.Miter, true); } } }
private static Point ToPoint(ScreenPoint point) { return(new Point(point.X, point.Y)); }
public static ScreenPoint[] CreateCustomMarker(EarType earType, bool isNoResponse, bool addShift) { const double a = 0.5; const double b = 0.375; List <AGPoint> sUpperUpperHalf = new List <AGPoint>(); sUpperUpperHalf.Add(new AGPoint(0.5, 0)); sUpperUpperHalf.Add(new AGPoint(0.3, 0)); sUpperUpperHalf.Add(new AGPoint(0.1, 0)); sUpperUpperHalf.Add(new AGPoint(-0.1, 0)); sUpperUpperHalf.Add(new AGPoint(-0.3, 0)); sUpperUpperHalf.Add(new AGPoint(-0.5, 0)); int i = 0; for (; i < sUpperUpperHalf.Count; i++) { sUpperUpperHalf[i].Y = -b - Math.Sqrt(Math.Pow(b, 2) - Math.Pow((b * sUpperUpperHalf[i].X / a), 2)); } List <AGPoint> sUpperLowerHalf = new List <AGPoint>(); sUpperLowerHalf.Add(new AGPoint(-0.5, 0)); sUpperLowerHalf.Add(new AGPoint(-0.3, 0)); sUpperLowerHalf.Add(new AGPoint(-0.1, 0)); sUpperLowerHalf.Add(new AGPoint(0, 0)); for (i = 0; i < sUpperLowerHalf.Count; i++) { sUpperLowerHalf[i].Y = -b + Math.Sqrt(Math.Pow(b, 2) - Math.Pow((b * sUpperLowerHalf[i].X / a), 2)); } List <AGPoint> sLowerUpperHalf = new List <AGPoint>(); sLowerUpperHalf.Add(new AGPoint(0.1, 0)); sLowerUpperHalf.Add(new AGPoint(0.3, 0)); sLowerUpperHalf.Add(new AGPoint(0.5, 0)); for (i = 0; i < sLowerUpperHalf.Count; i++) { sLowerUpperHalf[i].Y = b - Math.Sqrt(Math.Pow(b, 2) - Math.Pow((b * sLowerUpperHalf[i].X / a), 2)); } List <AGPoint> sLowerLowerHalf = new List <AGPoint>(); sLowerLowerHalf.Add(new AGPoint(0.5, 0)); sLowerLowerHalf.Add(new AGPoint(0.3, 0)); sLowerLowerHalf.Add(new AGPoint(0.1, 0)); sLowerLowerHalf.Add(new AGPoint(-0.1, 0)); sLowerLowerHalf.Add(new AGPoint(-0.3, 0)); sLowerLowerHalf.Add(new AGPoint(-0.5, 0)); for (i = 0; i < sLowerLowerHalf.Count; i++) { sLowerLowerHalf[i].Y = b + Math.Sqrt(Math.Pow(b, 2) - Math.Pow((b * sLowerLowerHalf[i].X / a), 2)); } List <ScreenPoint> marker = new List <ScreenPoint>(); for (i = sLowerLowerHalf.Count - 2; i >= 0; i--) { marker.Add(new ScreenPoint(sLowerLowerHalf[i].X, sLowerLowerHalf[i].Y)); } for (i = sLowerUpperHalf.Count - 1; i >= 0; i--) { marker.Add(new ScreenPoint(sLowerUpperHalf[i].X, sLowerUpperHalf[i].Y)); } for (i = sUpperLowerHalf.Count - 1; i >= 0; i--) { marker.Add(new ScreenPoint(sUpperLowerHalf[i].X, sUpperLowerHalf[i].Y)); } for (i = sUpperUpperHalf.Count - 1; i >= 0; i--) { marker.Add(new ScreenPoint(sUpperUpperHalf[i].X, sUpperUpperHalf[i].Y)); } for (i = 0; i < sUpperUpperHalf.Count; i++) { marker.Add(new ScreenPoint(sUpperUpperHalf[i].X, sUpperUpperHalf[i].Y)); } for (i = 0; i < sUpperLowerHalf.Count; i++) { marker.Add(new ScreenPoint(sUpperLowerHalf[i].X, sUpperLowerHalf[i].Y)); } for (i = 0; i < sLowerUpperHalf.Count; i++) { marker.Add(new ScreenPoint(sLowerUpperHalf[i].X, sLowerUpperHalf[i].Y)); } for (i = 0; i < sLowerLowerHalf.Count; i++) { marker.Add(new ScreenPoint(sLowerLowerHalf[i].X, sLowerLowerHalf[i].Y)); } if (isNoResponse) { ScreenPoint lastPoint = marker.Last(); ArrowMarker.AddArrowToMarker(marker, earType, lastPoint.X, lastPoint.Y); } if (addShift) { ShiftMarker.AddShift(marker, earType); } return(marker.ToArray()); }
private PointF ToPoint (ScreenPoint p) { return new PointF((float)p.X, (float)p.Y); }
/// <summary> /// Renders the series on the specified rendering context. /// </summary> /// <param name="rc">The rendering context.</param> public override void Render(IRenderContext rc) { if (this.Items.Count == 0) { return; } this.VerifyAxes(); var clippingRect = this.GetClippingRect(); var dashArray = this.LineStyle.GetDashArray(); var actualColor = this.GetSelectableColor(this.ActualColor); var shadowEndColor = this.GetSelectableColor(this.ShadowEndColor); if (this.StrokeThickness > 0 && this.LineStyle != LineStyle.None) { foreach (var v in this.Items) { if (!this.IsValidItem(v, this.XAxis, this.YAxis)) { continue; } if (v.X <= this.XAxis.ActualMinimum || v.X >= this.XAxis.ActualMaximum) { continue; } var high = this.Transform(v.X, v.High); var low = this.Transform(v.X, v.Low); if (double.IsNaN(v.Open) || double.IsNaN(v.Close)) { rc.DrawClippedLine( clippingRect, new[] { low, high }, 0, actualColor, this.StrokeThickness, dashArray, this.LineJoin, false); } else { var open = this.Transform(v.X, v.Open); var close = this.Transform(v.X, v.Close); var max = new ScreenPoint(open.X, Math.Max(open.Y, close.Y)); var min = new ScreenPoint(open.X, Math.Min(open.Y, close.Y)); // Upper shadow rc.DrawClippedLine( clippingRect, new[] { high, min }, 0, actualColor, this.StrokeThickness, dashArray, this.LineJoin, true); // Lower shadow rc.DrawClippedLine( clippingRect, new[] { max, low }, 0, actualColor, this.StrokeThickness, dashArray, this.LineJoin, true); // Shadow ends if (this.ShadowEndColor.IsVisible() && this.ShadowEndLength > 0) { var highLeft = new ScreenPoint(high.X - (this.CandleWidth * 0.5 * this.ShadowEndLength) - 1, high.Y); var highRight = new ScreenPoint(high.X + (this.CandleWidth * 0.5 * this.ShadowEndLength), high.Y); rc.DrawClippedLine( clippingRect, new[] { highLeft, highRight }, 0, shadowEndColor, this.StrokeThickness, dashArray, this.LineJoin, true); var lowLeft = new ScreenPoint(low.X - (this.CandleWidth * 0.5 * this.ShadowEndLength) - 1, low.Y); var lowRight = new ScreenPoint(low.X + (this.CandleWidth * 0.5 * this.ShadowEndLength), low.Y); rc.DrawClippedLine( clippingRect, new[] { lowLeft, lowRight }, 0, shadowEndColor, this.StrokeThickness, dashArray, this.LineJoin, true); } // Body var openLeft = open + new ScreenVector(-this.CandleWidth * 0.5, 0); var rect = new OxyRect(openLeft.X, min.Y, this.CandleWidth, max.Y - min.Y); var fillColor = v.Close > v.Open ? this.GetSelectableFillColor(this.ActualIncreasingFill) : this.GetSelectableFillColor(this.DecreasingFill); rc.DrawClippedRectangleAsPolygon(clippingRect, rect, fillColor, actualColor, this.StrokeThickness); } } } }
/// <summary> /// Renders the Series on the specified rendering context. /// </summary> /// <param name="rc">The rendering context.</param> /// <param name="model">The model.</param> public override void Render(IRenderContext rc, PlotModel model) { this.ActualBarRectangles = new List<OxyRect>(); if (this.ValidItems.Count == 0) { return; } var clippingRect = this.GetClippingRect(); var categoryAxis = this.GetCategoryAxis(); var actualBarWidth = this.GetActualBarWidth(); var stackIndex = categoryAxis.GetStackIndex(this.StackGroup); for (var i = 0; i < this.ValidItems.Count; i++) { var item = this.ValidItems[i]; var categoryIndex = item.GetCategoryIndex(i); double categoryValue = categoryAxis.GetCategoryValue(categoryIndex, stackIndex, actualBarWidth); var p0 = this.Transform(item.Start, categoryValue); var p1 = this.Transform(item.End, categoryValue + actualBarWidth); var rectangle = OxyRect.Create(p0.X, p0.Y, p1.X, p1.Y); this.ActualBarRectangles.Add(rectangle); rc.DrawClippedRectangleAsPolygon( clippingRect, rectangle, this.GetSelectableFillColor(item.Color.GetActualColor(this.ActualFillColor)), this.StrokeColor, this.StrokeThickness); if (this.LabelFormatString != null) { var s = this.Format(this.LabelFormatString, this.GetItem(i), item.Start, item.End, item.Title); var pt = new ScreenPoint( (rectangle.Left + rectangle.Right) / 2, (rectangle.Top + rectangle.Bottom) / 2); rc.DrawClippedText( clippingRect, pt, s, this.ActualTextColor, this.ActualFont, this.ActualFontSize, this.ActualFontWeight, 0, HorizontalAlignment.Center, VerticalAlignment.Middle); } } }
/// <summary> /// Gets the nearest point. /// </summary> /// <param name="point">The point.</param> /// <param name="interpolate">interpolate if set to <c>true</c> .</param> /// <returns>A TrackerHitResult for the current hit.</returns> public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { if (this.XAxis == null || this.YAxis == null) { return(null); } if (interpolate) { return(null); } TrackerHitResult result = null; double minimumDistance = double.MaxValue; int i = 0; var xaxisTitle = this.XAxis.Title ?? "X"; var yaxisTitle = this.YAxis.Title ?? "Y"; var colorAxisTitle = (this.ColorAxis != null ? ((Axis)this.ColorAxis).Title : null) ?? "Z"; var formatString = this.TrackerFormatString; if (string.IsNullOrEmpty(this.TrackerFormatString)) { // Create a default format string formatString = "{1}: {2}\n{3}: {4}"; if (this.ColorAxis != null) { formatString += "\n{5}: {6}"; } } foreach (var p in this.ActualPointsList) { if (p.X < this.XAxis.ActualMinimum || p.X > this.XAxis.ActualMaximum || p.Y < this.YAxis.ActualMinimum || p.Y > this.YAxis.ActualMaximum) { i++; continue; } var sp = this.XAxis.Transform(p.X, p.Y, this.YAxis); double dx = sp.x - point.x; double dy = sp.y - point.y; double d2 = (dx * dx) + (dy * dy); if (d2 < minimumDistance) { var item = this.GetItem(i) ?? p; object xvalue = this.XAxis.GetValue(p.X); object yvalue = this.YAxis.GetValue(p.Y); object zvalue = null; if (!double.IsNaN(p.Value) && !double.IsInfinity(p.Value)) { zvalue = p.Value; } var text = this.Format( formatString, item, this.Title, xaxisTitle, xvalue, yaxisTitle, yvalue, colorAxisTitle, zvalue); result = new TrackerHitResult(this, new DataPoint(p.X, p.Y), sp, item, i, text); minimumDistance = d2; } i++; } return(result); }
/// <summary> /// Renders the arrow annotation. /// </summary> /// <param name="rc">The render context.</param> /// <param name="model">The plot model.</param> public override void Render(IRenderContext rc, PlotModel model) { base.Render(rc, model); this.screenEndPoint = this.Transform(this.EndPoint); if (this.ArrowDirection.LengthSquared > 0) { this.screenStartPoint = this.screenEndPoint - this.ArrowDirection; } else { this.screenStartPoint = this.Transform(this.StartPoint); } var d = this.screenEndPoint - this.screenStartPoint; d.Normalize(); var n = new ScreenVector(d.Y, -d.X); var p1 = this.screenEndPoint - (d * this.HeadLength * this.StrokeThickness); var p2 = p1 + (n * this.HeadWidth * this.StrokeThickness); var p3 = p1 - (n * this.HeadWidth * this.StrokeThickness); var p4 = p1 + (d * this.Veeness * this.StrokeThickness); var clippingRectangle = this.GetClippingRect(); const double MinimumSegmentLength = 4; var dashArray = this.LineStyle.GetDashArray(); rc.DrawClippedLine( clippingRectangle, new[] { this.screenStartPoint, p4 }, MinimumSegmentLength * MinimumSegmentLength, this.GetSelectableColor(this.Color), this.StrokeThickness, dashArray, this.LineJoin, false); rc.DrawClippedPolygon( clippingRectangle, new[] { p3, this.screenEndPoint, p2, p4 }, MinimumSegmentLength * MinimumSegmentLength, this.GetSelectableColor(this.Color), OxyColors.Undefined); if (!string.IsNullOrEmpty(this.Text)) { var ha = this.TextHorizontalAlignment; var va = this.TextVerticalAlignment; if (!this.TextPosition.IsDefined()) { // automatic position => use automatic alignment ha = d.X < 0 ? HorizontalAlignment.Left : HorizontalAlignment.Right; va = d.Y < 0 ? VerticalAlignment.Top : VerticalAlignment.Bottom; } var textPoint = this.GetActualTextPosition(() => this.screenStartPoint); rc.DrawClippedText( clippingRectangle, textPoint, this.Text, this.ActualTextColor, this.ActualFont, this.ActualFontSize, this.ActualFontWeight, this.TextRotation, ha, va); } }
/// <summary> /// Initializes a new instance of the <see cref="HitTestArguments"/> class. /// </summary> /// <param name="point">The point.</param> /// <param name="tolerance">The tolerance.</param> public HitTestArguments(ScreenPoint point, double tolerance) { this.Point = point; this.Tolerance = tolerance; }
/// <summary> /// Gets the point on the curve that is nearest the specified point. /// </summary> /// <param name="points">The point list.</param> /// <param name="point">The point.</param> /// <returns>A tracker hit result if a point was found.</returns> /// <remarks>The Text property of the result will not be set, since the formatting depends on the various series.</remarks> protected TrackerHitResult GetNearestInterpolatedPointInternal(List <DataPoint> points, ScreenPoint point) { if (this.XAxis == null || this.YAxis == null || points == null) { return(null); } var spn = default(ScreenPoint); var dpn = default(DataPoint); double index = -1; double minimumDistance = double.MaxValue; for (int i = 0; i + 1 < points.Count; i++) { var p1 = points[i]; var p2 = points[i + 1]; if (!this.IsValidPoint(p1) || !this.IsValidPoint(p2)) { continue; } var sp1 = this.Transform(p1); var sp2 = this.Transform(p2); // Find the nearest point on the line segment. var spl = ScreenPointHelper.FindPointOnLine(point, sp1, sp2); if (ScreenPoint.IsUndefined(spl)) { // P1 && P2 coincident continue; } double l2 = (point - spl).LengthSquared; if (l2 < minimumDistance) { double segmentLength = (sp2 - sp1).Length; double u = segmentLength > 0 ? (spl - sp1).Length / segmentLength : 0; dpn = new DataPoint(p1.X + (u * (p2.X - p1.X)), p1.Y + (u * (p2.Y - p1.Y))); spn = spl; minimumDistance = l2; index = i + u; } } if (minimumDistance < double.MaxValue) { var item = this.GetItem((int)Math.Round(index)); return(new TrackerHitResult { Series = this, DataPoint = dpn, Position = spn, Item = item, Index = index }); } return(null); }
/// <summary> /// Gets the point on the series that is nearest the specified point. /// </summary> /// <param name="point">The point.</param> /// <param name="interpolate">Interpolate the series if this flag is set to <c>true</c>.</param> /// <returns>A TrackerHitResult for the current hit.</returns> public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { if (this.XAxis == null || this.YAxis == null) { return(null); } if (interpolate) { return(null); } TrackerHitResult result = null; // http://paulbourke.net/geometry/pointlineplane/ double minimumDistance = double.MaxValue; var points = this.ActualPoints; for (int i = 0; i < points.Count; i++) { var p1 = points[i]; var basePoint = new DataPoint(p1.X, this.Base); var sp1 = this.Transform(p1); var sp2 = this.Transform(basePoint); var u = ScreenPointHelper.FindPositionOnLine(point, sp1, sp2); if (double.IsNaN(u)) { u = 1; // we are a tiny line, snap to the end } if (u < 0 || u > 1) { u = 1; // we are outside the line, snap to the end } var sp = sp1 + ((sp2 - sp1) * u); double distance = (point - sp).LengthSquared; if (distance < minimumDistance) { var item = this.GetItem(i); result = new TrackerHitResult { Series = this, DataPoint = new DataPoint(p1.X, p1.Y), Position = new ScreenPoint(sp1.x, sp1.y), Item = this.GetItem(i), Index = i, Text = StringHelper.Format( this.ActualCulture, this.TrackerFormatString, item, this.Title, this.XAxis.Title ?? XYAxisSeries.DefaultXAxisTitle, this.XAxis.GetValue(p1.X), this.YAxis.Title ?? XYAxisSeries.DefaultYAxisTitle, this.YAxis.GetValue(p1.Y)) }; minimumDistance = distance; } } return(result); }
/// <summary> /// Draws the text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The fill color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text.</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, OxyPlot.HorizontalAlignment halign, OxyPlot.VerticalAlignment valign, OxySize?maxSize) { var tb = new TextBlock { Text = text, Foreground = new SolidColorBrush(fill.ToColor()) }; // tb.SetValue(TextOptions.TextHintingModeProperty, TextHintingMode.Animated); if (fontFamily != null) { tb.FontFamily = new FontFamily(fontFamily); } if (fontSize > 0) { tb.FontSize = fontSize; } tb.FontWeight = GetFontWeight(fontWeight); tb.Measure(new Size(1000, 1000)); var size = new Size(tb.ActualWidth, tb.ActualHeight); if (maxSize != null) { if (size.Width > maxSize.Value.Width) { size.Width = maxSize.Value.Width; } if (size.Height > maxSize.Value.Height) { size.Height = maxSize.Value.Height; } tb.Clip = new RectangleGeometry { Rect = new Rect(0, 0, size.Width, size.Height) }; } double dx = 0; if (halign == OxyPlot.HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == OxyPlot.HorizontalAlignment.Right) { dx = -size.Width; } double dy = 0; if (valign == OxyPlot.VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == OxyPlot.VerticalAlignment.Bottom) { dy = -size.Height; } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform { X = (int)dx, Y = (int)dy }); if (!rotate.Equals(0)) { transform.Children.Add(new RotateTransform { Angle = rotate }); } transform.Children.Add(new TranslateTransform { X = (int)p.X, Y = (int)p.Y }); tb.RenderTransform = transform; this.ApplyTooltip(tb); if (this.clip) { // add a clipping container that is not rotated var c = new Canvas(); c.Children.Add(tb); this.Add(c); } else { this.Add(tb); } }
/// <summary> /// Gets the nearest point. /// </summary> /// <param name="point">The point.</param> /// <param name="interpolate">interpolate if set to <c>true</c> .</param> /// <returns>A TrackerHitResult for the current hit.</returns> public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { if (this.XAxis == null || this.YAxis == null) { return(null); } if (interpolate) { return(null); } var actualPoints = this.ActualPointsList; if (actualPoints == null || actualPoints.Count == 0) { return(null); } TrackerHitResult result = null; double minimumDistance = double.MaxValue; int i = 0; var xaxisTitle = this.XAxis.Title ?? DefaultXAxisTitle; var yaxisTitle = this.YAxis.Title ?? DefaultYAxisTitle; var colorAxisTitle = (this.ColorAxis != null ? ((Axis)this.ColorAxis).Title : null) ?? DefaultColorAxisTitle; foreach (var p in actualPoints) { if (p.X < this.XAxis.ActualMinimum || p.X > this.XAxis.ActualMaximum || p.Y < this.YAxis.ActualMinimum || p.Y > this.YAxis.ActualMaximum) { i++; continue; } var sp = this.XAxis.Transform(p.X, p.Y, this.YAxis); double dx = sp.x - point.x; double dy = sp.y - point.y; double d2 = (dx * dx) + (dy * dy); if (d2 < minimumDistance) { var item = this.GetItem(i) ?? p; object zvalue = null; if (!double.IsNaN(p.Value) && !double.IsInfinity(p.Value)) { zvalue = p.Value; } result = new TrackerHitResult { Series = this, DataPoint = new DataPoint(p.X, p.Y), Position = sp, Item = item, Index = i, Text = StringHelper.Format( this.ActualCulture, this.TrackerFormatString, item, this.Title, xaxisTitle, this.XAxis.GetValue(p.X), yaxisTitle, this.YAxis.GetValue(p.Y), colorAxisTitle, zvalue), }; minimumDistance = d2; } i++; } return(result); }
/// <summary> /// Converts a <see cref="ScreenPoint" /> to a pixel center aligned <see cref="PointF" />. /// </summary> /// <param name="p">The point to convert.</param> /// <returns>The converted point.</returns> public static PointF ConvertAliased(this ScreenPoint p) { return(new PointF(0.5f + (float)Math.Round(p.X), 0.5f + (float)Math.Round(p.Y))); }
/// <summary> /// Draws text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The text color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font (in device independent units, 1/96 inch).</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text (in device independent units, 1/96 inch).</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalAlignment halign, VerticalAlignment valign, OxySize?maxSize) { var tb = this.CreateAndAdd <TextBlock>(); tb.Text = text; tb.Foreground = this.GetCachedBrush(fill); if (fontFamily != null) { tb.FontFamily = this.GetCachedFontFamily(fontFamily); } if (fontSize > 0) { tb.FontSize = fontSize; } if (fontWeight > 0) { tb.FontWeight = GetFontWeight(fontWeight); } TextOptions.SetTextFormattingMode(tb, this.TextFormattingMode); double dx = 0; double dy = 0; if (maxSize != null || halign != HorizontalAlignment.Left || valign != VerticalAlignment.Top) { tb.Measure(new Size(1000, 1000)); var size = tb.DesiredSize; if (maxSize != null) { if (size.Width > maxSize.Value.Width + 1e-3) { size.Width = Math.Max(maxSize.Value.Width, 0); } if (size.Height > maxSize.Value.Height + 1e-3) { size.Height = Math.Max(maxSize.Value.Height, 0); } tb.Width = size.Width; tb.Height = size.Height; } if (halign == HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == HorizontalAlignment.Right) { dx = -size.Width; } if (valign == VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == VerticalAlignment.Bottom) { dy = -size.Height; } } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform(dx, dy)); if (Math.Abs(rotate) > double.Epsilon) { transform.Children.Add(new RotateTransform(rotate)); } transform.Children.Add(new TranslateTransform(p.X, p.Y)); tb.RenderTransform = transform; if (tb.Clip != null) { tb.Clip.Transform = tb.RenderTransform.Inverse as Transform; } #if !NET35 tb.SetValue(RenderOptions.ClearTypeHintProperty, ClearTypeHint.Enabled); #endif }
/// <summary> /// Renders the Series on the specified rendering context. /// </summary> /// <param name="rc"> /// The rendering context. /// </param> /// <param name="model"> /// The model. /// </param> public override void Render(IRenderContext rc, PlotModel model) { this.ActualMinimumBarRectangles = new List<OxyRect>(); this.ActualMaximumBarRectangles = new List<OxyRect>(); if (this.ValidItems.Count == 0) { return; } var clippingRect = this.GetClippingRect(); var categoryAxis = this.GetCategoryAxis(); var actualBarWidth = this.GetActualBarWidth(); for (var i = 0; i < this.ValidItems.Count; i++) { var item = this.ValidItems[i]; var categoryIndex = item.GetCategoryIndex(i); var baseValue = double.IsNaN(item.BaseValue) ? this.BaseValue : item.BaseValue; var p0 = this.Transform(item.Minimum, categoryIndex - 0.5 + categoryAxis.BarOffset[categoryIndex]); var p1 = this.Transform( item.Maximum, categoryIndex - 0.5 + categoryAxis.BarOffset[categoryIndex] + actualBarWidth); var p2 = this.Transform(baseValue, categoryIndex - 0.5 + categoryAxis.BarOffset[categoryIndex]); p2.X = (int)p2.X; var minimumRectangle = OxyRect.Create(p0.X, p0.Y, p2.X, p1.Y); var maximumRectangle = OxyRect.Create(p2.X, p0.Y, p1.X, p1.Y); this.ActualMinimumBarRectangles.Add(minimumRectangle); this.ActualMaximumBarRectangles.Add(maximumRectangle); rc.DrawClippedRectangleAsPolygon( minimumRectangle, clippingRect, item.MinimumColor ?? this.ActualMinimumFillColor, this.StrokeColor, this.StrokeThickness); rc.DrawClippedRectangleAsPolygon( maximumRectangle, clippingRect, item.MaximumColor ?? this.ActualMaximumFillColor, this.StrokeColor, this.StrokeThickness); if (this.MinimumLabelFormatString != null) { var s = StringHelper.Format( this.ActualCulture, this.MinimumLabelFormatString, this.GetItem(this.ValidItemsIndexInversion[i]), item.Minimum); var pt = new ScreenPoint( minimumRectangle.Left - this.LabelMargin, (minimumRectangle.Top + minimumRectangle.Bottom) / 2); rc.DrawClippedText( clippingRect, pt, s, this.ActualTextColor, this.ActualFont, this.ActualFontSize, this.ActualFontWeight, 0, HorizontalAlignment.Right, VerticalAlignment.Middle); } if (this.MaximumLabelFormatString != null) { var s = StringHelper.Format( this.ActualCulture, this.MaximumLabelFormatString, this.GetItem(this.ValidItemsIndexInversion[i]), item.Maximum); var pt = new ScreenPoint( maximumRectangle.Right + this.LabelMargin, (maximumRectangle.Top + maximumRectangle.Bottom) / 2); rc.DrawClippedText( clippingRect, pt, s, this.ActualTextColor, this.ActualFont, this.ActualFontSize, this.ActualFontWeight, 0, HorizontalAlignment.Left, VerticalAlignment.Middle); } } }
/// <summary> /// Converts a <see cref="ScreenPoint" /> to a <see cref="Point" />. /// </summary> /// <param name="pt">The screen point.</param> /// <param name="aliased">use pixel alignment conversion if set to <c>true</c>.</param> /// <returns>A <see cref="Point" />.</returns> private Point ToPoint(ScreenPoint pt, bool aliased) { return(aliased ? this.ToPixelAlignedPoint(pt) : this.ToPoint(pt)); }
/// <summary> /// Converts a <see cref="ScreenPoint" /> to a <see cref="PointF" />. /// </summary> /// <param name="p">The point to convert.</param> /// <returns>The converted point.</returns> public static PointF Convert(this ScreenPoint p) { return(new PointF((float)p.X, (float)p.Y)); }
/// <summary> /// Converts a <see cref="ScreenPoint" /> to a <see cref="Point" />. /// </summary> /// <param name="pt">The screen point.</param> /// <returns>A <see cref="Point" />.</returns> private Point ToPoint(ScreenPoint pt) { return(new Point(pt.X, pt.Y)); }
public override void DrawText (ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalTextAlign halign, VerticalTextAlign valign, OxySize? maxSize) { //This method needs work not 100% around vertical alignment. if(string.IsNullOrEmpty(text)) { return; } fontFamily = GetDefaultFont(fontFamily); if (fontWeight >= 700) { //fs = FontStyle.Bold; } //var textSize = MeasureText(text, fontFamily, fontSize, fontWeight); if (maxSize != null) { // if (size.Width > maxSize.Value.Width) // { // size.Width = (float)maxSize.Value.Width; // } // // if (size.Height > maxSize.Value.Height) // { // size.Height = (float)maxSize.Value.Height; // } } gctx.SaveState(); gctx.SelectFont(fontFamily, (float)fontSize, CGTextEncoding.MacRoman); ToColor(fill).SetFill(); gctx.SetTextDrawingMode(CGTextDrawingMode.Fill); var tfont = UIFont.FromName (fontFamily,(float)fontSize); NSString nsstr = new NSString(text); SizeF sz = nsstr.StringSize(tfont); float y = (float)(p.Y); float x = (float)(p.X); switch(halign) { case HorizontalTextAlign.Left: x = (float)(p.X); break; case HorizontalTextAlign.Right: x = (float)(p.X - sz.Width); break; case HorizontalTextAlign.Center: x = (float)(p.X - (sz.Width / 2)); break; } switch(valign) { case VerticalTextAlign.Bottom: y -= (float)fontSize; break; case VerticalTextAlign.Top: // y += (float)fontSize; break; case VerticalTextAlign.Middle: y -= (float)(fontSize / 2); break; } RectangleF rect = new RectangleF(x,y,sz.Width,sz.Height); nsstr.DrawString( rect, tfont); gctx.RestoreState(); //Console.WriteLine("X:{0:###} Y:{1:###} HA:{2}:{3:###} VA:{4}:{5:###} TW:{6:###} - {7}", p.X, p.Y, halign, x, valign, y, textSize.Width, text); }
private static bool ShouldTrackerOpen(TrackerHitResult result, ScreenPoint point, double firesDistance) => result?.Position.DistanceTo(point) < firesDistance;
/// <summary> /// Renders the LineSeries on the specified rendering context. /// </summary> /// <param name="rc">The rendering context.</param> /// <param name="model">The owner plot model.</param> public override void Render(IRenderContext rc, PlotModel model) { if (this.ActualPoints.Count == 0) { return; } this.VerifyAxes(); double minDistSquared = this.MinimumSegmentLength * this.MinimumSegmentLength; var clippingRect = this.GetClippingRect(); // Transform all points to screen coordinates // Render the line when invalid points occur var dashArray = this.ActualDashArray; var actualColor = this.GetSelectableColor(this.ActualColor); var points = new ScreenPoint[2]; var markerPoints = this.MarkerType != MarkerType.None ? new List<ScreenPoint>(this.ActualPoints.Count) : null; foreach (var point in this.ActualPoints) { if (!this.IsValidPoint(point)) { continue; } points[0] = this.Transform(point.X, this.Base); points[1] = this.Transform(point.X, point.Y); if (this.StrokeThickness > 0 && this.ActualLineStyle != LineStyle.None) { rc.DrawClippedLine( clippingRect, points, minDistSquared, actualColor, this.StrokeThickness, dashArray, this.LineJoin, false); } if (markerPoints != null) { markerPoints.Add(points[1]); } } if (this.MarkerType != MarkerType.None) { rc.DrawMarkers( clippingRect, markerPoints, this.MarkerType, this.MarkerOutline, new[] { this.MarkerSize }, this.MarkerFill, this.MarkerStroke, this.MarkerStrokeThickness); } }
/// <summary> /// Update the position and border of the tracker. /// </summary> private void UpdatePositionAndBorder() { if (this.contentContainer == null) { return; } Canvas.SetLeft(this.contentContainer, this.Position.X); Canvas.SetTop(this.contentContainer, this.Position.Y); FrameworkElement parent = this; while (!(parent is Canvas) && parent != null) { parent = VisualTreeHelper.GetParent(parent) as FrameworkElement; } if (parent == null) { return; } // throw new InvalidOperationException("The TrackerControl must have a Canvas parent."); double canvasWidth = parent.ActualWidth; double canvasHeight = parent.ActualHeight; this.content.Measure(new Size(canvasWidth, canvasHeight)); this.content.Arrange(new Rect(0, 0, this.content.DesiredSize.Width, this.content.DesiredSize.Height)); double contentWidth = this.content.DesiredSize.Width; double contentHeight = this.content.DesiredSize.Height; // Minimum allowed margins around the tracker const double MarginLimit = 10; var ha = HorizontalAlignment.Center; if (this.CanCenterHorizontally) { if (this.Position.X - (contentWidth / 2) < MarginLimit) { ha = HorizontalAlignment.Left; } if (this.Position.X + (contentWidth / 2) > canvasWidth - MarginLimit) { ha = HorizontalAlignment.Right; } } else { ha = this.Position.X < canvasWidth / 2 ? HorizontalAlignment.Left : HorizontalAlignment.Right; } var va = VerticalAlignment.Center; if (this.CanCenterVertically) { if (this.Position.Y - (contentHeight / 2) < MarginLimit) { va = VerticalAlignment.Top; } if (ha == HorizontalAlignment.Center) { va = VerticalAlignment.Bottom; if (this.Position.Y - contentHeight < MarginLimit) { va = VerticalAlignment.Top; } } if (va == VerticalAlignment.Center && this.Position.Y + (contentHeight / 2) > canvasHeight - MarginLimit) { va = VerticalAlignment.Bottom; } if (va == VerticalAlignment.Top && this.Position.Y + contentHeight > canvasHeight - MarginLimit) { va = VerticalAlignment.Bottom; } } else { va = this.Position.Y < canvasHeight / 2 ? VerticalAlignment.Top : VerticalAlignment.Bottom; } double dx = ha == HorizontalAlignment.Center ? -0.5 : ha == HorizontalAlignment.Left ? 0 : -1; double dy = va == VerticalAlignment.Center ? -0.5 : va == VerticalAlignment.Top ? 0 : -1; Thickness margin; this.path.Data = this.ShowPointer ? this.CreatePointerBorderGeometry(ha, va, contentWidth, contentHeight, out margin) : this.CreateBorderGeometry(ha, va, contentWidth, contentHeight, out margin); this.content.Margin = margin; this.contentContainer.Measure(new Size(canvasWidth, canvasHeight)); Size contentSize = this.contentContainer.DesiredSize; this.contentContainer.RenderTransform = new TranslateTransform { X = dx * contentSize.Width, Y = dy * contentSize.Height }; #if WPF ScreenPoint pos = this.Position; #endif #if SILVERLIGHT || METRO Point pos = this.Position.ToPoint(true); #endif if (this.horizontalLine != null) { if (this.LineExtents.Width > 0) { this.horizontalLine.X1 = this.LineExtents.Left; this.horizontalLine.X2 = this.LineExtents.Right; } else { this.horizontalLine.X1 = 0; this.horizontalLine.X2 = canvasWidth; } this.horizontalLine.Y1 = pos.Y; this.horizontalLine.Y2 = pos.Y; } if (this.verticalLine != null) { if (this.LineExtents.Width > 0) { this.verticalLine.Y1 = this.LineExtents.Top; this.verticalLine.Y2 = this.LineExtents.Bottom; } else { this.verticalLine.Y1 = 0; this.verticalLine.Y2 = canvasHeight; } this.verticalLine.X1 = pos.X; this.verticalLine.X2 = pos.X; } }
/// <summary> /// Gets the point in the dataset that is nearest the specified point. /// </summary> /// <param name="point">The point.</param> /// <param name="interpolate">The interpolate.</param> /// <returns>A TrackerHitResult for the current hit.</returns> public override TrackerHitResult GetNearestPoint(ScreenPoint point, bool interpolate) { for (int i = 0; i < this.ActualBarRectangles.Count; i++) { var r = this.ActualBarRectangles[i]; if (r.Contains(point)) { var item = (IntervalBarItem)this.GetItem(this.ValidItemsIndexInversion[i]); var categoryIndex = item.GetCategoryIndex(i); double value = (this.ValidItems[i].Start + this.ValidItems[i].End) / 2; var dp = new DataPoint(categoryIndex, value); var text = this.Format( this.TrackerFormatString, item, this.Items[i].Start, this.Items[i].End, this.Items[i].Title); return new TrackerHitResult(this, dp, point, item, i, text); } } return null; }
/// <summary> /// Draws the text. /// </summary> /// <param name="p">The p.</param> /// <param name="text">The text.</param> /// <param name="c">The c.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotate.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">Size of the max.</param> public override void DrawText( ScreenPoint p, string text, OxyColor c, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalAlignment halign, VerticalAlignment valign, OxySize?maxSize) { if (string.IsNullOrEmpty(text)) { return; } var lines = Regex.Split(text, "\r\n"); var textSize = this.MeasureText(text, fontFamily, fontSize, fontWeight); var lineHeight = textSize.Height / lines.Length; var lineOffset = new ScreenVector(-Math.Sin(rotate / 180.0 * Math.PI) * lineHeight, +Math.Cos(rotate / 180.0 * Math.PI) * lineHeight); if (this.UseVerticalTextAlignmentWorkaround) { // offset the position, and set the valign to neutral value of `Bottom` double offsetRatio = valign == VerticalAlignment.Bottom ? (1.0 - lines.Length) : valign == VerticalAlignment.Top ? 1.0 : (1.0 - (lines.Length / 2.0)); valign = VerticalAlignment.Bottom; p += lineOffset * offsetRatio; foreach (var line in lines) { var size = this.MeasureText(line, fontFamily, fontSize, fontWeight); this.WriteText(p, line, c, fontFamily, fontSize, fontWeight, rotate, halign, valign); p += lineOffset; } } else { if (valign == VerticalAlignment.Bottom) { for (var i = lines.Length - 1; i >= 0; i--) { var line = lines[i]; _ = this.MeasureText(line, fontFamily, fontSize, fontWeight); this.WriteText(p, line, c, fontFamily, fontSize, fontWeight, rotate, halign, valign); p -= lineOffset; } } else { foreach (var line in lines) { var size = this.MeasureText(line, fontFamily, fontSize, fontWeight); this.WriteText(p, line, c, fontFamily, fontSize, fontWeight, rotate, halign, valign); p += lineOffset; } } } }
public void DrawText(ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalAlignment halign, VerticalTextAlign valign) { var tb = new TextBlock { Text = text, Foreground = new SolidColorBrush(fill.ToColor()) }; if (fontFamily != null) tb.FontFamily = new FontFamily(fontFamily); if (fontSize > 0) tb.FontSize = fontSize; if (fontWeight > 0) tb.FontWeight = FontWeight.FromOpenTypeWeight((int)fontWeight); tb.Measure(new Size(1000, 1000)); double dx = 0; if (halign == HorizontalAlignment.Center) dx = -tb.DesiredSize.Width / 2; if (halign == HorizontalAlignment.Right) dx = -tb.DesiredSize.Width; double dy = 0; if (valign == VerticalTextAlign.Middle) dy = -tb.DesiredSize.Height / 2; if (valign == VerticalTextAlign.Bottom) dy = -tb.DesiredSize.Height; var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform(dx, dy)); if (rotate != 0) transform.Children.Add(new RotateTransform(rotate)); transform.Children.Add(new TranslateTransform(p.X, p.Y)); tb.RenderTransform = transform; tb.SetValue(RenderOptions.ClearTypeHintProperty, ClearTypeHint.Enabled); Add(tb); }
/// <summary> /// Writes text. /// </summary> /// <param name="position">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The text color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">The font size (in user units).</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> public void WriteText( ScreenPoint position, string text, OxyColor fill, string fontFamily = null, double fontSize = 10, double fontWeight = FontWeights.Normal, double rotate = 0, HorizontalAlignment halign = HorizontalAlignment.Left, VerticalAlignment valign = VerticalAlignment.Top) { // http://www.w3.org/TR/SVG/text.html this.WriteStartElement("text"); // WriteAttributeString("x", position.X); // WriteAttributeString("y", position.Y); string baselineAlignment = "hanging"; if (valign == VerticalAlignment.Middle) { baselineAlignment = "middle"; } if (valign == VerticalAlignment.Bottom) { baselineAlignment = "baseline"; } this.WriteAttributeString("dominant-baseline", baselineAlignment); string textAnchor = "start"; if (halign == HorizontalAlignment.Center) { textAnchor = "middle"; } if (halign == HorizontalAlignment.Right) { textAnchor = "end"; } this.WriteAttributeString("text-anchor", textAnchor); string fmt = "translate({0:" + this.NumberFormat + "},{1:" + this.NumberFormat + "})"; string transform = string.Format(CultureInfo.InvariantCulture, fmt, position.X, position.Y); if (Math.Abs(rotate) > 0) { transform += string.Format(CultureInfo.InvariantCulture, " rotate({0})", rotate); } this.WriteAttributeString("transform", transform); if (fontFamily != null) { this.WriteAttributeString("font-family", fontFamily); } if (fontSize > 0) { this.WriteAttributeString("font-size", fontSize); } if (fontWeight > 0) { this.WriteAttributeString("font-weight", fontWeight); } if (fill.IsInvisible()) { this.WriteAttributeString("fill", "none"); } else { this.WriteAttributeString("fill", this.ColorToString(fill)); if (fill.A != 0xFF) { this.WriteAttributeString("fill-opacity", fill.A / 255.0); } } this.WriteClipPathAttribute(); // WriteAttributeString("style", style); this.WriteString(text); this.WriteEndElement(); }
/// <summary> /// Initializes a new instance of the <see cref="ManipulationEventArgs"/> class. /// </summary> /// <param name="currentPosition"> /// The current position. /// </param> public ManipulationEventArgs(ScreenPoint currentPosition) { this.CurrentPosition = currentPosition; }
/// <summary> /// Renders the point labels. /// </summary> /// <param name="rc">The render context.</param> /// <param name="clippingRect">The clipping rectangle.</param> protected void RenderPointLabels(IRenderContext rc, OxyRect clippingRect) { var actualPoints = this.ActualPointsList; if (actualPoints == null || actualPoints.Count == 0) { return; } // TODO: share code with LineSeries int index = -1; foreach (var point in actualPoints) { index++; var dataPoint = new DataPoint(point.X, point.Y); if (!this.IsValidPoint(dataPoint)) { continue; } var pt = this.Transform(dataPoint) + new ScreenVector(0, -this.LabelMargin); if (!clippingRect.Contains(pt)) { continue; } var item = this.GetItem(index); var s = StringHelper.Format(this.ActualCulture, this.LabelFormatString, item, point.X, point.Y); #if SUPPORTLABELPLACEMENT switch (this.LabelPlacement) { case LabelPlacement.Inside: pt = new ScreenPoint(rect.Right - this.LabelMargin, (rect.Top + rect.Bottom) / 2); ha = HorizontalAlignment.Right; break; case LabelPlacement.Middle: pt = new ScreenPoint((rect.Left + rect.Right) / 2, (rect.Top + rect.Bottom) / 2); ha = HorizontalAlignment.Center; break; case LabelPlacement.Base: pt = new ScreenPoint(rect.Left + this.LabelMargin, (rect.Top + rect.Bottom) / 2); ha = HorizontalAlignment.Left; break; default: // Outside pt = new ScreenPoint(rect.Right + this.LabelMargin, (rect.Top + rect.Bottom) / 2); ha = HorizontalAlignment.Left; break; } #endif rc.DrawClippedText( clippingRect, pt, s, this.ActualTextColor, this.ActualFont, this.ActualFontSize, this.ActualFontWeight, 0, HorizontalAlignment.Center, VerticalAlignment.Bottom); } }