使用StreamGeometryContext绘制点几何

时间:2015-12-16 11:59:21

标签: c# wpf math gis

尝试使用C#中的GeometryContext绘制极坐标类型图表。我将方向输入为xRange(开始和停止),以度为单位。我把它转换成Radians。都好。 yRange被切入&以m / s为单位切出风速为双倍。我试图在没有轴标签等的情况下实现下面图像的简化版本。

enter image description here

对于要绘制图表的每个对象,我将返回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);
            }
       }

那么如何参考风速来创建绘图范围内的实际点?

1 个答案:

答案 0 :(得分:1)

图表扇区的四个点位于两个同心圆上,其中内圆的半径由起始风速给出,而外圆的半径由最终风速给出。每个圆上的点的位置直接由弧度的风向给出。

如果风向有变量startDirectionendDirection,风速有startSpeedendSpeed,那么扇区将如下构建:< / 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);
}