65.9K
CodeProject 正在变化。 阅读更多。
Home

GraphDisplay: 一个基于 Bezier 曲线的绘制函数和曲线的控件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2012年7月8日

CPOL

1分钟阅读

viewsIcon

15169

这是“GraphDisplay: 一个基于 Bezier 曲线的绘制函数和曲线的控件”的替代方案

引言

我非常喜欢这种方法,并打算将这段代码作为一个库在我的一个项目中中使用,该项目主要用于显示极坐标曲线,所以我认为添加一个替代的极坐标网格会很有用。

希望这能作为一个对优秀项目的非常小的补充是可以接受的。

使用代码 

我按照作者的风格,在GraphDisplay类中添加了几个新函数,具体如下:

  1. 一个函数AddPolarGrid,用于根据圆形和径向规则构建网格
  2. 一个函数AddCircularRule,用于向显示中添加圆形规则
  3. 一个函数AddRadialRule,用于向显示中添加径向规则
  4. 我还将原始的AddGrid函数重命名为AddRectanglarGrid。
/// <summary>
/// Adds a polar grid to the GraphDisplay  
/// </summary>
/// <param name="x" />The r Size of the grid radius in graphed units
/// <param name="y" />The a Size of the grid angle in graphed units
/// <param name="style" />The style information for the graph
 
public void AddPolarGrid(double r, double a, GraphStyle style)
{
    int rLeft = (int)Math.Ceiling(Math.Abs(XRight) / r);
    int rRight = (int)Math.Ceiling(Math.Abs(XLeft) / r);
    int rHoriz = Math.Max(rLeft,rRight);
    int rTop = (int)Math.Ceiling(Math.Abs(YTop) / r);
    int rBot = (int)Math.Ceiling(Math.Abs(YBottom) / r);
    int rVert = Math.Max(rTop,rBot);
    int imax = Math.Max(rHoriz,rVert);
    double rmax = r * (imax + 1);
                
    for (int i = 0; i < imax + 1; i++)
    {
      	AddCircularRule((i + 1)* r, style);
    }
 
    for (double aa = 0; aa <= 360 ; aa += a)
    {
       	double rad = aa * Math.PI / 180.0;
       	double cos = Math.Cos(rad);
       	double sin = Math.Sin(rad);
       	Point orig = new Point(r * cos, r * sin);
       	Point end = new Point(rmax * cos, rmax * sin );
       	AddRadialRule(orig,end,style);
    }
}
 
/// <summary>
/// Adds a Circular rule at the specified radial value
/// </summary>
/// <param name="r" />The radius of the rule
/// <param name="style" />The Graphstyle for the rule
 
public void AddCircularRule(double r, GraphStyle style)
{
    Path p = new Path();
    EllipseGeometry eg = new EllipseGeometry();
    eg.Center = new Point( mXTransform.Value(0), mYTransform.Value(0));
    eg.RadiusX =  mXTransform.Value(r) - eg.Center.X;
    eg.RadiusY =  mYTransform.Value(r) - eg.Center.Y;
    p.Data = eg;
    p.Fill = style.Fill;
    p.Stroke = style.Stroke;
    p.StrokeThickness = style.Thickness;
    DisplayCanvas.Children.Add(p);
}
 
/// <summary>
/// Adds a Radial rule from centre to the specified X,Y value
/// </summary>
/// <param name="x" />The X position for the rule
/// <param name="y" />The Y position for the rule
/// <param name="style" />The Graphstyle for the rule
 
public void AddRadialRule(Point orig, Point end, GraphStyle style)
{
    Path p = new Path();
    LineGeometry lg = new LineGeometry();
    lg.StartPoint = new Point(mXTransform.Value(orig.X), mYTransform.Value(orig.Y));
    lg.EndPoint = new Point(mXTransform.Value(end.X), mYTransform.Value(end.Y));
    p.Data = lg;
    p.Fill = style.Fill;
    p.Stroke = style.Stroke;
    p.StrokeThickness = style.Thickness;
    DisplayCanvas.Children.Add(p);
}

我还对RoseCurveDisplay进行了一些简单的XAML更改,我在RoseCurveDisplay的 Decorations Expander 中添加了一个checkbox,并为每个 checkbox 命名,以便可以选择极坐标网格。

<expander removed="{StaticResource HeaderBrush}" isexpanded="True" name="exDecorations" 
        dockpanel.dock="Top" grid.column="1">
...
   <grid removed="{StaticResource InteriorBrush}">
       <stackpanel>
           <checkbox unchecked="checkBoxChanged" checked="checkBoxChanged" 
                margin="22,0,0,0" name="chkShowGrid">Show Grid</checkbox>
           <checkbox unchecked="checkBoxChanged" checked="checkBoxChanged" 
               margin="22,0,0,0" name="chkGridPolar">Polar Grid</checkbox>
 
...                   
                       
         <textblock x:name="GridXWidth">X width</textblock>
               ...    
 
        <textblock grid.row="1" x:name="GridYWidth">Y width</textblock>
                       
       </stackpanel>
    </grid>
</expander>

并添加了代码将新的 checkbox 状态公开为一个属性,并修改了RoseCurveDisplay.checkBoxChanged事件处理程序,使描述网格所需的两个数据项的两个标签的文本将取决于所选的网格类型。

public bool IsGridPolar
{
    get { return (bool)chkGridPolar.IsChecked; }
    set { chkGridPolar.IsChecked = value; }
}

private void checkBoxChanged(object sender, RoutedEventArgs e)
{
    // change text to reflect this
    if (IsGridPolar)
    {
    	GridXWidth.Text = "R width";
    	GridYWidth.Text = "Angle";
    }
    else
    {
    	GridXWidth.Text = "X width";
    	GridYWidth.Text = "Y width";
    }
     
    // original code 	
    if (GraphChanged != null)
    {
        GraphChanged(this, new EventArgs());
    }
}

最后,我修改了MainWindow.DisplayRoseCurve 以显示正确的网格。

public void DisplayRoseCurve()
{
...

   if (rcd.IsGridVisible)
   {
     	if (!rcd.IsGridPolar)
   	   this.gDisplay.AddRectangularGrid(rcd.GridX, rcd.GridY, gridStyle);
        else
           this.gDisplay.AddPolarGrid(rcd.GridX, rcd.GridY, gridStyle);

...
}

关注点

您还可以将代码添加到 checkBoxChanged 中,以根据网格类型更改 GridWidth 值的滑块范围。例如,您可能希望使用于 Y 值的滑块范围(用于为极坐标网格提供角宽度)从 1 到 180 度。

© . All rights reserved.