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 PolyStars, 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.

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:

After this, invoke some overall transformations contained in OverallTransformations 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:

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.

And Finally, the Callback

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.

Comments and Discussions

Thanks Ken!So did you ever animate this? I played around with a version (total hack on my part) where I used a signal generator class I found on the web to oscillate the size of some of the parameters automatically. The end result was much like a kaleidoscope & quite hypnotic! I tore that project down and plan to rebuild it somewhat cleaner. If I come up with anything really off the wall, I'll send you a message.Thanks again,Mike

An interesting article, I will probably have a good play with this while eating my sandwiches in half an hour

Regarding dependency properties, I agree it is all a little confusing. The main problem being that your CLR wrappers are not invoked when the framework makes DP changes at runtime. This is the reason why you are seeing unexpected problems in your example code.

I have also come across similar problems with default values, runtime type failures etc...

I would love you to create a Path editing program, that allowed you to snap points to grid lines, and allowed you to specify size of grid. And allowed you to specify path properties such as closed, endcap for line etc etc.

This is something I always hate doing.

Sacha Barber

Microsoft Visual C# MVP 2008

Codeproject MVP 2008

Your best friend is you.I'm my best friend too. We share the same views, and hardly ever argue

I was unaware of Fluidkit before your mentioning it. Probably any code for dealing with stars polygons or other well known geometric objects will bear some similarities.

However we approached the subject in a very different way. He walks around the circle in a parametric manner creating the full set of points. I formed various collections of points and then processed them with various transformations and mixed them back together.