private void ArrangeRadially(double angle, Point center, double radius) { Point location = RadialGaugePanel.CreateRotatedPoint(angle, radius, center, RadRadialGauge.GetIndicatorRadiusScale(this)); Canvas.SetLeft(this.visualElement, location.X); Canvas.SetTop(this.visualElement, location.Y); }
private void ArrangeLabel(ContentPresenter label, Size finalSize, double currentTickAngle, double radiusScale) { Size desiredSize = label.DesiredSize; double radius = Math.Min(finalSize.Width, finalSize.Height) / 2; Point center = GetIndicatorOffset(desiredSize, finalSize); var gauge = this.OwnerGauge as RadRadialGauge; double angle = 0; if (this.sweepDir == SweepDirection.Clockwise) { angle = RadialGaugePanel.ConvertDegreesToRadians(gauge.MinAngle) + RadialGaugePanel.ConvertDegreesToRadians(currentTickAngle); } else { angle = RadialGaugePanel.ConvertDegreesToRadians(gauge.MaxAngle) - RadialGaugePanel.ConvertDegreesToRadians(currentTickAngle); } Point labelPosition = CreateRotatedPoint(angle, radius, center, radiusScale); if ((TickType)label.GetValue(RadGauge.TickTypeProperty) == TickType.Label) { labelPosition.X -= desiredSize.Width * Math.Cos(angle) / 3; } label.Arrange(new Rect(labelPosition, desiredSize)); }
private void ArrangeMarker(Size desiredSize, double newValue) { if (this.Owner == null) { return; } double radius = Math.Min(desiredSize.Width, desiredSize.Height) / 2; switch (this.Owner.OwnerGauge.GaugeType) { case GaugeType.Linear: double distance = RadGauge.MapLogicalToPhysicalValue(newValue - this.minValue, this.isHorizontal ? desiredSize.Width : desiredSize.Height, this.MinMaxValueDifference); this.ArrangeLinearly(distance, this.CreateStartPoint(desiredSize), this.CreateDirection()); break; case GaugeType.Radial: double angleInDegrees = RadGauge.MapLogicalToPhysicalValue(newValue - this.Owner.OwnerGauge.MinValue, this.maxAngle - this.minAngle, this.MinMaxValueDifference); double currentAngle = this.minAngle + angleInDegrees; if (this.IsRotated) { this.visualElementRotation.Angle = this.initialRotationAngle + currentAngle; } else { this.visualElementRotation.Angle = this.initialRotationAngle; } double angleInRadians = RadialGaugePanel.ConvertDegreesToRadians(currentAngle); Point center = new Point((desiredSize.Width / 2) - (this.visualElement.DesiredSize.Width / 2), (desiredSize.Height / 2) - (this.visualElement.DesiredSize.Height / 2)); this.ArrangeRadially(angleInRadians, center, radius); break; } }
/// <summary> /// Calculates and angle in degrees based on a value, a value range, an angle range and a sweep direction. /// </summary> /// <param name="context">A context that contains the value to be converted to an angle.</param> /// <returns>Returns an angle in radians that corresponds to the provided value in the context.</returns> internal static double CalculateAngle(CalculateAngleContext context) { double angleDeg = RadGauge.MapLogicalToPhysicalValue(context.value - context.startValue, context.gaugePhysicalLength, context.gaugeLogicalLength); var angle = RadialGaugePanel.ConvertDegreesToRadians(angleDeg); return(RadialGaugePanel.ConvertDegreesToRadians(context.minAngle) + angle); }
private void UpdateCore() { var startAngle = RadialGaugePanel.ConvertDegreesToRadians(this.MinAngle); double angle = RadialGaugePanel.CalculateAngle(this.CreateCalculateAngleContext(this.ActualValue)); if (startAngle > angle) { var tmp = startAngle; startAngle = angle; angle = tmp; } this.figure.StartPoint = RadialGaugePanel.CreateRotatedPoint(startAngle, this.Radius, this.Center, this.RadiusScale); RadialBarGaugeIndicator.UpdateArc(this.CreateUpdateArcContext(angle, startAngle / Math.PI * 180)); }
/// <summary> /// Updates an arc segment with the provided data. /// </summary> /// <param name="context">A context for the arc to be updated. the arc to update is a part of the context.</param> internal static void UpdateArc(UpdateArcContext context) { context.angle = context.arc.SweepDirection == SweepDirection.Clockwise ? context.angle : -context.angle; var arcWidth = Math.Abs(context.angle - RadialGaugePanel.ConvertDegreesToRadians(context.minAngle)); // Ensure that start and endpoint will not match, so that arc is displayed. if (arcWidth >= 2 * Math.PI) { context.angle -= Math.Sign(context.angle - context.minAngle) * 0.01; } Point arcEndPoint = RadialGaugePanel.CreateRotatedPoint(context.angle, context.radius, context.center, 1); context.arc.IsLargeArc = arcWidth > Math.PI; context.arc.Size = new Size(context.radius, context.radius); context.arc.Point = arcEndPoint; }
/// <summary> /// This method is called whenever the segments /// need to recreate their visual representation. /// </summary> /// <param name="availableSize">The available size which the visual parts can occupy.</param> internal override void ResetSegments(Size availableSize) { this.PrepareReset(availableSize); this.SegmentInfos.Clear(); var currentstartAngle = this.minAngle; var angleSpan = this.maxAngle - this.minAngle; foreach (BarIndicatorSegment segment in this.Segments) { if (segment.Path == null) { Debug.Assert(false, "Missing segment path."); continue; } double lengthRatio = segment.Length / this.TotalSegmentLength; double angle = currentstartAngle + (angleSpan * lengthRatio); PathFigure figure = new PathFigure(); double startAngleInRadians = RadialGaugePanel.ConvertDegreesToRadians(currentstartAngle); figure.StartPoint = RadialGaugePanel.CreateRotatedPoint(startAngleInRadians, this.radius, this.center, this.radiusScale); ArcSegment newArc = new ArcSegment(); newArc.Point = figure.StartPoint; newArc.SweepDirection = SweepDirection.Clockwise; this.SegmentInfos.Add(new SegmentInfo() { PathSegment = newArc, Start = startAngleInRadians, End = RadialGaugePanel.ConvertDegreesToRadians(angle) }); figure.Segments.Add(newArc); PathGeometry pathGeom = new PathGeometry(); pathGeom.Figures.Add(figure); Path path = segment.Path; path.Stroke = segment.Stroke; path.StrokeThickness = segment.Thickness; path.Data = pathGeom; currentstartAngle = angle; } }
/// <summary> /// This method is called so that a segmented indicator can synchronize /// its visual state with its current value. /// </summary> /// <param name="value">The value to synchronize with.</param> internal override void SyncWithValue(double value) { double currentAngle = RadialGaugePanel.CalculateAngle(this.CreateCalculateAngleContext(value)); foreach (SegmentInfo info in this.SegmentInfos) { ArcSegment arc = (ArcSegment)info.PathSegment; if (currentAngle >= info.Start && currentAngle <= info.End) { RadialBarGaugeIndicator.UpdateArc(this.CreateUpdateArcContext(currentAngle, arc)); arc.IsLargeArc = Math.Abs(currentAngle - info.Start) > Math.PI; } else if (currentAngle > info.End) { RadialBarGaugeIndicator.UpdateArc(this.CreateUpdateArcContext(info.End, arc)); arc.IsLargeArc = Math.Abs(info.End - info.Start) > Math.PI; } else if (currentAngle <= info.Start) { RadialBarGaugeIndicator.UpdateArc(this.CreateUpdateArcContext(info.Start, arc)); arc.IsLargeArc = false; } } }