private SharpDX.Direct2D1.PathGeometry CreatePolygonGeometry(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, double pixelAdjust) { List <SharpDX.Vector2> vectors = new List <SharpDX.Vector2>(); Vector pixelAdjustVec = new Vector(pixelAdjust, pixelAdjust); for (int i = 0; i < ChartAnchors.Count; i++) { Point p = ChartAnchors[i].GetPoint(chartControl, chartPanel, chartScale); vectors.Add((p + pixelAdjustVec).ToVector2()); if (i + 1 < ChartAnchors.Count) { Point p2 = ChartAnchors[i + 1].GetPoint(chartControl, chartPanel, chartScale); vectors.Add((p2 + pixelAdjustVec).ToVector2()); } else if (DrawingState != DrawingState.Building) { vectors.Add(vectors[0]); } } SharpDX.Direct2D1.PathGeometry pathGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink geometrySink = pathGeometry.Open(); geometrySink.BeginFigure(vectors[0], SharpDX.Direct2D1.FigureBegin.Filled); geometrySink.AddLines(vectors.ToArray()); geometrySink.EndFigure(SharpDX.Direct2D1.FigureEnd.Open); geometrySink.Close(); // calls dispose for you return(pathGeometry); }
public void DrawPolygon(DUIPen pen, PointF[] points) { bool closed = true; if (points == null) { return; } if (points.Length < (closed ? 3 : 2)) { return; } pen.RenderTarget = this.target; if (pen.IsDefaultStyleProperties) { using (SharpDX.Direct2D1.PathGeometry pathGeometry = new SharpDX.Direct2D1.PathGeometry(this.target.RenderTarget.Factory)) using (SharpDX.Direct2D1.GeometrySink geometrySink = pathGeometry.Open()) { geometrySink.BeginFigure(DxConvert.ToVector2(points[0]), SharpDX.Direct2D1.FigureBegin.Filled); for (int i = 1; i < points.Length; i++) { geometrySink.AddLine(DxConvert.ToVector2(points[i])); } geometrySink.EndFigure(closed ? SharpDX.Direct2D1.FigureEnd.Closed : SharpDX.Direct2D1.FigureEnd.Open); geometrySink.Close(); this.target.RenderTarget.DrawGeometry(pathGeometry, pen, pen.Width); } } else { using (SharpDX.Direct2D1.PathGeometry pathGeometry = new SharpDX.Direct2D1.PathGeometry(this.target.RenderTarget.Factory)) using (SharpDX.Direct2D1.GeometrySink geometrySink = pathGeometry.Open()) { geometrySink.BeginFigure(DxConvert.ToVector2(points[0]), SharpDX.Direct2D1.FigureBegin.Filled); for (int i = 1; i < points.Length; i++) { geometrySink.AddLine(DxConvert.ToVector2(points[i])); } geometrySink.EndFigure(closed ? SharpDX.Direct2D1.FigureEnd.Closed : SharpDX.Direct2D1.FigureEnd.Open); geometrySink.Close(); this.target.RenderTarget.DrawGeometry(pathGeometry, pen, pen.Width, pen); } } }
public void DrawImage(DUIImage image, PointF[] polygon, GraphicsUnit srcUnit, float opacity) { image.RenderTarget = this.target; using (DirectUI.Common.DUIBitmapBrush dbs = new DirectUI.Common.DUIBitmapBrush(image, DUIExtendMode.Clamp, opacity)) using (SharpDX.Direct2D1.PathGeometry pathGeometry = new SharpDX.Direct2D1.PathGeometry(this.target.RenderTarget.Factory)) using (SharpDX.Direct2D1.GeometrySink gs1 = pathGeometry.Open()) { dbs.RenderTarget = this.target; gs1.SetFillMode(SharpDX.Direct2D1.FillMode.Alternate); gs1.BeginFigure(DxConvert.ToVector2(polygon[0]), SharpDX.Direct2D1.FigureBegin.Filled); for (int i = 1; i < polygon.Length; i++) { gs1.AddLine(DxConvert.ToVector2(polygon[i])); } gs1.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); gs1.Close(); this.target.RenderTarget.FillGeometry(pathGeometry, dbs); } }
private void DrawFigure(SharpDXFigure figure) { SharpDX.Direct2D1.PathGeometry geometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink sink = geometry.Open(); sink.BeginFigure(figure.Points[0], new SharpDX.Direct2D1.FigureBegin()); for (int i = 0; i < figure.Points.Length; i++) { sink.AddLine(figure.Points[i]); } sink.AddLine(figure.Points[0]); sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); sink.Close(); RenderTarget.FillGeometry(geometry, dxmBrushes[figure.Color].DxBrush); geometry.Dispose(); sink.Dispose(); }
public void DrawImage(DUIImage image, PointF[] destTriangle, PointF[] srcTriangle, GraphicsUnit srcUnit, float opacity) { PointF t1 = destTriangle[0]; PointF t2 = destTriangle[1]; PointF t3 = destTriangle[2]; image.RenderTarget = this.target; using (DirectUI.Common.DUIBitmapBrush dbs = new DirectUI.Common.DUIBitmapBrush(image, DUIExtendMode.Clamp, opacity)) using (SharpDX.Direct2D1.PathGeometry pathGeometry = new SharpDX.Direct2D1.PathGeometry(this.target.RenderTarget.Factory)) using (SharpDX.Direct2D1.GeometrySink gs1 = pathGeometry.Open()) { dbs.RenderTarget = this.target; gs1.SetFillMode(SharpDX.Direct2D1.FillMode.Alternate); gs1.BeginFigure(DxConvert.ToVector2(t1), SharpDX.Direct2D1.FigureBegin.Filled); gs1.AddLine(DxConvert.ToVector2(t2)); gs1.AddLine(DxConvert.ToVector2(t3)); gs1.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); gs1.Close(); dbs.Transform = MatrixTools.ThreePointsAffine(srcTriangle, destTriangle); this.target.RenderTarget.FillGeometry(pathGeometry, dbs); } }
public void DrawPathGeometrySink(List <System.Drawing.Point> Points, System.Drawing.Color LineColor, float LineWidth, System.Drawing.Drawing2D.DashStyle dashStyle, bool CloseGeometry = false) { SharpDX.Direct2D1.PathGeometry pg = new SharpDX.Direct2D1.PathGeometry(D2Drender.Factory); SharpDX.Direct2D1.GeometrySink sink = pg.Open(); for (int i = 0; i < Points.Count; i++) { if (i == 0) { sink.BeginFigure(utils.Point2Raw(Points[0]), SharpDX.Direct2D1.FigureBegin.Hollow); } else { sink.AddLine(utils.Point2Raw(Points[i])); } } if (Points.Count > 0) { sink.EndFigure(CloseGeometry?SharpDX.Direct2D1.FigureEnd.Closed:SharpDX.Direct2D1.FigureEnd.Open); } sink.Close(); SharpDX.Direct2D1.StrokeStyleProperties ssProps = new SharpDX.Direct2D1.StrokeStyleProperties(); ssProps.StartCap = SharpDX.Direct2D1.CapStyle.Flat; ssProps.EndCap = SharpDX.Direct2D1.CapStyle.Flat; ssProps.DashOffset = 0.1f; switch (dashStyle) { case System.Drawing.Drawing2D.DashStyle.Dash: ssProps.DashStyle = SharpDX.Direct2D1.DashStyle.Dash; break; case System.Drawing.Drawing2D.DashStyle.DashDot: ssProps.DashStyle = SharpDX.Direct2D1.DashStyle.DashDot; break; case System.Drawing.Drawing2D.DashStyle.DashDotDot: ssProps.DashStyle = SharpDX.Direct2D1.DashStyle.DashDotDot; break; case System.Drawing.Drawing2D.DashStyle.Dot: ssProps.DashStyle = SharpDX.Direct2D1.DashStyle.Dot; break; case System.Drawing.Drawing2D.DashStyle.Solid: ssProps.DashStyle = SharpDX.Direct2D1.DashStyle.Solid; break; } SharpDX.Direct2D1.StrokeStyle LineStyle = new SharpDX.Direct2D1.StrokeStyle(D2Drender.Factory, ssProps); D2Drender.DrawGeometry(pg, utils.SoildBrush2Raw(LineColor), LineWidth, LineStyle); }
private void UpdateArcGeometry(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale) { Point startPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point endPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); if (arcGeometry != null && startPoint == cachedStartPoint && endPoint == cachedEndPoint) { return; } cachedEndPoint = endPoint; cachedStartPoint = startPoint; if (arcGeometry != null && !arcGeometry.IsDisposed) { arcGeometry.Dispose(); } Vector lineVec = endPoint - startPoint; float width = Math.Abs((float)lineVec.X); float height = Math.Abs((float)lineVec.Y); SharpDX.Direct2D1.ArcSegment arcSegment = new SharpDX.Direct2D1.ArcSegment { ArcSize = SharpDX.Direct2D1.ArcSize.Small, Point = new SharpDX.Vector2((float)endPoint.X, (float)endPoint.Y), SweepDirection = SharpDX.Direct2D1.SweepDirection.CounterClockwise, Size = new SharpDX.Size2F(width, height) }; // Create the arc between the line two end points arcGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink geometrySink = arcGeometry.Open(); geometrySink.BeginFigure(new SharpDX.Vector2((float)startPoint.X, (float)startPoint.Y), SharpDX.Direct2D1.FigureBegin.Filled); geometrySink.AddArc(arcSegment); geometrySink.EndFigure(SharpDX.Direct2D1.FigureEnd.Open); geometrySink.Close(); }
public void DrawPathGeometrySink(List <System.Drawing.Point> Points, System.Drawing.Color LineColor, float LineWidth, bool CloseGeometry = false) { SharpDX.Direct2D1.PathGeometry pg = new SharpDX.Direct2D1.PathGeometry(D2Drender.Factory); SharpDX.Direct2D1.GeometrySink sink = pg.Open(); for (int i = 0; i < Points.Count; i++) { if (i == 0) { sink.BeginFigure(utils.Point2Raw(Points[0]), SharpDX.Direct2D1.FigureBegin.Hollow); } else { sink.AddLine(utils.Point2Raw(Points[i])); } } if (Points.Count > 0) { sink.EndFigure(CloseGeometry ? SharpDX.Direct2D1.FigureEnd.Closed : SharpDX.Direct2D1.FigureEnd.Open); } sink.Close(); D2Drender.DrawGeometry(pg, utils.SoildBrush2Raw(LineColor), LineWidth); }
public void FillPathGeometrySink(List <System.Drawing.Point> Points, System.Drawing.Color FillColor) { SharpDX.Direct2D1.PathGeometry pg = new SharpDX.Direct2D1.PathGeometry(D2Drender.Factory); SharpDX.Direct2D1.GeometrySink sink = pg.Open(); for (int i = 0; i < Points.Count; i++) { if (i == 0) { sink.BeginFigure(utils.Point2Raw(Points[0]), SharpDX.Direct2D1.FigureBegin.Filled); } else { sink.AddLine(utils.Point2Raw(Points[i])); } } if (Points.Count > 0) { sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); } sink.Close(); D2Drender.FillGeometry(pg, utils.SoildBrush2Raw(FillColor)); }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (firstTime && DrawingState == DrawingState.Normal) { firstTime = false; Cbi.License.Log("Path"); } RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; Stroke outlineStroke = OutlineStroke; outlineStroke.RenderTarget = RenderTarget; ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; double strokePixAdjust = outlineStroke.Width % 2 == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(strokePixAdjust, strokePixAdjust); SharpDX.Direct2D1.PathGeometry polyGeo = CreatePathGeometry(chartControl, chartPanel, chartScale, strokePixAdjust); SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : outlineStroke.BrushDX; RenderTarget.DrawGeometry(polyGeo, tmpBrush, outlineStroke.Width, outlineStroke.StrokeStyle); polyGeo.Dispose(); if (PathBegin == PathToolCapMode.Arrow || PathEnd == PathToolCapMode.Arrow) { Point[] points = GetPathAnchorPoints(chartControl, chartScale); if (points.Length > 1) { if (arrowPathGeometry == null) { arrowPathGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink geometrySink = arrowPathGeometry.Open(); float arrowWidth = 6f; SharpDX.Vector2 top = new SharpDX.Vector2(0, outlineStroke.Width * 0.5f); geometrySink.BeginFigure(top, SharpDX.Direct2D1.FigureBegin.Filled); geometrySink.AddLine(new SharpDX.Vector2(arrowWidth, -arrowWidth)); geometrySink.AddLine(new SharpDX.Vector2(-arrowWidth, -arrowWidth)); geometrySink.AddLine(top); // cap off figure geometrySink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); geometrySink.Close(); } if (PathBegin == PathToolCapMode.Arrow) { Vector lineVector = points[0] - points[1]; lineVector.Normalize(); Point pointAdjusted = points[0] + pixelAdjustVec; SharpDX.Vector2 pointVec = pointAdjusted.ToVector2(); float vectorAngle = -(float)Math.Atan2(lineVector.X, lineVector.Y); Vector adjustVector = lineVector * 5; SharpDX.Vector2 arrowPointVec = new SharpDX.Vector2((float)(pointVec.X + adjustVector.X), (float)(pointVec.Y + adjustVector.Y)); SharpDX.Matrix3x2 transformMatrix2 = SharpDX.Matrix3x2.Rotation(vectorAngle, SharpDX.Vector2.Zero) * SharpDX.Matrix3x2.Scaling((float)Math.Max(1.0f, outlineStroke.Width * .45) + 0.25f) * SharpDX.Matrix3x2.Translation(arrowPointVec); RenderTarget.Transform = transformMatrix2; RenderTarget.FillGeometry(arrowPathGeometry, tmpBrush); RenderTarget.Transform = SharpDX.Matrix3x2.Identity; } if (PathEnd == PathToolCapMode.Arrow) { Vector lineVector = points[points.Length - 1] - points[points.Length - 2]; lineVector.Normalize(); Point pointAdjusted = points[points.Length - 1] + pixelAdjustVec; SharpDX.Vector2 pointVec = pointAdjusted.ToVector2(); float vectorAngle = -(float)Math.Atan2(lineVector.X, lineVector.Y); Vector adjustVector = lineVector * 5; SharpDX.Vector2 arrowPointVec = new SharpDX.Vector2((float)(pointVec.X + adjustVector.X), (float)(pointVec.Y + adjustVector.Y)); SharpDX.Matrix3x2 transformMatrix2 = SharpDX.Matrix3x2.Rotation(vectorAngle, SharpDX.Vector2.Zero) * SharpDX.Matrix3x2.Scaling((float)Math.Max(1.0f, outlineStroke.Width * .45) + 0.25f) * SharpDX.Matrix3x2.Translation(arrowPointVec); RenderTarget.Transform = transformMatrix2; RenderTarget.FillGeometry(arrowPathGeometry, tmpBrush); RenderTarget.Transform = SharpDX.Matrix3x2.Identity; } } } if (ShowCount) { SimpleFont wpfFont = chartControl.Properties.LabelFont ?? new SimpleFont(); SharpDX.DirectWrite.TextFormat textFormat = wpfFont.ToDirectWriteTextFormat(); textFormat.TextAlignment = SharpDX.DirectWrite.TextAlignment.Leading; textFormat.WordWrapping = SharpDX.DirectWrite.WordWrapping.NoWrap; for (int i = 1; i < ChartAnchors.Count; i++) { Point p = ChartAnchors[i - 1].GetPoint(chartControl, chartPanel, chartScale); Point p1 = ChartAnchors[i].GetPoint(chartControl, chartPanel, chartScale); if (i + 1 < ChartAnchors.Count) { Point p2 = ChartAnchors[i + 1].GetPoint(chartControl, chartPanel, chartScale); Vector v1 = p - p1; v1.Normalize(); Vector v2 = p2 - p1; v2.Normalize(); Vector vector = v1 + v2; vector.Normalize(); SharpDX.DirectWrite.TextLayout textLayout = new SharpDX.DirectWrite.TextLayout(Core.Globals.DirectWriteFactory, i.ToString(), textFormat, 250, textFormat.FontSize); Point textPoint = p1 - vector * textFormat.FontSize; textPoint.X -= textLayout.Metrics.Width / 2f; textPoint.Y -= textLayout.Metrics.Height / 2f; RenderTarget.DrawTextLayout((textPoint + pixelAdjustVec).ToVector2(), textLayout, outlineStroke.BrushDX, SharpDX.Direct2D1.DrawTextOptions.NoSnap); textLayout.Dispose(); } else { SharpDX.DirectWrite.TextLayout textLayout = new SharpDX.DirectWrite.TextLayout(Core.Globals.DirectWriteFactory, i.ToString(), textFormat, 250, textFormat.FontSize); Vector vector = (p - p1); vector.Normalize(); Point textPoint = p1 - vector * textFormat.FontSize; textPoint.X -= textLayout.Metrics.Width / 2f; textPoint.Y -= textLayout.Metrics.Height / 2f; RenderTarget.DrawTextLayout((textPoint + pixelAdjustVec).ToVector2(), textLayout, outlineStroke.BrushDX, SharpDX.Direct2D1.DrawTextOptions.NoSnap); textLayout.Dispose(); } } textFormat.Dispose(); } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; ChartPanel panel = chartControl.ChartPanels[PanelIndex]; Point anchorPoint = Anchor.GetPoint(chartControl, panel, chartScale); Point lastEndPoint = new Point(0, 0); SharpDX.Direct2D1.Brush lastBrush = null; foreach (GannAngle gannAngle in GannAngles.Where(ga => ga.IsVisible && ga.Stroke != null).OrderBy(ga => (ga.RatioX / ga.RatioY))) { gannAngle.Stroke.RenderTarget = RenderTarget; double dx = gannAngle.RatioX * chartControl.Properties.BarDistance; double dVal = gannAngle.RatioY * PointsPerBar; //NT7, just multiple directly this is price not pixels //chartScale.GetPixelsForDistance(gannAngle.RatioY * PointsPerBar); Vector gannDataVector = GetGannStepDataVector(dx, dVal); Point extendedEndPoint = CalculateExtendedDataPoint(panel, chartScale, Convert.ToInt32(anchorPoint.X), Anchor.Price, gannDataVector); // align to full pixel to avoid unneeded aliasing double strokePixAdj = ((double)(gannAngle.Stroke.Width % 2)).ApproxCompare(0) == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(0, strokePixAdj); SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : gannAngle.Stroke.BrushDX; RenderTarget.DrawLine((anchorPoint + pixelAdjustVec).ToVector2(), (extendedEndPoint + pixelAdjustVec).ToVector2(), tmpBrush, gannAngle.Stroke.Width, gannAngle.Stroke.StrokeStyle); if (lastBrush != null) { float oldOpacity = lastBrush.Opacity; lastBrush.Opacity = PriceLevelOpacity / 100f; // create geometry SharpDX.Direct2D1.PathGeometry lineGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink sink = lineGeometry.Open(); sink.BeginFigure(lastEndPoint.ToVector2(), SharpDX.Direct2D1.FigureBegin.Filled); // Does the fill color need to fill a corner? Check and add a point if (Math.Abs(lastEndPoint.Y - extendedEndPoint.Y) > 0.1 && Math.Abs(lastEndPoint.X - extendedEndPoint.X) > 0.1) { double boundaryX; double boundaryY; if (lastEndPoint.Y <= ChartPanel.Y || lastEndPoint.Y >= ChartPanel.Y + ChartPanel.H) { if (FanDirection == GannFanDirection.UpLeft || FanDirection == GannFanDirection.UpRight) { boundaryY = extendedEndPoint.Y; boundaryX = lastEndPoint.X; } else { boundaryY = lastEndPoint.Y; boundaryX = extendedEndPoint.X; } } else { if (FanDirection == GannFanDirection.UpLeft || FanDirection == GannFanDirection.UpRight) { boundaryY = lastEndPoint.Y; boundaryX = extendedEndPoint.X; } else { boundaryY = extendedEndPoint.Y; boundaryX = lastEndPoint.X; } } sink.AddLine(new SharpDX.Vector2((float)boundaryX, (float)boundaryY)); } sink.AddLine(extendedEndPoint.ToVector2()); sink.AddLine((anchorPoint + pixelAdjustVec).ToVector2()); sink.AddLine((lastEndPoint).ToVector2()); sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); sink.Close(); RenderTarget.FillGeometry(lineGeometry, lastBrush); lineGeometry.Dispose(); lastBrush.Opacity = oldOpacity; } lastEndPoint = extendedEndPoint + pixelAdjustVec; lastBrush = tmpBrush; } if (!IsTextDisplayed || IsInHitTest) { return; } foreach (GannAngle gannAngle in GannAngles.Where(ga => ga.IsVisible && ga.Stroke != null).OrderBy(ga => (ga.RatioX / ga.RatioY))) { gannAngle.Stroke.RenderTarget = RenderTarget; double dx = gannAngle.RatioX * chartControl.Properties.BarDistance; double dVal = gannAngle.RatioY * PointsPerBar; //NT7, just multiple directly this is price not pixels //chartScale.GetPixelsForDistance(gannAngle.RatioY * PointsPerBar); Vector gannDataVector = GetGannStepDataVector(dx, dVal); Point extendedEndPoint = CalculateExtendedDataPoint(panel, chartScale, Convert.ToInt32(anchorPoint.X), Anchor.Price, gannDataVector); if (!IsTextDisplayed || IsInHitTest) { continue; } SimpleFont wpfFont = chartControl.Properties.LabelFont ?? new SimpleFont(); SharpDX.DirectWrite.TextFormat textFormat = wpfFont.ToDirectWriteTextFormat(); textFormat.TextAlignment = SharpDX.DirectWrite.TextAlignment.Leading; textFormat.WordWrapping = SharpDX.DirectWrite.WordWrapping.NoWrap; SharpDX.DirectWrite.TextLayout textLayout = new SharpDX.DirectWrite.TextLayout(Core.Globals.DirectWriteFactory, gannAngle.Name, textFormat, 100, textFormat.FontSize); // once text is laid out, update used width to calcuated space required float fontHeight = textLayout.Metrics.Height; Point textEndPoint = new Point(extendedEndPoint.X, extendedEndPoint.Y); if (textEndPoint.X > panel.X + panel.W - textLayout.Metrics.Width) { textEndPoint.X = panel.X + panel.W - textLayout.Metrics.Width; textEndPoint.Y += textLayout.Metrics.Width; } if (gannDataVector.Y > 0) { if (textEndPoint.Y < panel.Y + (fontHeight * 0.5)) { textEndPoint.Y = panel.Y + (fontHeight * 0.5); } } else { if (textEndPoint.Y > panel.Y + panel.H - (fontHeight * 1.5)) { textEndPoint.Y = panel.Y + panel.H - (fontHeight * 1.5); } } float?marginResource = Application.Current.FindResource("FontModalTitleMargin") as float?; float margin = 2f + (marginResource.HasValue ? marginResource.Value : 3f); // Allow for changes in X position based on whether text is aligned to left or right edge of screen float marginX = FanDirection == GannFanDirection.DownLeft || FanDirection == GannFanDirection.UpLeft ? margin : -2 * margin; SharpDX.Vector2 endVec = new SharpDX.Vector2((float)textEndPoint.X, (float)textEndPoint.Y); SharpDX.Matrix3x2 transformMatrix = SharpDX.Matrix3x2.Translation(endVec); RenderTarget.Transform = transformMatrix; RenderTarget.DrawTextLayout(new SharpDX.Vector2(marginX + margin, margin), textLayout, gannAngle.Stroke.BrushDX, SharpDX.Direct2D1.DrawTextOptions.NoSnap); RenderTarget.Transform = SharpDX.Matrix3x2.Identity; textFormat.Dispose(); textLayout.Dispose(); } }
protected override void OnRender(Gui.Chart.ChartControl chartControl, Gui.Chart.ChartScale chartScale) { if (Bars == null || chartControl == null || startIndex == int.MinValue) { return; } IsValidDataPointAt(Bars.Count - 1 - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 1 : 0)); // Make sure indicator is calculated until last (existing) bar int preDiff = 1; for (int i = ChartBars.FromIndex - 1; i >= 0; i--) { if (i - Displacement < startIndex || i - Displacement > Bars.Count - 1 - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 1 : 0)) { break; } bool isHigh = zigZagHighZigZags.IsValidDataPointAt(i - Displacement); bool isLow = zigZagLowZigZags.IsValidDataPointAt(i - Displacement); if (isHigh || isLow) { break; } preDiff++; } preDiff -= (Displacement < 0 ? Displacement : 0 - Displacement); int postDiff = 0; for (int i = ChartBars.ToIndex; i <= zigZagHighZigZags.Count; i++) { if (i - Displacement < startIndex || i - Displacement > Bars.Count - 1 - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 1 : 0)) { break; } bool isHigh = zigZagHighZigZags.IsValidDataPointAt(i - Displacement); bool isLow = zigZagLowZigZags.IsValidDataPointAt(i - Displacement); if (isHigh || isLow) { break; } postDiff++; } postDiff += (Displacement < 0 ? 0 - Displacement : Displacement); int lastIdx = -1; double lastValue = -1; SharpDX.Direct2D1.PathGeometry g = null; SharpDX.Direct2D1.GeometrySink sink = null; for (int idx = ChartBars.FromIndex - preDiff; idx <= ChartBars.ToIndex + postDiff; idx++) { if (idx < startIndex || idx > Bars.Count - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 2 : 1) || idx < Math.Max(BarsRequiredToPlot - Displacement, Displacement)) { continue; } bool isHigh = zigZagHighZigZags.IsValidDataPointAt(idx); bool isLow = zigZagLowZigZags.IsValidDataPointAt(idx); if (!isHigh && !isLow) { continue; } double value = isHigh ? zigZagHighZigZags.GetValueAt(idx) : zigZagLowZigZags.GetValueAt(idx); if (lastIdx >= startIndex) { float x1 = (chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && idx + Displacement >= ChartBars.Count ? chartControl.GetXByTime(ChartBars.GetTimeByBarIdx(chartControl, idx + Displacement)) : chartControl.GetXByBarIndex(ChartBars, idx + Displacement)); float y1 = chartScale.GetYByValue(value); if (sink == null) { float x0 = (chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && lastIdx + Displacement >= ChartBars.Count ? chartControl.GetXByTime(ChartBars.GetTimeByBarIdx(chartControl, lastIdx + Displacement)) : chartControl.GetXByBarIndex(ChartBars, lastIdx + Displacement)); float y0 = chartScale.GetYByValue(lastValue); g = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); sink = g.Open(); sink.BeginFigure(new SharpDX.Vector2(x0, y0), SharpDX.Direct2D1.FigureBegin.Hollow); } sink.AddLine(new SharpDX.Vector2(x1, y1)); } // Save as previous point lastIdx = idx; lastValue = value; } if (sink != null) { sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Open); sink.Close(); } if (g != null) { var oldAntiAliasMode = RenderTarget.AntialiasMode; RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; RenderTarget.DrawGeometry(g, Plots[0].BrushDX, Plots[0].Width, Plots[0].StrokeStyle); RenderTarget.AntialiasMode = oldAntiAliasMode; g.Dispose(); RemoveDrawObject("NinjaScriptInfo"); } else { Draw.TextFixed(this, "NinjaScriptInfo", NinjaTrader.Custom.Resource.ZigZagDeviationValueError, TextPosition.BottomRight); } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (Series1 == null) { return; } NinjaScriptBase nsb = AttachedTo.ChartObject as NinjaScriptBase; ChartBars chartBars = (AttachedTo.ChartObject as Gui.NinjaScript.IChartBars).ChartBars; if (nsb == null || chartBars == null || Math.Abs(Series1.Count - chartBars.Count) > 1) { return; } int startBarIdx; int endBarIdx; if (chartControl.BarSpacingType == BarSpacingType.TimeBased) { startBarIdx = chartBars.GetBarIdxByTime(chartControl, StartAnchor.Time); endBarIdx = chartBars.GetBarIdxByTime(chartControl, EndAnchor.Time); } else { startBarIdx = StartAnchor.DrawnOnBar - StartAnchor.BarsAgo; endBarIdx = EndAnchor.DrawnOnBar - EndAnchor.BarsAgo; if (startBarIdx == endBarIdx) { startBarIdx = chartBars.GetBarIdxByTime(chartControl, StartAnchor.Time); endBarIdx = chartBars.GetBarIdxByTime(chartControl, EndAnchor.Time); } } int startIdx = Math.Min(startBarIdx, endBarIdx); int endIdx = Math.Max(startBarIdx, endBarIdx); // Now cap start/end by visibly painted bars! // If you dont do this it will absolutely crush performance on larger regions int firstVisibleIdx = Math.Max(nsb.BarsRequiredToPlot + Displacement, chartBars.GetBarIdxByTime(chartControl, chartControl.GetTimeByX(0)) - 1); int lastVisibleIdx = Math.Max(chartBars.ToIndex, chartBars.GetBarIdxByTime(chartControl, chartControl.LastTimePainted)) + 1; // Update indicies for displacement startIdx = Math.Max(0, Math.Max(firstVisibleIdx, startIdx + Displacement)); endIdx = Math.Max(0, Math.Min(endIdx + Displacement, lastVisibleIdx)); // we're completely not visible if (startIdx > lastVisibleIdx || endIdx < firstVisibleIdx) { return; } /* NOTE: Calling GetValueAt() on an ISeries<double> interface with a concrete * type of NinjaScriptBase will get the *bar* value which is not what we want, * in this case, default to first values (indicator) series */ ISeries <double> series1Adjusted = Series1; ISeries <double> series2Adjusted = Series2; NinjaScriptBase series1NsBase = Series1 as NinjaScriptBase; if (series1NsBase != null) { series1Adjusted = series1NsBase.Value; } if (series1Adjusted == null) { return; } NinjaScriptBase series2NsBase = Series2 as NinjaScriptBase; if (series2NsBase != null) { series2Adjusted = series2NsBase.Value; } // take care to wind the points correctly so our geometry builds as a solid, not flipped inside out SharpDX.Vector2[] points; SharpDX.Vector2[] points2 = new SharpDX.Vector2[0]; int pointIdx = 0; int pointIdx2 = 0; if (series2Adjusted == null) { points = new SharpDX.Vector2[endIdx - startIdx + 1 + 2]; for (int i = startIdx; i <= endIdx; ++i) { if (i < Math.Max(0, Displacement) || i > Math.Max(chartBars.Count - (nsb.Calculate == Calculate.OnBarClose ? 2 : 1) + Displacement, endIdx)) { continue; } int displacedIndex = Math.Min(chartBars.Count - (nsb.Calculate == Calculate.OnBarClose ? 2 : 1), Math.Max(0, i - Displacement)); double seriesValue = series1Adjusted.GetValueAt(displacedIndex); float y = chartScale.GetYByValue(seriesValue); float x = chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && i >= chartBars.Count //i is already displaced ? chartControl.GetXByTime(chartBars.GetTimeByBarIdx(chartControl, i)) : chartControl.GetXByBarIndex(chartBars, i); double pixXAdjust = x % 1 != 0 ? 0 : 0.5d; double pixYAdjust = y % 1 != 0 ? 0 : 0.5d; Vector pixelAdjustVec = new Vector(pixXAdjust, pixYAdjust); Point adjusted = new Point(x, y) + pixelAdjustVec; points[pointIdx] = adjusted.ToVector2(); ++pointIdx; } // cap it end->start points[pointIdx].X = chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && endIdx >= chartBars.Count ? chartControl.GetXByTime(chartBars.GetTimeByBarIdx(chartControl, endIdx)) : chartControl.GetXByBarIndex(chartBars, endIdx); points[pointIdx++].Y = chartScale.GetYByValue(Math.Max(chartScale.MinValue, Math.Min(chartScale.MaxValue, Price))); points[pointIdx].X = chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && startIdx >= chartBars.Count ? chartControl.GetXByTime(chartBars.GetTimeByBarIdx(chartControl, startIdx)) : chartControl.GetXByBarIndex(chartBars, startIdx); points[pointIdx++].Y = chartScale.GetYByValue(Math.Max(chartScale.MinValue, Math.Min(chartScale.MaxValue, Price))); } else { points = new SharpDX.Vector2[endIdx - startIdx + 1]; points2 = new SharpDX.Vector2[endIdx - startIdx + 1]; // fill clockwise from series1, the counter clockwise for series 2 for correct point poly winding for (int i = startIdx; i <= endIdx; ++i) { if (i < Math.Max(0, Displacement) || i > Math.Max(chartBars.Count - (nsb.Calculate == Calculate.OnBarClose ? 2 : 1) + Displacement, endIdx)) { continue; } int displacedIndex = Math.Min(chartBars.Count - (nsb.Calculate == Calculate.OnBarClose ? 2 : 1), Math.Max(0, i - Displacement)); float x = chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && i >= chartBars.Count //i is already displaced ? chartControl.GetXByTime(chartBars.GetTimeByBarIdx(chartControl, i)) : chartControl.GetXByBarIndex(chartBars, i); if (!series1Adjusted.IsValidDataPointAt(displacedIndex)) { continue; } double seriesValue = series1Adjusted.GetValueAt(displacedIndex); float y = chartScale.GetYByValue(seriesValue); double pixXAdjust = x % 1 != 0 ? 0 : 0.5d; double pixYAdjust = y % 1 != 0 ? 0 : 0.5d; Vector pixelAdjustVec = new Vector(pixXAdjust, pixYAdjust); Point adjusted = new Point(x, y) + pixelAdjustVec; points[pointIdx] = adjusted.ToVector2(); ++pointIdx; if (!series2Adjusted.IsValidDataPointAt(displacedIndex)) { continue; } seriesValue = series2Adjusted.GetValueAt(displacedIndex); y = chartScale.GetYByValue(seriesValue); pixYAdjust = y % 1 != 0 ? 0 : 0.5d; pixelAdjustVec = new Vector(pixXAdjust, pixYAdjust); adjusted = new Point(x, y) + pixelAdjustVec; points2[pointIdx2] = adjusted.ToVector2(); ++pointIdx2; } } if (pointIdx + pointIdx2 > 2) { RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; if (OutlineStroke != null) { OutlineStroke.RenderTarget = RenderTarget; } if (AreaBrush != null) { if (areaBrushDevice.Brush == null) { Brush brushCopy = areaBrush.Clone(); brushCopy.Opacity = areaOpacity / 100d; areaBrushDevice.Brush = brushCopy; } areaBrushDevice.RenderTarget = RenderTarget; } SharpDX.Direct2D1.PathGeometry polyGeo = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink geoSink = polyGeo.Open(); double pixXAdjust = points[0].X % 1 != 0 ? 0 : 0.5d; double pixYAdjust = points[0].Y % 1 != 0 ? 0 : 0.5d; Vector pixelAdjustVec = new Vector(pixXAdjust, pixYAdjust); Point startPt = new Point(points[0].X, points[0].Y) + pixelAdjustVec; geoSink.BeginFigure(startPt.ToVector2(), SharpDX.Direct2D1.FigureBegin.Filled); geoSink.SetFillMode(SharpDX.Direct2D1.FillMode.Winding); // NOTE: We skip our first point since that is where the path will start for (int i = 1; i < pointIdx; i++) { geoSink.AddLine(points[i]); } for (int i = pointIdx2 - 1; i >= 0; i--) { geoSink.AddLine(points2[i]); } geoSink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); geoSink.Close(); SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : areaBrushDevice == null ? null : areaBrushDevice.BrushDX; if (tmpBrush != null) { RenderTarget.FillGeometry(polyGeo, tmpBrush); } tmpBrush = IsInHitTest ? chartControl.SelectionBrush : OutlineStroke == null ? null : OutlineStroke.BrushDX; if (tmpBrush != null) { RenderTarget.DrawGeometry(polyGeo, OutlineStroke.BrushDX, OutlineStroke.Width); } polyGeo.Dispose(); } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (Anchors.All(a => a.IsEditing)) { return; } RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; Point anchorStartPoint = StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point anchorEndPoint = EndAnchor.GetPoint(chartControl, chartPanel, chartScale); Point anchorExtensionPoint = ExtensionAnchor.GetPoint(chartControl, chartPanel, chartScale); Point midPointExtension = new Point((anchorExtensionPoint.X + anchorEndPoint.X) / 2, (anchorExtensionPoint.Y + anchorEndPoint.Y) / 2); if (CalculationMethod == AndrewsPitchforkCalculationMethod.Schiff) { anchorStartPoint = new Point(anchorStartPoint.X, (anchorStartPoint.Y + anchorEndPoint.Y) / 2); } else if (CalculationMethod == AndrewsPitchforkCalculationMethod.ModifiedSchiff) { anchorStartPoint = new Point((anchorEndPoint.X + anchorStartPoint.X) / 2, (anchorEndPoint.Y + anchorStartPoint.Y) / 2); } AnchorLineStroke.RenderTarget = RenderTarget; RetracementLineStroke.RenderTarget = RenderTarget; // Align to full pixel to avoid unneeded aliasing double strokePixAdj = AnchorLineStroke.Width % 2 == 0 ? 0.5d : 0d; Vector pixelAdjustVec = new Vector(strokePixAdj, strokePixAdj); SharpDX.Vector2 startVec = (anchorStartPoint + pixelAdjustVec).ToVector2(); SharpDX.Vector2 endVec = (anchorEndPoint + pixelAdjustVec).ToVector2(); SharpDX.Direct2D1.Brush tmpBrush = IsInHitTest ? chartControl.SelectionBrush : AnchorLineStroke.BrushDX; SharpDX.Vector2 startOriginVec = (StartAnchor.GetPoint(chartControl, chartPanel, chartScale) + pixelAdjustVec).ToVector2(); RenderTarget.DrawLine(startOriginVec, endVec, tmpBrush, AnchorLineStroke.Width, AnchorLineStroke.StrokeStyle); // Is second anchor set yet? Check both so we correctly re-draw during extension anchor editing if (ExtensionAnchor.IsEditing && EndAnchor.IsEditing) { return; } SharpDX.Vector2 extVector = anchorExtensionPoint.ToVector2(); tmpBrush = IsInHitTest ? chartControl.SelectionBrush : RetracementLineStroke.BrushDX; RenderTarget.DrawLine(endVec, extVector, tmpBrush, RetracementLineStroke.Width, RetracementLineStroke.StrokeStyle); // If we're doing a hit test pass, don't draw price levels at all, we dont want those to count for // hit testing if (IsInHitTest || PriceLevels == null || !PriceLevels.Any()) { return; } SetAllPriceLevelsRenderTarget(); // Calculate total y range for % calculation on each level double totalPriceRange = EndAnchor.Price - ExtensionAnchor.Price; double startPrice = ExtensionAnchor.Price; float minLevelY = float.MaxValue; float maxLevelY = float.MinValue; // Store values to use in correct render order Point lastEndPoint = new Point(0, 0); Point lastStartPoint = new Point(0, 0); Stroke lastStroke = null; List <Tuple <PriceLevel, Point> > textPoints = new List <Tuple <PriceLevel, Point> >(); foreach (PriceLevel priceLevel in PriceLevels.Where(pl => pl.IsVisible && pl.Stroke != null).OrderBy(pl => pl.Value)) { double levelPrice = (startPrice + ((priceLevel.Value / 100) * totalPriceRange)); float pixelY = chartScale.GetYByValue(levelPrice); float pixelX = anchorExtensionPoint.X > anchorEndPoint.X ? priceLevel.Value >= 0 ? (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))) : (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))): priceLevel.Value >= 0 ? (float)(anchorExtensionPoint.X + ((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100))) : (float)(anchorExtensionPoint.X - (Math.Abs((anchorEndPoint.X - anchorExtensionPoint.X) * (priceLevel.Value / 100)))); Point startPoint = new Point(pixelX, pixelY); Point endPoint = new Point(startPoint.X + (midPointExtension.X - anchorStartPoint.X), startPoint.Y + (midPointExtension.Y - anchorStartPoint.Y)); Point maxLevelPoint = GetExtendedPoint(startPoint, endPoint); if (priceLevel.Value == 50) { RenderTarget.DrawLine(startVec, maxLevelPoint.ToVector2(), priceLevel.Stroke.BrushDX, priceLevel.Stroke.Width, priceLevel.Stroke.StrokeStyle); } else { RenderTarget.DrawLine(startPoint.ToVector2(), maxLevelPoint.ToVector2(), priceLevel.Stroke.BrushDX, priceLevel.Stroke.Width, priceLevel.Stroke.StrokeStyle); } if (lastStroke == null) { lastStroke = new Stroke(); } else { SharpDX.Direct2D1.PathGeometry lineGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); SharpDX.Direct2D1.GeometrySink sink = lineGeometry.Open(); sink.BeginFigure(lastEndPoint.ToVector2(), SharpDX.Direct2D1.FigureBegin.Filled); // Does the fill color need to fill a corner? Check and add a point if (lastEndPoint.Y != maxLevelPoint.Y && lastEndPoint.X != maxLevelPoint.X) { double boundaryX; double boundaryY; if (lastEndPoint.Y <= ChartPanel.Y || lastEndPoint.Y >= ChartPanel.Y + ChartPanel.H) { boundaryY = lastEndPoint.Y; boundaryX = maxLevelPoint.X; } else { boundaryY = maxLevelPoint.Y; boundaryX = lastEndPoint.X; } sink.AddLine(new SharpDX.Vector2((float)boundaryX, (float)boundaryY)); } sink.AddLine(maxLevelPoint.ToVector2()); sink.AddLine(startPoint.ToVector2()); sink.AddLine(lastStartPoint.ToVector2()); sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Closed); sink.Close(); RenderTarget.FillGeometry(lineGeometry, lastStroke.BrushDX); lineGeometry.Dispose(); } if (IsTextDisplayed) { textPoints.Add(new Tuple <PriceLevel, Point>(priceLevel, maxLevelPoint)); } priceLevel.Stroke.CopyTo(lastStroke); lastStroke.Opacity = PriceLevelOpacity; lastStartPoint = startPoint; lastEndPoint = maxLevelPoint; minLevelY = Math.Min(pixelY, minLevelY); maxLevelY = Math.Max(pixelY, maxLevelY); } // Render text last so it's on top of the price level colors if (IsTextDisplayed) { foreach (Tuple <PriceLevel, Point> textPoint in textPoints) { DrawPriceLevelText(0, 0, textPoint.Item2, textPoint.Item1, chartPanel); } } }