尝试使用C#中的GeometryContext绘制极坐标类型图表。我将方向输入为xRange
(开始和停止),以度为单位。我把它转换成Radians。都好。 yRange
被切入&以m / s为单位切出风速为双倍。我试图在没有轴标签等的情况下实现下面图像的简化版本。
对于要绘制图表的每个对象,我将返回XY范围:
public IEnumerable<Styled2DRange> Query()
{
SolidColorBrush brush = new SolidColorBrush(Colors.Maroon);
brush.Freeze();
Pen linePen = new Pen(brush, 3);
linePen.Freeze();
SolidColorBrush fillBrush = new SolidColorBrush(Colors.Maroon);
fillBrush.Freeze();
foreach (var range in this.Charts)
{
Range xRange = new Range(ConvertToRadians(range.StartDirection), ConvertToRadians(range.EndDirection));
Range yRange = new Range(range.CutInWindSpeed, range.CutOutWindSpeed);
yield return new 2DRange()
{
Range = new XYRange()
{
XRange = xRange,
YRange = yRange
},
Line = linePen,
Fill = fillBrush
};
}
yield break;
}
从我覆盖Onrender
调用此方法。显然,由StreamGeometryContext
绘制的点数没有意义,因为Range.Y值只是以m / s为单位的风速:
protected override void OnRender(DrawingContext dc)
{
Point origin = new Point(0, 0);
double maxR = 0;
SweepDirection outerSweep = SweepDirection.Clockwise;
SweepDirection innerSweep = SweepDirection.Counterclockwise;
outerSweep = SweepDirection.Counterclockwise;
innerSweep = SweepDirection.Clockwise;
foreach (Styled2DRange range in Query())
{
maxR = Math.Max(maxR, range.Range.YRange.End);
Point outerScreenPointBefore = new Point(range.Range.XRange.Start, range.Range.YRange.End);
Point outerScreenPointAfter = new Point(range.Range.XRange.End, range.Range.YRange.End);
Point innerScreenPointBefore = new Point(range.Range.XRange.Start, range.Range.YRange.Start);
Point innerScreenPointAfter = new Point(range.Range.XRange.End, range.Range.YRange.Start);
StreamGeometry sectorGeometry = new StreamGeometry();
sectorGeometry.FillRule = FillRule.Nonzero;
using (StreamGeometryContext geometryContext = sectorGeometry.Open())
{
geometryContext.BeginFigure(innerScreenPointBefore, true, true);
geometryContext.LineTo(outerScreenPointBefore, true, false);
double outerCircleRadius = Math.Sqrt(Math.Pow(outerScreenPointBefore.X - origin.X, 2) + Math.Pow(outerScreenPointBefore.Y - origin.Y, 2));
geometryContext.ArcTo(outerScreenPointAfter, new Size(outerCircleRadius, outerCircleRadius), 0, false, outerSweep, true, false);
geometryContext.LineTo(innerScreenPointAfter, true, false);
double innerCircleRadius = Math.Sqrt(Math.Pow(innerScreenPointBefore.X - origin.X, 2) + Math.Pow(innerScreenPointBefore.Y - origin.Y, 2));
geometryContext.ArcTo(innerScreenPointBefore, new Size(innerCircleRadius, innerCircleRadius), 0, false, innerSweep, true, false);
}
sectorGeometry.Freeze();
dc.DrawGeometry(range.Fill, range.Line, sectorGeometry);
}
}
那么如何参考风速来创建绘图范围内的实际点?
答案 0 :(得分:1)
图表扇区的四个点位于两个同心圆上,其中内圆的半径由起始风速给出,而外圆的半径由最终风速给出。每个圆上的点的位置直接由弧度的风向给出。
如果风向有变量startDirection
和endDirection
,风速有startSpeed
和endSpeed
,那么扇区将如下构建:< / p>
var pStart = new Point(Math.Sin(startDirection), -Math.Cos(startDirection));
var pEnd = new Point(Math.Sin(endDirection), -Math.Cos(endDirection));
var isLargeArc = Math.Abs(endDirection - startDirection) > Math.PI;
var geometry = new StreamGeometry();
using (var sgc = geometry.Open())
{
sgc.BeginFigure( // start point on inner circle
new Point(startSpeed * pStart.X, startSpeed * pStart.Y),
true, true);
sgc.ArcTo( // end point on inner circle
new Point(startSpeed * pEnd.X, startSpeed * pEnd.Y),
new Size(startSpeed, startSpeed), // radius of inner circle
0d, isLargeArc, SweepDirection.Clockwise, true, true);
sgc.LineTo( // end point on outer circle
new Point(endSpeed * pEnd.X, endSpeed * pEnd.Y),
true, true);
sgc.ArcTo( // start point on outer circle
new Point(endSpeed * pStart.X, endSpeed * pStart.Y),
new Size(endSpeed, endSpeed), // radius of outer circle
0d, isLargeArc, SweepDirection.Counterclockwise, true, true);
}