internal static PointF WorldToScreenF(PointD worldPt, RectangleD worldRect, RectangleD screenRect) { if ((Math.Abs(worldRect.Width) <= double.Epsilon) || (Math.Abs(worldRect.Height) <= double.Epsilon)) { return worldPt.ToPointF(); } if (double.IsNegativeInfinity(worldPt.Y)) worldPt.Y = worldRect.Bottom - 1; else if (double.IsInfinity(worldPt.Y)) worldPt.Y = worldRect.Top + 1; var td = new PointF { X = (float)((((worldPt.X - worldRect.Left) / worldRect.Width) * screenRect.Width) + screenRect.Left), Y = (float) ((screenRect.Height - (((worldPt.Y - worldRect.Top) / worldRect.Height) * screenRect.Height)) + screenRect.Top) }; const float maxDimx = 1048576f; if (td.X > maxDimx) td.X = maxDimx; if (td.X < -maxDimx) td.X = -maxDimx; if (td.Y > maxDimx) td.Y = maxDimx; if (td.Y < -maxDimx) td.Y = -maxDimx; return td; }
/// <summary> /// вернуть массив точек стрелочки в точку e /// </summary> private PointF[] GetArrowPoints(PointD b, PointD e) { const double arrowA = Math.PI/8; const int arrowL = 8; //double spanAngle = Math.Atan2(e.Y - b.Y, e.X - b.X); var spanLen = Geometry.GetSpanLength(b, e); if (spanLen == 0) return new PointF[0]; var c = e + (b - e)*(arrowL/spanLen); var c1 = Geometry.RotatePoint(c, e, -arrowA); var c2 = Geometry.RotatePoint(c, e, arrowA); return new[] { e.ToPointF(), c1.ToPointF(), c2.ToPointF() }; }
protected bool IsInObject(PointD a, PointD b, VectorGraphObject obj, Point ptClient, float tolerance) { var len = (float)Geometry.GetSpanLength(a, b); VectorGraphObject smb = obj.Copy(); float scale = len / smb.Width; // масштабирование smb.Scale(scale, scale); // перенос smb.Move2Point(a.ToPointF()); // наклон smb.Rotate((float)Math.Atan2(b.Y - a.Y, b.X - a.X)); // проверить попадание return smb.IsPointIn(ptClient, tolerance); }
private void DrawTangent(List<PointD> screenPoints, Rectangle canvasRect, Graphics g, PenStorage penStorage, BrushesStorage brushStorage, Font font) { var ptLeft = points[0].X < points[1].X ? points[0] : points[1]; var ptRight = points[0].X < points[1].X ? points[1] : points[0]; var m1 = new PointD(cx + b * Math.Sin(angle), cy + b * Math.Cos(angle)); var m2 = new PointD(cx + b * Math.Sin(angle + Math.PI), cy + b * Math.Cos(angle + Math.PI)); var m = ptLeft.Y > ptRight.Y ? m1.Y < m2.Y ? m1 : m2 // нижняя касательная для растущего эллипса : m1.Y < m2.Y ? m2 : m1; // верхняя для падающего var o = new PointD(cx, cy); var r = new PointD(m.X - o.X, m.Y - o.Y); var pen = penStorage.GetPen(TangentColor); foreach (var level in tangentFiboLevels) { // нарисовать касательную или параллельную ей линию var A = new PointD(screenPoints[0].X + r.X * (level + 1), screenPoints[0].Y + r.Y * (level + 1)); var B = new PointD(screenPoints[1].X + r.X * (level + 1), screenPoints[1].Y + r.Y * (level + 1)); if (TangentType == EllipseTangentType.Прямая) StretchSpanToScreen(ref A, ref B, canvasRect); g.DrawLine(pen, A.ToPointF(), B.ToPointF()); if (level == 0) continue; // нарисовать текстовую отметку var ptText = new PointD(o.X + r.X * (level + 1), o.Y + r.Y * (level + 1)); var textSz = g.MeasureString(level.ToString(), font); var textRect = new Rectangle((int) (ptText.X - textSz.Width / 2 - 2), (int) (ptText.Y - textSz.Height / 2 - 2), (int) textSz.Width + 4, (int) textSz.Height + 4); var brushWhite = brushStorage.GetBrush(Color.FromArgb(60, pen.Color)); g.FillRectangle(brushWhite, textRect); g.DrawRectangle(pen, textRect); var brushText = brushStorage.GetBrush(pen.Color); g.DrawString(level.ToString(), font, brushText, (float) ptText.X, (float) ptText.Y, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); } }
/// <summary> /// Получить описывающий /// </summary> /// <param name="candles"></param> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> private ChartEllipse BuildInclusiveEllipse(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 = new PointD(start, Convert.ToDouble(startvalue)); var B = new PointD(end, Convert.ToDouble(endvalue)); var C = new PointD(); double angle; float cx, cy, a, b; var S = float.NaN; bool correctEllipse = false; // поиск охватывающего эллипса for (var i = start; i <= end; i++) { var d = new PointD(i, Convert.ToDouble(candles[i].high)); correctEllipse = Geometry.GetEllipseParams(A.ToPointF(), B.ToPointF(), d.ToPointF(), out angle, out a, out b, out cx, out cy); if (float.IsNaN(S) || (correctEllipse && S < b)) { S = b; C = d; } d = new PointD(i, Convert.ToDouble(candles[i].low)); correctEllipse = Geometry.GetEllipseParams(A.ToPointF(), B.ToPointF(), d.ToPointF(), 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.ToPointF(), B.ToPointF(), C.ToPointF(), 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.AddPoint((float)A.X, (float)A.Y); newEllipse.AddPoint((float)B.X, (float)B.Y); newEllipse.AddPoint((float)C.X, (float)C.Y); var minIndex = newEllipse.points.Min(p => p.X); newEllipse.DateStart = owner.StockSeries.GetCandleOpenTimeByIndex((int)minIndex); return newEllipse; } return null; }