12,946,658 members (51,981 online)
alternative version

Stats

55.5K views
39 bookmarked
Posted 27 Sep 2008

PolyStar - WPF Polygons and Stars

, 27 Sep 2008 CPOL
 Rate this:
Control and tool for the creation of various stars and polygons.

Introduction

This article is comprised of a `Shape` class for generating polygons and stars as well as a designer that enables us to preview these objects. This started when I found myself in need of a “Spinny Thingy” to display during a long process. A geometric shape evolved, and a designer application along with it.

Most of this article will cover the implementing of the geometrical transformations to create the stars and polygons (Polystars, henceforth). Along the way, I ran afoul of some oddities in the implementation of the `DependencyProperty` class. Hopefully, my experience can be of help.

Although understanding is a great and wonderful thing, the `PolyStar` class and the design application can be used prior to examining their inner workings. You can put a reference to `PolygonImageLib` in you project, construct the polygon with the Generator tool, and then get the XAML and paste it in, either as a `PolyStar` or as a `Polygon`.

Assemblies

The code consists of three assemblies. PolygonBuilder contains the code for displaying the `PolyStar`s, PolygonImageLib contains the classes for the `PolyStar`, and PointTransformations contains the basic classes for manipulating the points in the polygons. The classes in `PointTransformations` have mostly come from my last article.

Polygons and Stars

Polygons can be thought of as an equiangular set of points along a circle specified by a radius and a number of points/sides. The code to generate both stars and polygons is in `PolyMatrixBuilder`.

```if (mShapeType == EShapeType.Polygon)
{
Matrix mat = new Matrix(2);
for (int i = 0; i < mSides; i++)
{
double x = mRadius * Math.Cos((2 * Math.PI / mSides) * i);
double y = mRadius * Math.Sin((2 * Math.PI / mSides) * i);
mat.AddRow(new Double[] { x, y });
}```

Stars are a bit more complicated. One of the ways of defining a star is to think of it as two polygons with the same number of sides and the same origin but different radii, but with the inner one rotated.

To create the star, we clones the matrix of points, rotate them, and interleave the two matrices. Note that the inner radius can be negative, which makes an interesting effect, especially when the negative inner radius number is just a little smaller, absolute value wise, than the radius. The interface is set up so that negative values need to be typed rather than come from the slider.

Angular Offset

The angular offset can be thought of as the amount that the inner polygon is rotated away from where it would be in a normal star.

Note that it can be either positive or negative. Also, if the offset is greater than 360/(number of sides) in degrees, the geometry changes significantly.

Bevel

A Bevel is usually thought of as lopping off the corners of a shape. Technically, I should speak of chamfers, but that is not common usage. There is another way to think of a bevel. We could make a copy of the set of points, rotate it slightly, and then interleave the two sets of points. This is the approach that I took.

We get interesting effects when the bevel angle is negative, or when the angle is larger than 360/(number of sides) degrees for a polygon, or 180/(number of sides) degrees for a star.

Star Generation Code

Combining all of the geometrical notions in the code, we get the following for a star:

```Matrix innerMat = (Matrix)outerMat.Clone();
// Will work because centered about origin
PointTransformations.RotationalTransformation rot =
new RotationalTransformation() { Matrix = innerMat };
if (mIsAngularlyOffset)
{
rot.RotateDegreesAroundOrigin(mAngularOffset);
}
outerMat.Interleave(innerMat, false);

if (mIsBeveled )
{
Matrix bevelmat = (Matrix)outerMat.Clone();
rot.Matrix = bevelmat;
rot.RotateDegreesAroundOrigin(mBevelOffset);
outerMat.Interleave(bevelmat, false);
rot.Matrix = outerMat;
//Remove appearance of rotation
rot.RotateDegreesAroundOrigin(-mBevelOffset / 2);
}```

After this, invoke some overall transformations contained in `OverallTransformation`s to rotate the shape, or flatten it in either the vertical or horizontal directions. This was done to ease maintenance.

Dependency Properties

My motivation for creating the `PolyStar` was to animate it. That requires that most of the properties be dependency properties. All went well with a few minor irritations. Please note that if you have a `double` property, you need to set the default to 0.0 rather than 0 for the value of zero. It will not cast it for you, and will also crash in the XAML where the object is created, rather than at the point of the faulty assignment.

