Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

GraphDisplay: A Bezier based control for graphing functions and curves

0.00/5 (No votes)
8 Jul 2012 1  
This is an alternative for GraphDisplay: a Bezier based control for graphing functions and curves

Introduction

I really like this approach and intend to use the code as a library in one of my projects which will mostly display polar curves so I thought that adding an alternative polar grid would be useful.

I hope that this is an acceptable very minor addition to an excellent project.

Using the code 

I added a several new functions to the GraphDisplay class  following the style of the author, specifically

  1. A function AddPolarGrid to build the grid from circular and radial rules
  2. A function AddCircularRule to add a Circular rule to the display  
  3. A function AddRadialRule to add a Radial rule to the display
  4. I also renamed the original AddGrid function to 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);
}

I also made some simple xaml changes to RoseCurveDisplay, I added a checkbox to the Decorations Expander in RoseCurveDisplay and gave each checkbox a name to allow the polar grid to be selected. 

<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>

and added code expose the new checkbox status as a property, and modified the RoseCurveDisplay.checkBoxChanged event handler so that the text of the two labels describing the two data items required by the grid would be dependent on the selected grid type. 

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());
    }
}

Finally I altered MainWindow.DisplayRoseCurve to display the correct grid.

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);

...
}

Points of Interest

You could also add code into checkBoxChanged to alter the slider ranges for the GridWidth values to be dependent on the grid type. For example you may wish to make the slider range values for the Y values (which are used to give the angular width for a polar grid) go from 1 to 180 degrees.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here