private static Geometry ProcessGeometryHorizontalTraverse(GunPitchLimitsComponent traverse, TurretYawLimits yawLimits, Point center, double geometryRotation, Geometry geometry, double maxRadius) { if (yawLimits == null || yawLimits.Range == 360) { return(geometry); } else { // create a horizontal fan var fanFigure = new PathFigure { StartPoint = center }; var point = GunTraverseHelper.PolarToCartesian(center, maxRadius, 360 - yawLimits.Right + geometryRotation); fanFigure.Segments.Add(new LineSegment(point, true)); point = GunTraverseHelper.PolarToCartesian(center, maxRadius, -yawLimits.Left + geometryRotation); fanFigure.Segments.Add(new ArcSegment(point, new Size(maxRadius, maxRadius), yawLimits.Range, yawLimits.Range > 180, SweepDirection.Counterclockwise, true)); fanFigure.IsClosed = true; var fanGeometry = new PathGeometry(); fanGeometry.Figures.Add(fanFigure); return(new CombinedGeometry(GeometryCombineMode.Intersect, geometry, fanGeometry)); } }
public static Geometry CreateGeometry(GunPitchLimitsComponent traverse, TurretYawLimits yawLimits, double size, Point center, double geometryRotation = 0, double margin = 0, double padding = 0, Func <double, double> verticalTraverseTransform = null) { if (verticalTraverseTransform == null) { verticalTraverseTransform = GunTraverseHelper.DefaultVerticalTraverseTransform; } if (traverse.HasSingularValue && yawLimits.Range == 360) { var radius = size / 2 - margin; return(new EllipseGeometry(center, radius, radius)); } else { var maxRadiusInDegrees = traverse.GetMaxValue(); var scale = (size / 2 - margin - padding) / maxRadiusInDegrees; Func <double, double> radiusConverter = r => padding + Math.Max(verticalTraverseTransform(r) * scale, 0); return(GunTraverseHelper.CreateGeometry(traverse, yawLimits, center, radiusConverter, geometryRotation)); } }
public void SetTraverse(GunPitchLimitsComponent gunPitch, TurretYawLimits turretYaw) { this.CurveCanvas.Children.Clear(); if (gunPitch == null) { return; } var traverseFigureStrokeStyle = this.FindResource("TraverseFigure") as Style; var maxRadius = gunPitch.GetMaxValue(); //maxRadius = Math.Ceiling(maxRadius / 5) * 5; const double margin = 1; var scale = 80 / (maxRadius + margin); var size = scale * maxRadius * 2; var center = new Point(100, 100); var figurePath = new Path { Data = GunTraverseHelper.CreateGeometry(gunPitch, turretYaw, size, center, 90, scale * margin, verticalTraverseTransform: v => v + 1), Style = traverseFigureStrokeStyle }; this.CurveCanvas.Children.Add(figurePath); // draw references var thinReferenceGeometry = new GeometryGroup(); var thickReferenceGeometry = new GeometryGroup(); const double referenceCircleGap = 20; const double halfReferenceCircleGap = referenceCircleGap / 2; var sign = Math.Sign(maxRadius); var absMaxRadius = Math.Abs(maxRadius); var thickDivisor = absMaxRadius > 45 ? 20 : absMaxRadius > 25 ? 10 : 5; var thinDivisor = absMaxRadius > 25 ? 5 : 1; for (var i = thinDivisor; i <= absMaxRadius; i += thinDivisor) { var radius = scale * i * sign; Geometry geometry; var isThickRing = i % thickDivisor == 0; if (absMaxRadius < 10 || isThickRing) { var gapHalfAngle = Math.Asin(halfReferenceCircleGap / radius) * 180 / Math.PI; if (double.IsNaN(gapHalfAngle)) { gapHalfAngle = 180; } var startPoint = GunTraverseHelper.PolarToCartesian(center, radius, gapHalfAngle); var endPoint = GunTraverseHelper.PolarToCartesian(center, radius, 360 - gapHalfAngle); var arc = new ArcSegment(endPoint, new Size(radius, radius), 360 - gapHalfAngle * 2, true, SweepDirection.Counterclockwise, true); var figure = new PathFigure(startPoint, new[] { arc }, false); geometry = new PathGeometry(new[] { figure }); var referenceTextContainer = new Grid { Width = 20, Height = referenceCircleGap }; var referenceTextContainerPosition = GunTraverseHelper.PolarToCartesian(center, radius, 0); Canvas.SetLeft(referenceTextContainer, referenceTextContainerPosition.X - 10); Canvas.SetTop(referenceTextContainer, referenceTextContainerPosition.Y - halfReferenceCircleGap); var referenceText = new TextBlock { Text = (i * sign).ToString(), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, FontSize = isThickRing ? 10 : 8, Foreground = isThickRing ? Brushes.White : new SolidColorBrush(Color.FromArgb(0x80, 0xff, 0xff, 0xff)) }; referenceTextContainer.Children.Add(referenceText); this.CurveCanvas.Children.Add(referenceTextContainer); } else { geometry = new EllipseGeometry(center, radius, radius); } if (isThickRing) { thickReferenceGeometry.Children.Add(geometry); } else { thinReferenceGeometry.Children.Add(geometry); } } var thinReferencePath = new Path { Data = thinReferenceGeometry, Style = this.FindResource("ThinReferenceStroke") as Style }; this.CurveCanvas.Children.Add(thinReferencePath); var thickReferencePath = new Path { Data = thickReferenceGeometry, Style = this.FindResource("ThickReferenceStroke") as Style }; this.CurveCanvas.Children.Add(thickReferencePath); }
public static Geometry CreateGeometry(GunPitchLimitsComponent traverse, TurretYawLimits yawLimits, Point center, Func <double, double> radiusConverter, double geometryRotation = 0) { Geometry geometry; double maxRadius; var data = traverse.Data; if (traverse.HasSingularValue) { var radius = radiusConverter(data[0].Limit); geometry = new EllipseGeometry(center, radius, radius); maxRadius = radius; } else { maxRadius = radiusConverter(traverse.GetMaxValue()); var figureFigure = new PathFigure(); var previousTheta = 0.0; var previousRadius = 0.0; var previousNode = (GunPitchLimitsComponent.PitchData)null; for (var i = 0; i < data.Length; ++i) { var node = data[i]; var theta = geometryRotation + node.Angle * 360; var radius = radiusConverter(node.Limit); var point = GunTraverseHelper.PolarToCartesian(center, radius, theta); var thetaRange = theta - previousTheta; if (i == 0) { figureFigure.StartPoint = point; } else { Debug.Assert(previousNode != null, "previousNode != null"); if (previousNode.Angle == node.Angle) { figureFigure.Segments.Add(new LineSegment(point, true)); } else if (previousNode.Limit == node.Limit) { figureFigure.Segments.Add(new ArcSegment(point, new Size(radius, radius), thetaRange, thetaRange >= 180, SweepDirection.Counterclockwise, true)); } else { figureFigure.Segments.Add(GunTraverseHelper.CreateTraverseFigureTransition(ref figureFigure, ref center, previousTheta, thetaRange, previousRadius, radius)); } } previousTheta = theta; previousNode = node; previousRadius = radius; } var pathGeometry = new PathGeometry(); pathGeometry.Figures.Add(figureFigure); geometry = pathGeometry; } return(GunTraverseHelper.ProcessGeometryHorizontalTraverse(traverse, yawLimits, center, geometryRotation, geometry, maxRadius)); }