/// <summary> /// Method used to remove the polygon in Queue. /// </summary> /// <param name="points">The Points</param> /// <param name="tag">The Tag</param> /// <param name="index">The Index</param> /// <param name="stroke">The stroke</param> /// <param name="strokeThickness">The stroke Thickness</param> /// <param name="fill">The Fill</param> /// <returns>Returns the polygon.</returns> public Polygon3D DequeuePolygon(Vector3D[] points, DependencyObject tag, int index, Brush stroke, double strokeThickness, Brush fill) { if (polygonCache.Count > pointer) { polygon = polygonCache[pointer]; polygon.Element = new Path(); polygon.Tag = tag; polygon.Index = index; polygon.Stroke = stroke; polygon.CalcNormal(points[0], points[1], points[2]); polygon.VectorPoints = points; polygon.CalcNormal(); pointer++; } else if (polygonCache.Count <= pointer) { polygon = new Polygon3D(points, tag, index, stroke, strokeThickness, fill); polygon.CalcNormal(points[0], points[1], points[2]); polygon.CalcNormal(); polygonCache.Add(polygon); pointer++; } return(polygon); }
/// <summary> /// Redraws the segments. /// </summary> internal void ReDraw() { if (VectorPoints == null || VectorPoints.Length <= 0) { return; } var transform = Graphics3D.Transform; var segmentPath = Element as Path; if (segmentPath == null) { return; } var figure = new PathFigure(); var segmentGeometry = new PathGeometry(); if (transform != null) { figure.StartPoint = transform.ToScreen(VectorPoints[0]); foreach (var lineSegment in VectorPoints.Select(item => new WindowsLineSegment { Point = transform.ToScreen(item) })) { figure.Segments.Add(lineSegment); } } segmentGeometry.Figures.Add(figure); segmentPath.Data = segmentGeometry; var lightCoefZ = (int)(2 * (Math.Abs(normal & new Vector3D(0, 0, 1)) - 1)); var lightCoefY = (int)(2 * (Math.Abs(normal & new Vector3D(0, 1, 0)) - 1)); var lightCoefX = (int)(2 * (Math.Abs(normal & new Vector3D(1, 0, 0)) - 1)); var actualBrush = (Fill is SolidColorBrush) ? ((SolidColorBrush)Fill).Color : ((Fill is LinearGradientBrush) && ((LinearGradientBrush)Fill).GradientStops.Count > 0) ? ((LinearGradientBrush)Fill).GradientStops[0].Color : new SolidColorBrush(Colors.Transparent).Color; if (lightCoefZ == lightCoefX && Fill != null) { segmentPath.Fill = ApplyZLight(actualBrush); } else if (((lightCoefY == lightCoefZ) || (lightCoefZ != 0 && lightCoefY < lightCoefZ)) && !(Tag is LineSegment3D) && !(Tag is AreaSegment3D) && !(Tag is PieSegment3D) && Fill != null) { segmentPath.Fill = Polygon3D.ApplyXLight(actualBrush); } else if (lightCoefZ < 0 && Fill != null) { segmentPath.Fill = ApplyZLight(actualBrush); } else { segmentPath.Fill = Fill; } segmentPath.StrokeThickness = strokeThickness; segmentPath.Stroke = Stroke; }
/// <summary> /// Updates the polygon. /// </summary> /// <param name="updatedPoints">The Updated Points</param> /// <param name="interior">The Interior</param> /// <param name="visibility">The Visibility</param> internal void Update(Vector3D[] updatedPoints, Brush interior, Visibility visibility) { VectorPoints = updatedPoints; var segmentPath = Element as Path; if (segmentPath == null) { return; } segmentPath.Visibility = visibility; if (Graphics3D == null) { return; } var transform = Graphics3D.Transform; var figure = new PathFigure(); var segmentGeometry = new PathGeometry(); var actualBrush = (Fill is SolidColorBrush) ? ((SolidColorBrush)Fill).Color : ((Fill is LinearGradientBrush) && ((LinearGradientBrush)Fill).GradientStops.Count > 0) ? ((LinearGradientBrush)Fill).GradientStops[0].Color : new SolidColorBrush(Colors.Transparent).Color; if (transform != null) { figure.StartPoint = transform.ToScreen(VectorPoints[0]); foreach (var lineSegment in VectorPoints.Select(item => new WindowsLineSegment { Point = transform.ToScreen(item) })) { figure.Segments.Add(lineSegment); } } segmentGeometry.Figures.Add(figure); var lightCoefZ = (int)(2 * (Math.Abs(normal & new Vector3D(0, 0, 1)) - 1)); var lightCoefY = (int)(2 * (Math.Abs(normal & new Vector3D(0, 1, 0)) - 1)); var lightCoefX = (int)(2 * (Math.Abs(normal & new Vector3D(1, 0, 0)) - 1)); if (lightCoefZ == lightCoefX && interior != null) { segmentPath.Fill = ApplyZLight(actualBrush); } else if (((lightCoefY == lightCoefZ) || (lightCoefZ != 0 && lightCoefY < lightCoefZ)) && !(Tag is LineSegment3D) && !(Tag is AreaSegment3D) && interior != null) { segmentPath.Fill = Polygon3D.ApplyXLight(actualBrush); } else if (lightCoefZ < 0 && interior != null) { segmentPath.Fill = ApplyZLight(actualBrush); } else { segmentPath.Fill = interior; } segmentPath.Data = segmentGeometry; }
/// <summary> /// Renders the front polygon. /// </summary> /// <param name="point1">The Points Array</param> /// <param name="startDepth">The Start Depth</param> /// <param name="endDepth">The End Depth</param> /// <param name="color">The Color</param> private void RenderFrontPolygon(double[] point1, double startDepth, double endDepth, Brush color) { Vector3D[] frontVectors = new Vector3D[] { new Vector3D(point1[0], point1[1], startDepth), new Vector3D(point1[2], point1[3], startDepth), new Vector3D(point1[4], point1[5], startDepth), new Vector3D(point1[6], point1[7], startDepth), new Vector3D(point1[8], point1[9], startDepth) }; Vector3D[] backVectors = new Vector3D[] { new Vector3D(point1[0], point1[1], endDepth), new Vector3D(point1[2], point1[3], endDepth), new Vector3D(point1[4], point1[5], endDepth), new Vector3D(point1[6], point1[7], endDepth), new Vector3D(point1[8], point1[9], endDepth) }; Polygon3D frontPolygon = new Polygon3D(frontVectors, this, 0, Stroke, 1, color); frontPolygon.CalcNormal(frontVectors[0], frontVectors[1], frontVectors[2]); frontPolygon.CalcNormal(); this.area.Graphics3D.AddVisual(frontPolygon); Polygon3D backPolygon = new Polygon3D(backVectors, this, 0, Stroke, 1, color); backPolygon.CalcNormal(backVectors[0], backVectors[1], backVectors[2]); backPolygon.CalcNormal(); this.area.Graphics3D.AddVisual(backPolygon); }
/// <summary> /// Classify the polygon. /// </summary> /// <param name="polygon1">The First Polygon.</param> /// <param name="polygon2">The Second Polygon.</param> /// <returns>Returns the classified result.</returns> private static ClassifyPolyResult ClassifyPolygon(Polygon3D polygon1, Polygon3D polygon2) { var res = ClassifyPolyResult.Unknown; var points = polygon2.Points; if (points == null) { return(res); } var onBack = 0; var onFront = 0; var onPlane = 0; var normal = polygon1.Normal; // root node normailized value perpendicular direction var d = polygon1.D; // constant of the plan or depth for (int i = 0, len = points.Length; i < len; i++) { var r = -d - (points[i] & normal); // Comparision of Plane point depth with the other nodes if (r > EPSILON) { onBack++; } else if (r < -EPSILON) { onFront++; } else { onPlane++; } if ((onBack > 0) && (onFront > 0)) { break; } } if (onPlane == points.Length) { res = ClassifyPolyResult.OnPlane; } else if (onFront + onPlane == points.Length) { res = ClassifyPolyResult.ToRight; } else if (onBack + onPlane == points.Length) { res = ClassifyPolyResult.ToLeft; } else { res = ClassifyPolyResult.Unknown; } return(res); }
/// <summary> /// Initializes a new instance of the <see cref="Graphics3D"/> class. /// </summary> /// <summary> /// Adds the polygon to the drawing. /// </summary> /// <param name="polygon">The <see cref="Polygon3D"/>.</param> /// <returns>Returns the last index.</returns> public int AddVisual(Polygon3D polygon) { if ((polygon == null) || (polygon.Test())) { return(-1); } polygon.Graphics3D = this; return(this.treeBuilder.Add(polygon)); }
/// <summary> /// Initializes a new instance of the <see cref="Polygon3D"/> class. /// </summary> /// <param name="points">The points.</param> /// <param name="polygon">The plane.</param> public Polygon3D(Vector3D[] points, Polygon3D polygon) : this(points) { polygon.Element = null; Element = new Path(); Index = polygon.Index; Stroke = polygon.Stroke; Tag = polygon.Tag; Graphics3D = polygon.Graphics3D; Fill = polygon.Fill; strokeThickness = polygon.strokeThickness; }
/// <summary> /// This method used to gets the chart data point at a position. /// </summary> /// <param name="point">The Mouse Position</param> /// <returns>Returns the data point.</returns> internal override ChartDataPointInfo GetDataPoint(Point point) { var frontPlane = new Polygon3D(new Vector3D(0, 0, 1), 0); var transform = (ActualArea as SfChart3D).Graphics3D.Transform; frontPlane.Transform(transform.View); var position = transform.ToPlane(point, frontPlane); Rect rect; int startIndex, endIndex; List <int> hitIndexes = new List <int>(); IList <double> xValues = (ActualXValues is IList <double>) ? ActualXValues as IList <double> : GetXValues(); this.CalculateHittestRect(new Point(position.X, position.Y), out startIndex, out endIndex, out rect); for (int i = startIndex; i <= endIndex; i++) { this.hitPoint.X = this.IsIndexed ? i : xValues[i]; this.hitPoint.Y = this.YValues[i]; if (rect.Contains(this.hitPoint)) { hitIndexes.Add(i); } } if (hitIndexes.Count > 0) { int i = hitIndexes[hitIndexes.Count / 2]; hitIndexes = null; this.dataPoint = new ChartDataPointInfo(); dataPoint.Index = i; dataPoint.Series = this; dataPoint.XData = xValues[i]; dataPoint.YData = this.YValues[i]; if (ActualData.Count > i) { dataPoint.Item = this.ActualData[i]; } return(this.dataPoint); } else { return(this.dataPoint); } }
/// <summary> /// Classifies the point. /// </summary> /// <param name="point3D">The 3D Point</param> /// <param name="polygon3D">The 3D Polygon</param> /// <returns>Returns the classified point result.</returns> private static ClassifyPointResult ClassifyPoint(Vector3D point3D, Polygon3D polygon3D) { var res = ClassifyPointResult.OnPlane; var sv = -polygon3D.D - (point3D & polygon3D.Normal); if (sv > EPSILON) { res = ClassifyPointResult.OnBack; } else if (sv < -EPSILON) { res = ClassifyPointResult.OnFront; } return(res); }
/// <summary> /// Returns the intercept point of mouse ray with the specified plane. /// </summary> /// <param name="point">The point.</param> /// <param name="plane">The plane.</param> /// <returns></returns> public Vector3D ToPlane(Point point, Polygon3D plane) { var vec1 = new Vector3D(point.X, point.Y, 0); var vec2 = vec1 + new Vector3D(0, 0, 1); vec1 = centeredMatrix * vec1; vec2 = centeredMatrix * vec2; vec1 = Matrix3D.GetInvertal(perspective) * vec1; vec2 = Matrix3D.GetInvertal(perspective) * vec2; vec1 = plane.GetPoint(vec1, vec2 - vec1); vec1 = Matrix3D.GetInvertal(viewMatrix) * vec1; vec1 = Matrix3D.GetInvertal(centeredMatrix) * vec1; return(vec1); }
public override void Update(IChartTransformer transformer) { ChartTransform.ChartCartesianTransformer cartesianTransformer = transformer as ChartTransform.ChartCartesianTransformer; if (cartesianTransformer != null) { 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; // Clippiing the area series 3D. if (this.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; } } } if (this.yValues.Min() < yStart) { List <double> tempYVal = this.yValues.ToList(); foreach (var yVal in tempYVal) { if (yVal < yStart) { this.yValues[this.yValues.IndexOf(yVal)] = yStart; } } } if (this.yValues.Max() > yEnd) { List <double> tempYVal = this.yValues.ToList(); foreach (var yVal in tempYVal) { if (yVal > yEnd) { this.yValues[this.yValues.IndexOf(yVal)] = yEnd; } } } // End of clipping logic double x = this.xValues[0]; double y = !(Series as AreaSeries3D).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; List <Point> areaPoint = new List <Point>(); areaPoint.Add(previousPoint); this.topPolygonCollection = new Polygon3D[this.yValues.Count]; Vector3D vector1, vector2, vector3, vector4; for (int i = 1; i < this.xValues.Count; i++) { x = this.xValues[i]; y = !(Series as AreaSeries3D).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); vector1 = new Vector3D(previousPoint.X, previousPoint.Y, startDepth); vector2 = new Vector3D(currentPoint.X, currentPoint.Y, startDepth); vector3 = new Vector3D(currentPoint.X, currentPoint.Y, endDepth); vector4 = new Vector3D(previousPoint.X, previousPoint.Y, endDepth); var points = new Vector3D[] { vector1, vector2, vector3, vector4 }; this.topPolygonCollection[i] = new Polygon3D(points, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, Interior); this.topPolygonCollection[i].CalcNormal(points[0], points[1], points[2]); this.topPolygonCollection[i].CalcNormal(); previousPoint = currentPoint; areaPoint.Add(currentPoint); } x = this.xValues[0]; y = !(Series as AreaSeries3D).IsAnimated && !Series.EnableAnimation ? this.yValues[0] : (this.Y < this.yValues[0] && this.Y > 0) ? this.Y : this.yValues[0]; Point topLeft = transformer.TransformToVisible(x, y); x = this.xValues[this.xValues.Count - 1]; y = !(Series as AreaSeries3D).IsAnimated && !Series.EnableAnimation ? this.yValues[this.xValues.Count - 1] : (this.Y < this.yValues[this.yValues.Count - 1]) ? this.Y : this.yValues[this.yValues.Count - 1]; Point topRight = transformer.TransformToVisible(x, y); double origin = Series.ActualYAxis.Origin < yStart ? yStart : Series.ActualYAxis.Origin; x = this.xValues[0]; Point bottomLeft = transformer.TransformToVisible(x, origin); x = this.xValues[this.xValues.Count - 1]; Point bottomRight = transformer.TransformToVisible(x, origin); areaPoint.Add(bottomRight); areaPoint.Add(bottomLeft); Vector3D tlfVector = new Vector3D(topLeft.X, topLeft.Y, startDepth); Vector3D tldVector = new Vector3D(topLeft.X, topLeft.Y, endDepth); Vector3D trfVector = new Vector3D(topRight.X, topRight.Y, startDepth); Vector3D trdVector = new Vector3D(topRight.X, topRight.Y, endDepth); Vector3D blfVector = new Vector3D(bottomLeft.X, bottomLeft.Y, startDepth); Vector3D bldVector = new Vector3D(bottomLeft.X, bottomLeft.Y, endDepth); Vector3D brfVector = new Vector3D(bottomRight.X, bottomRight.Y, startDepth); Vector3D brdVector = new Vector3D(bottomRight.X, bottomRight.Y, endDepth); Vector3D[] leftVectors = new Vector3D[4] { tlfVector, tldVector, bldVector, blfVector }; Vector3D[] rightVectors = new Vector3D[4] { trfVector, trdVector, brdVector, brfVector }; Vector3D[] bottomVectors = new Vector3D[4] { blfVector, bldVector, brdVector, brfVector }; Vector3D[] frontVector = new Vector3D[areaPoint.Count]; Vector3D[] backVector = new Vector3D[areaPoint.Count]; for (int i = 0; i < areaPoint.Count; i++) { Point point = areaPoint[i]; frontVector[i] = new Vector3D(point.X, point.Y, startDepth); backVector[i] = new Vector3D(point.X, point.Y, endDepth); } if ((Series as AreaSeries3D).IsAnimated || !Series.EnableAnimation) { this.leftPolygon = new Polygon3D( leftVectors, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, Interior); this.leftPolygon.CalcNormal(leftVectors[0], leftVectors[1], leftVectors[2]); this.leftPolygon.CalcNormal(); this.area.Graphics3D.AddVisual(this.leftPolygon); this.rightPolygon = new Polygon3D( rightVectors, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, Interior); this.rightPolygon.CalcNormal(rightVectors[0], rightVectors[1], rightVectors[2]); this.rightPolygon.CalcNormal(); this.area.Graphics3D.AddVisual(this.rightPolygon); this.bottomPolygon = new Polygon3D( bottomVectors, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, Interior); this.bottomPolygon.CalcNormal(bottomVectors[0], bottomVectors[1], bottomVectors[2]); this.bottomPolygon.CalcNormal(); this.area.Graphics3D.AddVisual(this.bottomPolygon); this.frontPolygon = new Polygon3D( frontVector, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, Interior); this.frontPolygon.CalcNormal(frontVector[0], frontVector[1], frontVector[2]); this.frontPolygon.CalcNormal(); this.area.Graphics3D.AddVisual(this.frontPolygon); this.backPolygon = new Polygon3D( backVector, this, Series.Segments.IndexOf(this), Stroke, StrokeThickness, Interior); this.backPolygon.CalcNormal(backVector[0], backVector[1], backVector[2]); this.backPolygon.CalcNormal(); this.area.Graphics3D.AddVisual(this.backPolygon); for (int i = 1; i < this.yValues.Count; i++) { this.area.Graphics3D.AddVisual(this.topPolygonCollection[i]); } } } }
/// <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) { if (transformer == null) { return; } var cartesianTransformer = transformer as ChartTransform.ChartCartesianTransformer; if (cartesianTransformer == null) { return; } if (double.IsNaN(this.YData) && !Series.ShowEmptyPoints) { return; } var xBase = cartesianTransformer.XAxis.IsLogarithmic ? ((LogarithmicAxis3D)cartesianTransformer.XAxis).LogarithmicBase : 1; var xIsLogarithmic = cartesianTransformer.XAxis.IsLogarithmic; var left = xIsLogarithmic ? Math.Log(this.Left, xBase) : this.Left; var right = xIsLogarithmic ? Math.Log(this.Right, xBase) : this.Right; var yBase = cartesianTransformer.YAxis.IsLogarithmic ? ((LogarithmicAxis3D)cartesianTransformer.YAxis).LogarithmicBase : 1; var yIsLogarithmic = cartesianTransformer.YAxis.IsLogarithmic; var bottom = yIsLogarithmic ? Math.Pow(yBase, cartesianTransformer.YAxis.VisibleRange.Start) : cartesianTransformer.YAxis.VisibleRange.Start; var top = yIsLogarithmic ? Math.Pow(yBase, cartesianTransformer.YAxis.VisibleRange.End) : cartesianTransformer.YAxis.VisibleRange.End; var xStart = cartesianTransformer.XAxis.VisibleRange.Start; var xEnd = cartesianTransformer.XAxis.VisibleRange.End; double z1 = startDepth, z2 = endDepth; var zSeries = this.Series as XyzDataSeries3D; bool isZAxis = cartesianTransformer.ZAxis != null && zSeries.ActualZAxis != null && zSeries.ActualZValues != null; double spacing = (Series as ISegmentSpacing).SegmentSpacing; if (!(left <= xEnd && right >= xStart)) { return; } // WPF -14524 3D Column and Bar Series is rendering out of the pane. while cross the bar value to visualRange of axis. double topValue; if (this.Top < 0) { topValue = this.Top > bottom ? this.Top : bottom; } else { topValue = this.Top < top ? this.Top : top; } this.Bottom = this.Bottom > top ? top : this.Bottom; if (spacing > 0 && spacing <= 1) { double leftpos = (Series as ISegmentSpacing).CalculateSegmentSpacing(spacing, right, left); double rightpos = (Series as ISegmentSpacing).CalculateSegmentSpacing(spacing, left, right); this.Left = leftpos; this.Right = rightpos; } var area = Series.ActualArea as SfChart3D; var tlfVector = new Vector3D(0, 0, 0); var brbVector = new Vector3D(0, 0, 0); var tlpoint = transformer.TransformToVisible(left > xStart ? this.Left : xStart, topValue < bottom ? bottom : topValue); var rbpoint = transformer.TransformToVisible(xEnd > right ? this.Right : xEnd, bottom > this.Bottom ? bottom : this.Bottom); if (isZAxis) { double zStart = cartesianTransformer.ZAxis.VisibleRange.Start; double zEnd = cartesianTransformer.ZAxis.VisibleRange.End; var zIsLogarithmic = cartesianTransformer.ZAxis.IsLogarithmic; var zBase = zIsLogarithmic ? ((LogarithmicAxis3D)cartesianTransformer.ZAxis).LogarithmicBase : 1; var actualZ1 = zIsLogarithmic ? Math.Log(z1, zBase) : z1; var actualZ2 = zIsLogarithmic ? Math.Log(z2, zBase) : z2; if (!(actualZ1 <= zEnd && actualZ2 >= zStart)) { return; } tlfVector = cartesianTransformer.TransformToVisible3D(this.Left > xStart ? this.Left : xStart, topValue <bottom?bottom : topValue, z1> zStart ? z1 : zStart); brbVector = cartesianTransformer.TransformToVisible3D(xEnd > this.Right ? this.Right : xEnd, bottom > this.Bottom ? bottom : this.Bottom, zEnd > z2 ? z2 : zEnd); } else { var rect = new Rect(tlpoint, rbpoint); tlfVector = new Vector3D(rect.Left, rect.Top, z1); brbVector = new Vector3D(rect.Right, rect.Bottom, z2); } if (this.plans == null) { this.plans = Polygon3D.CreateBox( tlfVector, brbVector, this, Series.Segments.IndexOf(this), area.Graphics3D, this.Stroke, Interior, this.StrokeThickness, Series.IsActualTransposed); } else { Polygon3D.UpdateBox(this.plans, tlfVector, brbVector, this.Interior, tlpoint.Y == rbpoint.Y ? Visibility.Collapsed : Visibility.Visible); } }
/// <summary> /// Split the polygon. /// </summary> /// <param name="poly">The Polygon</param> /// <param name="part">The Part</param> /// <param name="backPoly">The Back Polygon</param> /// <param name="frontPoly">The Front Polygon</param> private static void SplitPolygon(Polygon3D poly, Polygon3D part, out Polygon3D[] backPoly, out Polygon3D[] frontPoly) { var backP = new List <Polygon3D>(); var frontP = new List <Polygon3D>(); // this code looks for points which lie on the part plane and divide polygon into two parts if (poly.Points != null) { var polyPoints = new List <Vector3DIndexClassification>(); var backPartPoints = new List <Vector3DIndexClassification>(); var frontPartPoints = new List <Vector3DIndexClassification>(); var outpts = new List <Vector3D>(); var inpts = new List <Vector3D>(); var count = poly.Points.Length; for (var i = 0; i < count; i++) { var ptB = poly.Points[i]; var ptC = poly.Points[BspTreeBuilder.GetNext(i + 1, count)]; var sideB = ClassifyPoint(ptB, part); var sideC = ClassifyPoint(ptC, part); var vwiwcB = new Vector3DIndexClassification(ptB, polyPoints.Count, sideB); polyPoints.Add(vwiwcB); if ((sideB != sideC) && (sideB != ClassifyPointResult.OnPlane) && (sideC != ClassifyPointResult.OnPlane)) { var v = ptB - ptC; var dir = part.Normal * (-part.D) - ptC; var sv = dir & part.Normal; var sect = sv / (part.Normal & v); var ptP = ptC + v * sect; var vwiwc = new Vector3DIndexClassification( ptP, polyPoints.Count, ClassifyPointResult.OnPlane); polyPoints.Add(vwiwc); backPartPoints.Add(vwiwc); frontPartPoints.Add(vwiwc); } else if (sideB == ClassifyPointResult.OnPlane) { var ptA = poly.Points[BspTreeBuilder.GetNext(i - 1, count)]; var sideA = ClassifyPoint(ptA, part); if ((sideA == sideC)) { continue; } if ((sideA != ClassifyPointResult.OnPlane) && (sideC != ClassifyPointResult.OnPlane)) { backPartPoints.Add(vwiwcB); frontPartPoints.Add(vwiwcB); } else if (sideA == ClassifyPointResult.OnPlane) { switch (sideC) { case ClassifyPointResult.OnBack: backPartPoints.Add(vwiwcB); break; case ClassifyPointResult.OnFront: frontPartPoints.Add(vwiwcB); break; } } else if (sideC == ClassifyPointResult.OnPlane) { switch (sideA) { case ClassifyPointResult.OnBack: backPartPoints.Add(vwiwcB); break; case ClassifyPointResult.OnFront: frontPartPoints.Add(vwiwcB); break; } } } } if ((frontPartPoints.Count != 0) || (backPartPoints.Count != 0)) { for (var i = 0; i < backPartPoints.Count - 1; i += 2) { var vwiwc1 = backPartPoints[i]; var vwiwc2 = backPartPoints[i + 1]; vwiwc1.CuttingBackPoint = true; vwiwc2.CuttingBackPoint = true; vwiwc1.CuttingBackPairIndex = vwiwc2.Index; vwiwc2.CuttingBackPairIndex = vwiwc1.Index; } for (var i = 0; i < frontPartPoints.Count - 1; i += 2) { var vwiwc1 = frontPartPoints[i]; var vwiwc2 = frontPartPoints[i + 1]; vwiwc1.CuttingFrontPoint = true; vwiwc2.CuttingFrontPoint = true; vwiwc1.CuttingFrontPairIndex = vwiwc2.Index; vwiwc2.CuttingFrontPairIndex = vwiwc1.Index; } for (var i = 0; i < backPartPoints.Count - 1; i++) { var vwiwc = backPartPoints[i]; if (vwiwc.AlreadyCuttedBack) { continue; } BspTreeBuilder.CutOutBackPolygon(polyPoints, vwiwc, outpts); if (outpts.Count > 2) { var points = outpts.ToArray(); var polygon = new Polygon3D(points, poly); polygon.CalcNormal(points[0], points[1], points[2]); polygon.CalcNormal(); backP.Add(polygon); } } for (var i = 0; i < frontPartPoints.Count - 1; i++) { var vwiwc = frontPartPoints[i]; if (vwiwc.AlreadyCuttedFront) { continue; } BspTreeBuilder.CutOutFrontPolygon(polyPoints, vwiwc, inpts); if (inpts.Count > 2) { var points = inpts.ToArray(); var polygon = new Polygon3D(points, poly); polygon.CalcNormal(points[0], points[1], points[2]); polygon.CalcNormal(); frontP.Add(polygon); } } } } else { backP.Add(poly); frontP.Add(poly); } backPoly = backP.ToArray(); frontPoly = frontP.ToArray(); }
/// <summary> /// Creates the <see cref="Polygon3D"/> with the specified values. /// </summary> /// <param name="vector1">The First Vector</param> /// <param name="vector2">The Second Vector</param> /// <param name="tag">The Tag</param> /// <param name="index">The Index</param> /// <param name="graphics3D">The Graphics 3D</param> /// <param name="stroke">The Stroke</param> /// <param name="fill">The Fill Color</param> /// <param name="strokeThickness">The Stroke Thickness</param> /// <param name="inverse">The Inverse</param> /// <returns>Returns the created <see cref="Polygon3D"/>.</returns> internal static Polygon3D[] CreateBox( Vector3D vector1, Vector3D vector2, DependencyObject tag, int index, Graphics3D graphics3D, Brush stroke, Brush fill, double strokeThickness, bool inverse) { var res = new Polygon3D[6]; var p1 = new[] { new Vector3D(vector1.X, vector1.Y, vector1.Z), new Vector3D(vector2.X, vector1.Y, vector1.Z), new Vector3D(vector2.X, vector2.Y, vector1.Z), new Vector3D(vector1.X, vector2.Y, vector1.Z) }; var p2 = new[] { new Vector3D(vector1.X, vector1.Y, vector2.Z), new Vector3D(vector2.X, vector1.Y, vector2.Z), new Vector3D(vector2.X, vector2.Y, vector2.Z), new Vector3D(vector1.X, vector2.Y, vector2.Z) }; var p3 = new[] { new Vector3D(vector1.X, vector1.Y, vector2.Z), new Vector3D(vector2.X, vector1.Y, vector2.Z), new Vector3D(vector2.X, vector1.Y, vector1.Z), new Vector3D(vector1.X, vector1.Y, vector1.Z) }; var p4 = new[] { new Vector3D(vector1.X, vector2.Y, vector2.Z), new Vector3D(vector2.X, vector2.Y, vector2.Z), new Vector3D(vector2.X, vector2.Y, vector1.Z), new Vector3D(vector1.X, vector2.Y, vector1.Z) }; var p5 = new[] { new Vector3D(vector1.X, vector1.Y, vector1.Z), new Vector3D(vector1.X, vector1.Y, vector2.Z), new Vector3D(vector1.X, vector2.Y, vector2.Z), new Vector3D(vector1.X, vector2.Y, vector1.Z) }; var p6 = new[] { new Vector3D(vector2.X, vector1.Y, vector1.Z), new Vector3D(vector2.X, vector1.Y, vector2.Z), new Vector3D(vector2.X, vector2.Y, vector2.Z), new Vector3D(vector2.X, vector2.Y, vector1.Z) }; res[0] = new Polygon3D(p1, tag, index, stroke, strokeThickness, fill); res[0].CalcNormal(p1[0], p1[1], p1[2]); res[0].CalcNormal(); res[1] = new Polygon3D(p2, tag, index, stroke, strokeThickness, fill); res[1].CalcNormal(p2[0], p2[1], p2[2]); res[1].CalcNormal(); res[2] = new Polygon3D(p3, tag, index, stroke, strokeThickness, fill); res[2].CalcNormal(p3[0], p3[1], p3[2]); res[2].CalcNormal(); res[3] = new Polygon3D(p4, tag, index, stroke, strokeThickness, fill); res[3].CalcNormal(p4[0], p4[1], p4[2]); res[3].CalcNormal(); res[4] = new Polygon3D(p5, tag, index, stroke, strokeThickness, fill); res[4].CalcNormal(p5[0], p5[1], p5[2]); res[4].CalcNormal(); res[5] = new Polygon3D(p6, tag, index, stroke, strokeThickness, fill); res[5].CalcNormal(p6[0], p6[1], p6[2]); res[5].CalcNormal(); if (inverse) { graphics3D.AddVisual(res[0]); graphics3D.AddVisual(res[1]); graphics3D.AddVisual(res[2]); graphics3D.AddVisual(res[3]); graphics3D.AddVisual(res[4]); graphics3D.AddVisual(res[5]); } else { graphics3D.AddVisual(res[5]); graphics3D.AddVisual(res[4]); graphics3D.AddVisual(res[0]); graphics3D.AddVisual(res[1]); graphics3D.AddVisual(res[2]); graphics3D.AddVisual(res[3]); } return(res); }
/// <summary> /// Removes the specified polygon. /// </summary> /// <param name="polygon">The polygon.</param> public void Remove(Polygon3D polygon) { this.Polygons.Remove(polygon); }
/// <summary> /// Creates the sector. /// </summary> /// <returns>Returns the sector.</returns> internal Polygon3D[][] CreateSector() { Points.Clear(); var count = (int)Math.Ceiling(ActualEndValue / 6d); if (count < 1d) { return(null); } var res = new Polygon3D[4][]; var f = ActualEndValue / count; var opts = new Point[count + 1]; var ipts = new Point[count + 1]; for (var i = 0; i < count + 1; i++) { var ox = (float)(Center.X + radius * Math.Cos((ActualStartValue + i * f) * DtoR)); var oy = (float)(Center.Y + radius * Math.Sin((ActualStartValue + i * f) * DtoR)); opts[i] = new Point(ox, oy); var ix = (float)(Center.X + inSideRadius * Math.Cos((ActualStartValue + i * f) * DtoR)); var iy = (float)(Center.Y + inSideRadius * Math.Sin((ActualStartValue + i * f) * DtoR)); ipts[i] = new Point(ix, iy); Points.Add(new Point(ox, oy)); } var oplgs = new Polygon3D[count]; #region outside rounded polygons for (var i = 0; i < count; i++) { Vector3D[] vts = { new Vector3D(opts[i].X, opts[i].Y, 0), new Vector3D(opts[i].X, opts[i].Y, depth), new Vector3D(opts[i + 1].X, opts[i + 1].Y, depth), new Vector3D(opts[i + 1].X, opts[i + 1].Y, 0) }; oplgs[i] = new Polygon3D(vts, this, Index, Stroke, StrokeThickness, Interior); oplgs[i].CalcNormal(vts[0], vts[1], vts[2]); oplgs[i].CalcNormal(); } res[1] = oplgs; #endregion #region inside rounded polygons for doughnut if (inSideRadius > 0) { var iplgs = new Polygon3D[count]; for (int i = 0; i < count; i++) { var vts = new[] { new Vector3D(ipts[i].X, ipts[i].Y, 0), new Vector3D(ipts[i].X, ipts[i].Y, depth), new Vector3D(ipts[i + 1].X, ipts[i + 1].Y, depth), new Vector3D(ipts[i + 1].X, ipts[i + 1].Y, 0) }; iplgs[i] = new Polygon3D(vts, this, Index, Stroke, StrokeThickness, Interior); iplgs[i].CalcNormal(vts[0], vts[1], vts[2]); iplgs[i].CalcNormal(); } res[3] = iplgs; } #endregion #region front and backside polygons(similar 2D accumulation) var tvtxs = new List <Vector3D>(); var bvtxs = new List <Vector3D>(); for (int i = 0; i < count + 1; i++) { tvtxs.Add(new Vector3D(opts[i].X, opts[i].Y, 0)); bvtxs.Add(new Vector3D(opts[i].X, opts[i].Y, depth)); } if (inSideRadius > 0) { for (int i = count; i > -1; i--) { tvtxs.Add(new Vector3D(ipts[i].X, ipts[i].Y, 0)); bvtxs.Add(new Vector3D(ipts[i].X, ipts[i].Y, depth)); } } else { tvtxs.Add(Center); bvtxs.Add(new Vector3D(Center.X, Center.Y, depth)); } var poly1 = new Polygon3D(tvtxs.ToArray(), this, Index, Stroke, StrokeThickness, Interior); poly1.CalcNormal(tvtxs.ToArray()[0], tvtxs.ToArray()[1], tvtxs.ToArray()[2]); poly1.CalcNormal(); var poly2 = new Polygon3D(bvtxs.ToArray(), this, Index, Stroke, StrokeThickness, Interior); poly2.CalcNormal(bvtxs.ToArray()[0], bvtxs.ToArray()[1], bvtxs.ToArray()[2]); poly2.CalcNormal(); res[0] = new[] { poly1, poly2 }; #endregion #region Inside two polygons for every segments if (inSideRadius > 0) { Vector3D[] rvts = { // To avoid overlap subtract 0.1 value for every segment start value(90 to 270 dgree) // and add 0.1 value for (270-360 and 0-90 degree) new Vector3D(opts[0].X, (ActualStartValue >= 0 && ActualStartValue <= 90) || (ActualStartValue >= 270 && ActualStartValue <= 360) ? opts[0].Y + 0.1 : opts[0].Y - 0.1, 0), new Vector3D(opts[0].X, (ActualStartValue >= 0 && ActualStartValue <= 90) || (ActualStartValue >= 270 && ActualStartValue <= 360) ? opts[0].Y + 0.1 : opts[0].Y - 0.1, depth), new Vector3D(ipts[0].X, ipts[0].Y, depth), new Vector3D(ipts[0].X, ipts[0].Y, 0) }; Vector3D[] lvts = { new Vector3D(opts[count].X, opts[count].Y, 0), new Vector3D(opts[count].X, opts[count].Y, depth), new Vector3D(ipts[count].X, ipts[count].Y, depth), new Vector3D(ipts[count].X, ipts[count].Y, 0) }; var poly3 = new Polygon3D(rvts, this, Index, Stroke, StrokeThickness, Interior); poly3.CalcNormal(rvts[0], rvts[1], rvts[2]); poly3.CalcNormal(); var poly4 = new Polygon3D(lvts, this, Index, Stroke, StrokeThickness, Interior); poly4.CalcNormal(lvts[0], lvts[1], lvts[2]); poly4.CalcNormal(); res[2] = new[] { poly3, poly4 }; } else { Vector3D[] rvts = { new Vector3D(opts[0].X, (ActualStartValue >= 0 && ActualStartValue <= 90) || (ActualStartValue >= 270 && ActualStartValue <= 360) ? opts[0].Y + 0.1 : opts[0].Y - 0.1, 0), new Vector3D(opts[0].X, (ActualStartValue >= 0 && ActualStartValue <= 90) || (ActualStartValue >= 270 && ActualStartValue <= 360) ? opts[0].Y + 0.1 : opts[0].Y - 0.1, depth), new Vector3D(Center.X, Center.Y, depth), new Vector3D(Center.X, Center.Y, 0) }; Vector3D[] lvts = { new Vector3D(opts[count].X, opts[count].Y, 0), new Vector3D(opts[count].X, opts[count].Y, depth), new Vector3D(Center.X, Center.Y, depth), new Vector3D(Center.X, Center.Y, 0) }; var poly5 = new Polygon3D(rvts, this, Index, Stroke, StrokeThickness, Interior); poly5.CalcNormal(rvts[0], rvts[1], rvts[2]); poly5.CalcNormal(); var poly6 = new Polygon3D(lvts, this, Index, Stroke, StrokeThickness, Interior); poly6.CalcNormal(lvts[0], lvts[1], lvts[2]); poly6.CalcNormal(); res[2] = new[] { poly5, poly6 }; } #endregion return(res); }
/// <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); } } }
/// <summary> /// Renders the 3D tick lines. /// </summary> /// <param name="linesRecycler">The Line Recycler</param> /// <param name="orientation">The Orientation</param> /// <param name="tickSize">The Tick Size</param> /// <param name="tickPosition">The Tick Position</param> /// <param name="values">The Values</param> private void RenderTicks3D( UIElementsRecycler <Line> linesRecycler, Orientation orientation, double tickSize, AxisElementPosition tickPosition, IList <double> values) { var area3D = Axis.Area as SfChart3D; var actualRotationAngle = area3D.ActualRotationAngle; var labelsCount = values.Count; var linesCount = linesRecycler.Count; for (var i = 0; i < labelsCount; i++) { if (i >= linesCount) { continue; } double x1 = 0, y1 = 0, x2 = 0, y2 = 0; var line = linesRecycler[i]; var value = Axis.ValueToCoefficientCalc(values[i]); value = double.IsNaN(value) ? 0 : value; if (orientation == Orientation.Horizontal) { var tempaxis = axis as ChartAxisBase3D; if (tempaxis.IsManhattanAxis && (axis.RegisteredSeries[i] as ChartSeries3D).Segments != null && (axis.RegisteredSeries[i] as ChartSeries3D).Segments.Count > 0) { var segment = (axis.RegisteredSeries[i] as ChartSeries3D).Segments[0] as ChartSegment3D; x1 = x2 = segment.startDepth + (segment.endDepth - segment.startDepth) / 2; } else { x1 = x2 = Math.Round(Axis.ActualPlotOffset + (Axis.RenderedRect.Width * value)); } } else { y1 = y2 = Math.Round(Axis.ActualPlotOffset + (Axis.RenderedRect.Height * (1 - value))); } CalculatePosition3D(tickPosition, tickSize, ref x1, ref y1, ref x2, ref y2, actualRotationAngle); var verticalAxis = area3D.InternalSecondaryAxis.Orientation == Orientation.Vertical ? area3D.InternalSecondaryAxis : area3D.InternalPrimaryAxis; if ((axis as ChartAxisBase3D).IsZAxis) { // Adding one to prevent the tick hidding. var leftPosition = !verticalAxis.OpposedPosition && actualRotationAngle >= 0 && actualRotationAngle < 180 ? axis.ArrangeRect.Left + 1 : axis.ArrangeRect.Left; ((SfChart3D)Axis.Area).Graphics3D.AddVisual(Polygon3D.CreateLine(line, leftPosition, y1, leftPosition, y2, x1, x1, false)); } else { double depth = 0d; var axis3D = this.axis as ChartAxisBase3D; Line3D line3D = null; if (orientation == Orientation.Vertical) { if (axis.ShowAxisNextToOrigin) { if (actualRotationAngle >= 90 && actualRotationAngle < 270) { depth = (axis.Area as SfChart3D).ActualDepth; } line3D = Polygon3D.CreateLine(line, x1, y1, x2, y2, depth, depth, true); } else { if (axis3D.AxisPosition3D == AxisPosition3D.DepthBackRight || axis3D.AxisPosition3D == AxisPosition3D.DepthBackLeft || axis3D.AxisPosition3D == AxisPosition3D.DepthFrontRight || axis3D.AxisPosition3D == AxisPosition3D.DepthFrontLeft) { line3D = Polygon3D.CreateLine(line, axis.ArrangeRect.Left, y1, axis.ArrangeRect.Left, y2, x1, x2, false); } else { depth = axis3D.AxisDepth; line3D = Polygon3D.CreateLine(line, x1, y1, x2, y2, depth, depth, true); } } } else { depth = axis3D.AxisDepth; line3D = Polygon3D.CreateLine(line, x1, y1, x2, y2, depth, depth, true); } ((SfChart3D)Axis.Area).Graphics3D.AddVisual(line3D); } } }
/// <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) { Rect rect; double x, y, width, height; if (transformer == null) { return; } var cartesianTransformer = transformer as ChartTransform.ChartCartesianTransformer; if (cartesianTransformer == null) { return; } if (double.IsNaN(YData) && !Series.ShowEmptyPoints) { return; } ScatterSeries3D series = (Series as ScatterSeries3D); 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; var xValue = xIsLogarithmic ? Math.Log(X, xBase) : X; var yValue = yIsLogarithmic ? Math.Log(Y, yBase) : Y; var yStart = cartesianTransformer.YAxis.VisibleRange.Start; var yEnd = cartesianTransformer.YAxis.VisibleRange.End; var xStart = cartesianTransformer.XAxis.VisibleRange.Start; var xEnd = cartesianTransformer.XAxis.VisibleRange.End; var zSeries = this.Series as XyzDataSeries3D; bool isZAxis = cartesianTransformer.ZAxis != null && zSeries.ActualZAxis != null && (zSeries as XyzDataSeries3D).ActualZValues != null; Point tlpoint = new Point(0, 0); double frontDepth = 0d; double backDepth = 0d; if (isZAxis) { var z1value = startDepth; var z2value = endDepth; var depthDelta = (this.Series as ScatterSeries3D).GetSegmentDepth((this.Series.ActualArea as SfChart3D).ActualDepth).Delta / 2; var zStart = cartesianTransformer.ZAxis.VisibleRange.Start; var zEnd = cartesianTransformer.ZAxis.VisibleRange.End; var zIsLogarithmic = cartesianTransformer.ZAxis.IsLogarithmic; var zBase = zIsLogarithmic ? ((LogarithmicAxis3D)cartesianTransformer.ZAxis).LogarithmicBase : 1; var actualZ1 = zIsLogarithmic ? Math.Log(z1value, zBase) : z1value; var actualZ2 = zIsLogarithmic ? Math.Log(z2value, zBase) : z2value; if (!(actualZ1 <= zEnd && actualZ2 >= zStart)) { return; } var zLogStart = zIsLogarithmic ? Math.Pow(zBase, zStart) : zStart; var zLogEnd = zIsLogarithmic ? Math.Pow(zBase, zEnd) : zEnd; var tldpoint = cartesianTransformer.TransformToVisible3D(xValue, yValue, actualZ1 <zStart?zLogStart : actualZ1> zEnd ? zLogEnd : z1value); tlpoint = new Point(tldpoint.X, tldpoint.Y); frontDepth = (z1value == zStart) ? tldpoint.Z : tldpoint.Z - ScatterHeight / 2 < tldpoint.Z - depthDelta ? tldpoint.Z - depthDelta : tldpoint.Z - ScatterHeight / 2; backDepth = (z2value == zEnd) ? tldpoint.Z : tldpoint.Z + ScatterHeight / 2 > tldpoint.Z + depthDelta ? tldpoint.Z + depthDelta : tldpoint.Z + ScatterHeight / 2; } else { tlpoint = transformer.TransformToVisible(X, Y); } if (!series.Area.SeriesClipRect.Contains(tlpoint) && ((xValue != xEnd && xValue != xStart) || (yValue != yEnd && yValue != yStart)) && !(series.IsTransposed)) { return; } if (series.ScatterHeight <= 0 || series.ScatterWidth <= 0) { return; } x = (xValue == (series.IsTransposed ? xEnd : xStart)) ? tlpoint.X : tlpoint.X - (series.IsTransposed ? ScatterHeight / 2 : ScatterWidth / 2); y = (yValue == (series.IsTransposed ? yStart : yEnd)) ? tlpoint.Y : tlpoint.Y - (series.IsTransposed ? ScatterWidth / 2 : ScatterHeight / 2); width = (xValue == xStart) || (xValue == xEnd) ? ScatterWidth / 2 : ScatterWidth; height = (yValue == yStart) || (yValue == yEnd) ? ScatterHeight / 2 : ScatterHeight; rect = new Rect(x, y, width, height); if (!series.IsTransposed) { // Clipping segment of nearest range point if (!Series.ActualArea.SeriesClipRect.Contains(new Point(x, y))) { rect = new Rect(x, Series.ActualArea.SeriesClipRect.Top, width, height + y); } if (!Series.ActualArea.SeriesClipRect.Contains(new Point(rect.Left, rect.Bottom))) { rect = new Rect(x, y, width, Math.Abs(height + (Series.ActualArea.SeriesClipRect.Bottom - rect.Bottom) > ScatterHeight ? height : height + (Series.ActualArea.SeriesClipRect.Bottom - rect.Bottom))); } if (!Series.ActualArea.SeriesClipRect.Contains(new Point(rect.Left, rect.Top))) { var modifiedWidth = Math.Abs(width - (Series.ActualXAxis.RenderedRect.X - rect.X)); rect = new Rect(Series.ActualXAxis.RenderedRect.X, y, modifiedWidth, rect.Height); } if (!Series.ActualArea.SeriesClipRect.Contains(new Point(rect.Left + rect.Width, rect.Top))) { var modifiedWidth = Math.Abs(rect.Width + (Series.ActualArea.SeriesClipRect.Right - rect.Right)); rect = new Rect(rect.X, rect.Y, modifiedWidth, rect.Height); } } else { rect = new Rect(x, y, height, width); if (x < tlpoint.X && xValue == xStart && yValue == yStart) { rect = new Rect(tlpoint.X, y, height, width); } if (y < tlpoint.Y && yValue == yStart) { rect = new Rect(tlpoint.X, tlpoint.Y, height, width); } if (y == tlpoint.Y && yValue == yStart) { rect = new Rect(tlpoint.X, tlpoint.Y - ScatterWidth / 2, height, width); } if (y < tlpoint.Y && xValue == xEnd) { rect = new Rect(tlpoint.X, tlpoint.Y, height, width); } if (x == tlpoint.X && xValue == xEnd) { rect = new Rect(tlpoint.X, tlpoint.Y, height, width); } if (x == tlpoint.X && xValue == xEnd && yValue != yStart) { rect = new Rect(tlpoint.X - ScatterHeight / 2, tlpoint.Y, height, width); } } var area = Series.ActualArea as SfChart3D; Vector3D tlfVector = new Vector3D(0, 0, 0); Vector3D brbVector = new Vector3D(0, 0, 0); if (isZAxis) { tlfVector = new Vector3D(rect.Left, rect.Top, frontDepth); brbVector = new Vector3D(rect.Right, rect.Bottom, backDepth); } else { tlfVector = new Vector3D(rect.Left, rect.Top, startDepth); brbVector = new Vector3D(rect.Right, rect.Bottom, startDepth + ScatterHeight > endDepth ? endDepth : startDepth + ScatterHeight); } if (plans == null) { plans = Polygon3D.CreateBox( tlfVector, brbVector, this, series.Segments.IndexOf(this), area.Graphics3D, Stroke, Interior, StrokeThickness, Series.IsActualTransposed); } else { Polygon3D.UpdateBox(plans, tlfVector, brbVector, Interior, Visibility.Visible); } }
/// <summary> /// Removes the specified polygon. /// </summary> /// <param name="polygon">The polygon.</param> public void Remove(Polygon3D polygon) { this.treeBuilder.Remove(polygon); }
/// <summary> /// Adds the specified poly. /// </summary> /// <param name="poly">The poly.</param> /// <returns>Returns the last index.</returns> public int Add(Polygon3D poly) { this.Polygons.Add(poly); return(this.Polygons.Count - 1); }