Problems occurred when I decided that it would be better if setting `IsRotated` to `false` would also set the value of `Rotation` to 0. Naively, I thought the following code would work:

```set
{
SetValue(IsRotatedProperty, value);
Rotation= 0;
}```

The `Rotation` is not changed, but `IRotated` is modified just fine. After a while, I tried the following:

```set
{
double[] x = { 0 };
double y = x[4];
SetValue(IsRotatedProperty, value);
double z = x[4];
}```

This should generate a runtime error, but does not. Apparently, the compiler just ignores everything in the `set` statement, except `SetValue`. However, if there is a syntax error, it will fail to compile. If you want to do something when the property is set, you will need to use a callback. Putting code in the `set` area will not work.

Here is a version of the property that works.

Static Helper Functions

```private static DependencyProperty DependencyProp
(string name, System.Type type,object defaultValue){
DependencyProperty dp = DependencyProperty.Register
(name, type , typeof(PolyStar), fpm);
return dp;
}

private static DependencyProperty DependencyProp
(string name, System.Type type, object defaultValue,
PropertyChangedCallback callback)
{
DependencyProperty dp = DependencyProperty.Register
(name, type, typeof(PolyStar), fpm );
return dp;
}```

Property Definition

```public static DependencyProperty IsRotatedProperty =
DependencyProp("IsRotated", typeof(bool), false, IsRotatedCallBack);
public bool IsRotated
{
get { return (bool)GetValue(IsRotatedProperty ); }
set
{
SetValue(IsRotatedProperty, value);
}
}```

And Finally, the Callback

```static void IsRotatedCallBack(DependencyObject property,
DependencyPropertyChangedEventArgs args)
{
if (!(bool)args.NewValue)
{
PolyStar pTemp = (PolyStar)property;
pTemp.Rotation  = 0;
}
}```

Conclusion

There are other details about the technical implementation that might be interesting. `IValueConverter<t>` is worth looking at. MainWindow.xaml uses the `VisualBrush` in a productive way, something I had doubts that I would ever do. My purpose in writing this article was to make a tool so that people could easily add interesting polygons and stars to their applications. I hope to have succeeded.

History

• 27th September, 2008: Initial post

Share

 Software Developer (Senior) United States
Written software for what seems like forever. I'm currenly infatuated with WPF. Hopefully my affections are returned.

You may also be interested in...

 First Prev Next
 Thanks! gardnerp7-Mar-13 9:45 gardnerp 7-Mar-13 9:45
 5 PolyStars! mikkojay24-Aug-09 11:39 mikkojay 24-Aug-09 11:39
 Possible project? Noemata4-Aug-09 4:18 Noemata 4-Aug-09 4:18
 Re: Possible project? KenJohnson4-Aug-09 19:48 KenJohnson 4-Aug-09 19:48
 Email is always good and my address is no secret. kenjohnson777@hotmail.com is the best one to use.
 Excelent! Dragoljub18-Feb-09 23:59 Dragoljub 18-Feb-09 23:59
 Very pretty :-) Colin Eberhardt29-Sep-08 0:37 Colin Eberhardt 29-Sep-08 0:37
 An idea for you Sacha Barber27-Sep-08 20:56 Sacha Barber 27-Sep-08 20:56
 Re: An idea for you mtonsager28-Sep-08 2:07 mtonsager 28-Sep-08 2:07
 Re: An idea for you Leblanc Meneses29-Sep-08 19:02 Leblanc Meneses 29-Sep-08 19:02
 Cool The Dogcow Farmer27-Sep-08 9:58 The Dogcow Farmer 27-Sep-08 9:58
 Very cool but Sacha Barber27-Sep-08 9:13 Sacha Barber 27-Sep-08 9:13
 Re: Very cool but KenJohnson27-Sep-08 16:02 KenJohnson 27-Sep-08 16:02
 Re: Very cool but Sacha Barber27-Sep-08 20:54 Sacha Barber 27-Sep-08 20:54
 Last Visit: 31-Dec-99 18:00     Last Update: 23-May-17 23:59 Refresh 1