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
- A function
AddPolarGrid
to build the grid from circular and radial rules
- A function
AddCircularRule
to add a Circular rule to the display - A function
AddRadialRule
to add a Radial rule to the display
- I also renamed the original
AddGrid
function to AddRectanglarGrid
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);
}
}
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);
}
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)
{
if (IsGridPolar)
{
GridXWidth.Text = "R width";
GridYWidth.Text = "Angle";
}
else
{
GridXWidth.Text = "X width";
GridYWidth.Text = "Y width";
}
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.