public override IChartInteractiveObject LoadObject(XmlElement objectNode, CandleChartControl owner, bool trimObjectsOutOfHistory = false) { var obj = new ChartEllipse(); obj.LoadFromXML(objectNode, owner); obj.Owner = this; data.Add(obj); return(obj); }
protected override void OnMouseDown(List <SeriesEditParameter> parameters, MouseEventArgs e, Keys modifierKeys, out IChartInteractiveObject objectToEdit) { objectToEdit = null; if (e.Button != MouseButtons.Left) { return; } // получить время и цену var pointD = Chart.Owner.MouseToWorldCoords(e.X, e.Y); var editedEllipse = data.FirstOrDefault(el => el.IsBeingCreated); var shiftPressed = (Control.ModifierKeys & Keys.Shift) == Keys.Shift; var controlPressed = (Control.ModifierKeys & Keys.Control) == Keys.Control; if (editedEllipse == null) {// начинается редактирование - выбрана первая точка var lineColor = SeriesEditParameter.TryGetParamValue(parameters, "Stroke", Color.Black); var buildAuto = SeriesEditParameter.TryGetParamValue(parameters, "ByTwoPoints", false) ^ controlPressed; var buildTangent = SeriesEditParameter.TryGetParamValue(parameters, "Tangent", false) ^ shiftPressed; var tangentType = SeriesEditParameter.TryGetParamValue(parameters, "TangentView", ChartEllipse.EllipseTangentType.Отрезок); data.Add(new ChartEllipse { Owner = this, Color = lineColor, BuildTangent = buildTangent, TangentType = tangentType, buildAuto = buildAuto }); editedEllipse = data[data.Count - 1]; editedEllipse.IsBeingCreated = true; if (Owner.Owner.Owner.AdjustObjectColorsOnCreation) { editedEllipse.AjustColorScheme(Owner.Owner.Owner); } } // добавить точку в эллипс editedEllipse.points.Add(pointD.ToPointF()); // ... или сразу две if (editedEllipse.points.Count == 1) { editedEllipse.points.Add(pointD.ToPointF()); } ellipseBeingSized = editedEllipse; }
protected override bool OnMouseUp(List <SeriesEditParameter> parameters, MouseEventArgs e, Keys modifierKeys, out IChartInteractiveObject objectToEdit) { objectToEdit = null; if (ellipseBeingSized == null) { return(false); } // полуось эллипса не выродилась в точку? var lenPx = Conversion.GetSpanLenInScreenCoords(ellipseBeingSized.points[0], ellipseBeingSized.points[1], Chart.StockPane.WorldRect, Chart.StockPane.CanvasRect); if (lenPx < 3) { data.Remove(ellipseBeingSized); ellipseBeingSized = null; return(true); } ellipseBeingSized.buildAuto = false; // если в эллипсе все три точки - завершить редактирование if (ellipseBeingSized.points.Count == 3) { // проставить время - по первой точке var minIndex = ellipseBeingSized.points.Min(p => p.X); ellipseBeingSized.DateStart = Chart.StockSeries.GetCandleOpenTimeByIndex((int)minIndex); ellipseBeingSized.IsBeingCreated = false; objectToEdit = ellipseBeingSized; } // иначе - просто завершить режим "резинки" до след. нажатия ellipseBeingSized = null; return(true); }
/// <summary> /// построить эллипс по двум точкам так, чтобы он опоясывал тени свечей в своих пределах /// </summary> private bool BuildEllipseAuto(ChartEllipse editedEllipse) { if (editedEllipse.points[0].X == editedEllipse.points[1].X) { return(false); // эллипс вырожден } if (Owner.CanvasRect.Width == 0 || Owner.CanvasRect.Height == 0 || Owner.WorldRect.Width == 0 || Owner.WorldRect.Height == 0) { return(false); } // если точки эллипса следуют задом наперед - поменять их местами if (editedEllipse.points[0].X > editedEllipse.points[1].X) { var pt = editedEllipse.points[1]; editedEllipse.points[1] = editedEllipse.points[0]; editedEllipse.points[0] = pt; } // координаты в масштабе экрана PointF a = editedEllipse.points[0], b = editedEllipse.points[1]; PointF aScale = Conversion.WorldToScreen(new PointD(a.X, a.Y), Owner.WorldRect, Owner.CanvasRect).ToPointF(); PointF bScale = Conversion.WorldToScreen(new PointD(b.X, b.Y), Owner.WorldRect, Owner.CanvasRect).ToPointF(); var candles = Chart.StockSeries.Data.Candles; var start = Math.Max((int)a.X + 1, 0); var end = Math.Min((int)b.X - 1, candles.Count - 1); if (start >= end) { return(false); } // по каждой свече - эллипс должен охватывать оную Cortege2 <PointF, float>?maxEllipsePtrs = null; for (var i = start; i <= end; i++) { // кончик свечки (хай или лоу) PointF candleTip = Conversion.WorldToScreen(new PointD(i, (double)candles[i].high), Owner.WorldRect, Owner.CanvasRect).ToPointF(); var ellipsePtrs = TryMakeChartEllipse(aScale, bScale, candleTip, true); if (!maxEllipsePtrs.HasValue && ellipsePtrs.HasValue) { maxEllipsePtrs = ellipsePtrs; } else { if (ellipsePtrs.HasValue) { if (ellipsePtrs.Value.b > maxEllipsePtrs.Value.b) { maxEllipsePtrs = ellipsePtrs; } } } // тупой копипаст для лоу candleTip = Conversion.WorldToScreen(new PointD(i, (double)candles[i].low), Owner.WorldRect, Owner.CanvasRect).ToPointF(); ellipsePtrs = TryMakeChartEllipse(aScale, bScale, candleTip, true); if (!maxEllipsePtrs.HasValue && ellipsePtrs.HasValue) { maxEllipsePtrs = ellipsePtrs; } else { if (ellipsePtrs.HasValue) { if (ellipsePtrs.Value.b > maxEllipsePtrs.Value.b) { maxEllipsePtrs = ellipsePtrs; } } } } // если описывающий эллипс существует if (maxEllipsePtrs.HasValue) { var pt = Conversion.ScreenToWorld(new PointD(maxEllipsePtrs.Value.a.X, maxEllipsePtrs.Value.a.Y), Owner.WorldRect, Owner.CanvasRect).ToPointF(); if (editedEllipse.points.Count == 2) { editedEllipse.points.Add(pt); } else { editedEllipse.points[2] = pt; } } else { if (editedEllipse.points.Count == 3) { editedEllipse.points.RemoveAt(editedEllipse.points.Count - 1); } } return(true); }
/// <summary> /// построить эллипс по двум точкам так, чтобы он опоясывал тени свечей в своих пределах /// </summary> private bool BuildEllipseAuto(ChartEllipse editedEllipse) { if (editedEllipse.points[0].X == editedEllipse.points[1].X) return false; // эллипс вырожден if (Owner.CanvasRect.Width == 0 || Owner.CanvasRect.Height == 0 || Owner.WorldRect.Width == 0 || Owner.WorldRect.Height == 0) return false; // если точки эллипса следуют задом наперед - поменять их местами if (editedEllipse.points[0].X > editedEllipse.points[1].X) { var pt = editedEllipse.points[1]; editedEllipse.points[1] = editedEllipse.points[0]; editedEllipse.points[0] = pt; } // координаты в масштабе экрана PointF a = editedEllipse.points[0], b = editedEllipse.points[1]; PointF aScale = Conversion.WorldToScreen(new PointD(a.X, a.Y), Owner.WorldRect, Owner.CanvasRect).ToPointF(); PointF bScale = Conversion.WorldToScreen(new PointD(b.X, b.Y), Owner.WorldRect, Owner.CanvasRect).ToPointF(); var candles = Chart.StockSeries.Data.Candles; var start = Math.Max((int) a.X + 1, 0); var end = Math.Min((int) b.X - 1, candles.Count - 1); if (start >= end) return false; // по каждой свече - эллипс должен охватывать оную Cortege2<PointF, float>? maxEllipsePtrs = null; for (var i = start; i <= end; i++) { // кончик свечки (хай или лоу) PointF candleTip = Conversion.WorldToScreen(new PointD(i, (double)candles[i].high), Owner.WorldRect, Owner.CanvasRect).ToPointF(); var ellipsePtrs = TryMakeChartEllipse(aScale, bScale, candleTip, true); if (!maxEllipsePtrs.HasValue && ellipsePtrs.HasValue) maxEllipsePtrs = ellipsePtrs; else { if (ellipsePtrs.HasValue) if (ellipsePtrs.Value.b > maxEllipsePtrs.Value.b) maxEllipsePtrs = ellipsePtrs; } // тупой копипаст для лоу candleTip = Conversion.WorldToScreen(new PointD(i, (double)candles[i].low), Owner.WorldRect, Owner.CanvasRect).ToPointF(); ellipsePtrs = TryMakeChartEllipse(aScale, bScale, candleTip, true); if (!maxEllipsePtrs.HasValue && ellipsePtrs.HasValue) maxEllipsePtrs = ellipsePtrs; else { if (ellipsePtrs.HasValue) if (ellipsePtrs.Value.b > maxEllipsePtrs.Value.b) maxEllipsePtrs = ellipsePtrs; } } // если описывающий эллипс существует if (maxEllipsePtrs.HasValue) { var pt = Conversion.ScreenToWorld(new PointD(maxEllipsePtrs.Value.a.X, maxEllipsePtrs.Value.a.Y), Owner.WorldRect, Owner.CanvasRect).ToPointF(); if (editedEllipse.points.Count == 2) editedEllipse.points.Add(pt); else editedEllipse.points[2] = pt; } else { if (editedEllipse.points.Count == 3) editedEllipse.points.RemoveAt(editedEllipse.points.Count - 1); } return true; }
protected override bool OnMouseUp(List<SeriesEditParameter> parameters, MouseEventArgs e, Keys modifierKeys, out IChartInteractiveObject objectToEdit) { objectToEdit = null; if (ellipseBeingSized == null) return false; // полуось эллипса не выродилась в точку? var lenPx = Conversion.GetSpanLenInScreenCoords(ellipseBeingSized.points[0], ellipseBeingSized.points[1], Chart.StockPane.WorldRect, Chart.StockPane.CanvasRect); if (lenPx < 3) { data.Remove(ellipseBeingSized); ellipseBeingSized = null; return true; } ellipseBeingSized.buildAuto = false; // если в эллипсе все три точки - завершить редактирование if (ellipseBeingSized.points.Count == 3) { // проставить время - по первой точке var minIndex = ellipseBeingSized.points.Min(p => p.X); ellipseBeingSized.DateStart = Chart.StockSeries.GetCandleOpenTimeByIndex((int)minIndex); ellipseBeingSized.IsBeingCreated = false; objectToEdit = ellipseBeingSized; } // иначе - просто завершить режим "резинки" до след. нажатия ellipseBeingSized = null; return true; }
protected override void OnMouseDown(List<SeriesEditParameter> parameters, MouseEventArgs e, Keys modifierKeys, out IChartInteractiveObject objectToEdit) { objectToEdit = null; if (e.Button != MouseButtons.Left) return; // получить время и цену var pointD = Chart.Owner.MouseToWorldCoords(e.X, e.Y); var editedEllipse = data.FirstOrDefault(el => el.IsBeingCreated); var shiftPressed = (Control.ModifierKeys & Keys.Shift) == Keys.Shift; var controlPressed = (Control.ModifierKeys & Keys.Control) == Keys.Control; if (editedEllipse == null) {// начинается редактирование - выбрана первая точка var lineColor = SeriesEditParameter.TryGetParamValue(parameters, "Stroke", Color.Black); var buildAuto = SeriesEditParameter.TryGetParamValue(parameters, "ByTwoPoints", false) ^ controlPressed; var buildTangent = SeriesEditParameter.TryGetParamValue(parameters, "Tangent", false) ^ shiftPressed; var tangentType = SeriesEditParameter.TryGetParamValue(parameters, "TangentView", ChartEllipse.EllipseTangentType.Отрезок); data.Add(new ChartEllipse { Owner = this, Color = lineColor, BuildTangent = buildTangent, TangentType = tangentType, buildAuto = buildAuto }); editedEllipse = data[data.Count - 1]; editedEllipse.IsBeingCreated = true; if (Owner.Owner.Owner.AdjustObjectColorsOnCreation) editedEllipse.AjustColorScheme(Owner.Owner.Owner); } // добавить точку в эллипс editedEllipse.points.Add(pointD.ToPointF()); // ... или сразу две if (editedEllipse.points.Count == 1) editedEllipse.points.Add(pointD.ToPointF()); ellipseBeingSized = editedEllipse; }
public override IChartInteractiveObject LoadObject(XmlElement objectNode, CandleChartControl owner, bool trimObjectsOutOfHistory = false) { var obj = new ChartEllipse(); obj.LoadFromXML(objectNode, owner); obj.Owner = this; data.Add(obj); return obj; }
/// <summary> /// Получить описывающий визуальный /// </summary> /// <param name="candles"></param> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> private ChartEllipse BuildVisualInclusiveEllipse(StockSeriesData candles, int start, int end) { if (start == end) return null; float startvalue, endvalue; if (candles[start].high > candles[end].high) { startvalue = candles[start].high; endvalue = candles[end].low; } else { startvalue = candles[start].low; endvalue = candles[end].high; } var A = Conversion.WorldToScreen(new PointD(start, Convert.ToDouble(startvalue)), worldRect, canvasRect).ToPointF(); var B = Conversion.WorldToScreen(new PointD(end, Convert.ToDouble(endvalue)), worldRect, canvasRect).ToPointF(); var C = new PointF(); double angle; float cx, cy, a, b; var S = float.NaN; var correctEllipse = false; // поиск охватывающего эллипса for (var i = start; i <= end; i++) { var d = Conversion.WorldToScreen(new PointD(i, Convert.ToDouble(candles[i].high)), worldRect, canvasRect).ToPointF(); correctEllipse = Geometry.GetEllipseParams(A, B, d, out angle, out a, out b, out cx, out cy); if (float.IsNaN(S) || (correctEllipse && S < b)) { S = b; C = d; } d = Conversion.WorldToScreen(new PointD(i, Convert.ToDouble(candles[i].low)), worldRect, canvasRect).ToPointF(); correctEllipse = Geometry.GetEllipseParams(A, B, d, out angle, out a, out b, out cx, out cy); if (float.IsNaN(S) || (correctEllipse && S < b)) { S = b; C = d; } } correctEllipse = // пересчитываем параметры эллипса Geometry.GetEllipseParams(A, B, C, out angle, out a, out b, out cx, out cy); if (correctEllipse) { // можно построить эллипс - рисуем его var newEllipse = new ChartEllipse { BuildTangent = true, angle = angle, a = a, b = b, cx = cx, cy = cy }; newEllipse.points.Add(Conversion.ScreenToWorld(new PointD(A.X, A.Y), worldRect, canvasRect).ToPointF()); newEllipse.points.Add(Conversion.ScreenToWorld(new PointD(B.X, B.Y), worldRect, canvasRect).ToPointF()); newEllipse.points.Add(Conversion.ScreenToWorld(new PointD(C.X, C.Y), worldRect, canvasRect).ToPointF()); var minIndex = newEllipse.points.Min(p => p.X); newEllipse.DateStart = owner.StockSeries.GetCandleOpenTimeByIndex((int)minIndex); return newEllipse; } return null; }