/// <summary> /// Initializes a new instance of the <see cref="LineSegment3D"/> class with default settings. /// </summary> /// <param name="xValues">The X Values</param> /// <param name="YValues">The Y Values</param> /// <param name="startDepth">The Start Depth</param> /// <param name="endDepth">The End Depth</param> /// <param name="lineSeries3D">The LineSeries3D</param> public LineSegment3D(List <double> xValues, IList <double> YValues, double startDepth, double endDepth, LineSeries3D lineSeries3D) { this.Series = lineSeries3D; this.area = lineSeries3D.Area; this.polygonRecycler = new PolygonRecycler(); }
/// <summary> /// Updates the segments based on its data point value. This method is not /// intended to be called explicitly outside the Chart but it can be overridden by /// any derived class. /// </summary> /// <param name="transformer">Represents the view port of chart control.(refer <see cref="IChartTransformer"/>)</param> public override void Update(IChartTransformer transformer) { ChartTransform.ChartCartesianTransformer cartesianTransformer = transformer as ChartTransform.ChartCartesianTransformer; if (cartesianTransformer != null) { Polygon3D bottomPolygon, topPolygon, startPolygon, endPolygon; LineSeries3D lineSeries = Series as LineSeries3D; if (this.area == null || this.xValues.Count == 1 || lineSeries.StrokeThickness == 0) { return; } var xBase = cartesianTransformer.XAxis.IsLogarithmic ? ((LogarithmicAxis3D)cartesianTransformer.XAxis).LogarithmicBase : 1; var yBase = cartesianTransformer.YAxis.IsLogarithmic ? ((LogarithmicAxis3D)cartesianTransformer.YAxis).LogarithmicBase : 1; var xIsLogarithmic = cartesianTransformer.XAxis.IsLogarithmic; var yIsLogarithmic = cartesianTransformer.YAxis.IsLogarithmic; double xStart = xIsLogarithmic ? Math.Pow(xBase, cartesianTransformer.XAxis.VisibleRange.Start) : cartesianTransformer.XAxis.VisibleRange.Start; double xEnd = xIsLogarithmic ? Math.Pow(xBase, cartesianTransformer.XAxis.VisibleRange.End) : cartesianTransformer.XAxis.VisibleRange.End; var yStart = yIsLogarithmic ? Math.Pow(yBase, cartesianTransformer.YAxis.VisibleRange.Start) : cartesianTransformer.YAxis.VisibleRange.Start; var yEnd = yIsLogarithmic ? Math.Pow(yBase, cartesianTransformer.YAxis.VisibleRange.End) : cartesianTransformer.YAxis.VisibleRange.End; // Clipping the line series 3D if (xValues.Min() < xStart) { while (this.xValues[0] < xStart) { this.xValues.RemoveAt(0); this.yValues.RemoveAt(0); } } if (this.xValues.Max() > xEnd) { int index = this.xValues.IndexOf(xEnd); while (this.xValues[index + 1] > xEnd) { this.xValues.RemoveAt(index + 1); this.yValues.RemoveAt(index + 1); if (index >= this.xValues.Count - 1) { break; } } } var indexes = from val in this.yValues.ToList() where (val <yStart || val> yEnd) select this.yValues.IndexOf(val); if (this.yValues.Count - indexes.Count() < 2) { return; } if (indexes.Count() > 0) { foreach (var index in indexes) { if (yValues[index] < yStart) { this.yValues[index] = yStart; } else { this.yValues[index] = yEnd; } } } //// End of clipping logic double x = this.xValues[0]; double y = !lineSeries.IsAnimated && !Series.EnableAnimation ? this.yValues[0] : (this.Y < this.yValues[0] && this.Y > 0) ? this.Y : this.yValues[0]; Point previousPoint = transformer.TransformToVisible(x, y); Point currentPoint; this.point2 = new double[10]; this.point1 = new double[10]; x = this.xValues[1]; y = !lineSeries.IsAnimated && !Series.EnableAnimation ? this.yValues[1] : (this.Y < this.yValues[1] && Y > 0) ? this.Y : this.yValues[1]; currentPoint = transformer.TransformToVisible(x, y); int leftThickness = lineSeries.StrokeThickness / 2; int rightThickness = (lineSeries.StrokeThickness % 2 == 0 ? (lineSeries.StrokeThickness / 2) - 1 : lineSeries.StrokeThickness / 2); LineSegment3D.GetLinePoints(previousPoint.X, previousPoint.Y, currentPoint.X, currentPoint.Y, leftThickness, rightThickness, this.point1); int j = 0; // To reset the polygon recycler collection index. this.polygonRecycler.Reset(); for (int i = 1; i < this.yValues.Count;) { this.point2 = new double[10]; previousPoint = currentPoint; bool isMultiColor = (Series.SegmentColorPath != null || Series.Palette != ChartColorPalette.None); this.color = isMultiColor ? (Series.GetInteriorColor(i - 1)) : (this.Interior); if (i == 1) { Vector3D[] startPolygonVects = new Vector3D[] { new Vector3D(this.point1[6], this.point1[7], startDepth), new Vector3D(this.point1[6], this.point1[7], endDepth), new Vector3D(this.point1[0], this.point1[1], endDepth), new Vector3D(this.point1[0], this.point1[1], startDepth) }; startPolygon = this.polygonRecycler.DequeuePolygon(startPolygonVects, this, Series.Segments.IndexOf(this), this.Stroke, this.StrokeThickness, this.color); if (lineSeries.IsAnimated || !Series.EnableAnimation) { this.area.Graphics3D.AddVisual(startPolygon); } } i++; if (i < this.xValues.Count) { x = this.xValues[i]; y = !lineSeries.IsAnimated && !Series.EnableAnimation ? this.yValues[i] : (this.Y < this.yValues[i] && this.Y > 0) ? this.Y : this.yValues[i]; x = !(x >= xStart) ? xStart : !(x <= xEnd) ? xEnd : x; y = !(y >= yStart) ? yStart : !(y <= yEnd) ? yEnd : y; currentPoint = transformer.TransformToVisible(x, y); this.UpdatePoints2(previousPoint.X, previousPoint.Y, currentPoint.X, currentPoint.Y, leftThickness, rightThickness); } Vector3D[] bottomPolyVects = new Vector3D[] { new Vector3D(this.point1[2], this.point1[3], startDepth), new Vector3D(this.point1[0], this.point1[1], startDepth), new Vector3D(this.point1[0], this.point1[1], endDepth), new Vector3D(this.point1[2], this.point1[3], endDepth) }; Vector3D[] topPolyVects = new Vector3D[] { new Vector3D(this.point1[6], this.point1[7], startDepth), new Vector3D(this.point1[4], this.point1[5], startDepth), new Vector3D(this.point1[4], this.point1[5], endDepth), new Vector3D(this.point1[6], point1[7], endDepth) }; bottomPolygon = new Polygon3D( bottomPolyVects, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, this.color); bottomPolygon.CalcNormal(bottomPolyVects[0], bottomPolyVects[1], bottomPolyVects[2]); bottomPolygon.CalcNormal(); topPolygon = new Polygon3D( topPolyVects, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, this.color); topPolygon.CalcNormal(topPolyVects[0], topPolyVects[1], topPolyVects[2]); topPolygon.CalcNormal(); if (lineSeries.IsAnimated || !Series.EnableAnimation) { this.area.Graphics3D.AddVisual(bottomPolygon); this.area.Graphics3D.AddVisual(topPolygon); this.RenderFrontPolygon(this.point1, this.startDepth, this.endDepth, this.color); } if (this.point2 != null && (i < this.xValues.Count)) { this.point1 = this.point2; } j++; } Vector3D[] endPolyVects = new Vector3D[] { new Vector3D(this.point1[4], this.point1[5], startDepth), new Vector3D(this.point1[4], this.point1[5], endDepth), new Vector3D(this.point1[2], this.point1[3], endDepth), new Vector3D(this.point1[2], this.point1[3], startDepth) }; endPolygon = new Polygon3D(endPolyVects, this, 0, Stroke, 1, this.color); endPolygon.CalcNormal(endPolyVects[0], endPolyVects[1], endPolyVects[2]); endPolygon.CalcNormal(); if (lineSeries.IsAnimated || !Series.EnableAnimation) { this.area.Graphics3D.AddVisual(endPolygon); } } }