This example shows how to draw cylinders in a WPF application. Other examples such as Draw a 3D surface from a set of data points with an altitude map using WPF and C# show how to draw 3D graphics.

This example merely adds the following `AddCylinder` method to create the necessary points and triangles to make a cylinder.

// Add a cylinder. private void AddCylinder(MeshGeometry3D mesh, Point3D end_point, Vector3D axis, double radius, int num_sides) { // Get two vectors perpendicular to the axis. Vector3D v1; if ((axis.Z < -0.01) || (axis.Z > 0.01)) v1 = new Vector3D(axis.Z, axis.Z, -axis.X - axis.Y); else v1 = new Vector3D(-axis.Y - axis.Z, axis.X, axis.X); Vector3D v2 = Vector3D.CrossProduct(v1, axis); // Make the vectors have length radius. v1 *= (radius / v1.Length); v2 *= (radius / v2.Length); // Make the top end cap. double theta = 0; double dtheta = 2 * Math.PI / num_sides; for (int i = 0; i < num_sides; i++) { Point3D p1 = end_point + Math.Cos(theta) * v1 + Math.Sin(theta) * v2; theta += dtheta; Point3D p2 = end_point + Math.Cos(theta) * v1 + Math.Sin(theta) * v2; AddTriangle(mesh, end_point, p1, p2); } // Make the bottom end cap. Point3D end_point2 = end_point + axis; theta = 0; for (int i = 0; i < num_sides; i++) { Point3D p1 = end_point2 + Math.Cos(theta) * v1 + Math.Sin(theta) * v2; theta += dtheta; Point3D p2 = end_point2 + Math.Cos(theta) * v1 + Math.Sin(theta) * v2; AddTriangle(mesh, end_point2, p2, p1); } // Make the sides. theta = 0; for (int i = 0; i < num_sides; i++) { Point3D p1 = end_point + Math.Cos(theta) * v1 + Math.Sin(theta) * v2; theta += dtheta; Point3D p2 = end_point + Math.Cos(theta) * v1 + Math.Sin(theta) * v2; Point3D p3 = p1 + axis; Point3D p4 = p2 + axis; AddTriangle(mesh, p1, p3, p2); AddTriangle(mesh, p2, p3, p4); } }

The parameters to the method are:

`mesh`— The`MeshGeometry3D`object that should contain the cylinder.`end_point`— The center of one end of the cylinder.`axis`— A vector that determines the direction and length of the cylinder. In other words, the vector connecting the cylinder’s two end points.`radius`— The cylinder’s radius.`num_sides`— The number of sides the end caps for the cylinder should have. The end caps will each be made up of`num_sides`triangles. The cylinder’s sides will be made up of`2 × num_sides`triangles forming`num_sides`rectangles.

When it begins, the `AddCylinder` method finds two vectors that are perpendicular to the cylinder’s axis and to each other. Those vectors (and all other vectors that are perpendicular to the axis) lie in the plane containing the cylinder’s first end cap.

To find the two vectors, the program first creates vector `v1`. If the `axis`‘s Z coordinate is not close to 0, then the vector <axis.Z, axis.Z, -axis.X – axis.Y> is perpendicular to `axis`. If the `axis`‘s Z coordinate is close to 0, then the vector <-axis.Y – axis.Z, axis.X, axis.X> is perpendicular to `axis`. (To see why those are perpendicular vectors, calculate the dot product of the two vectors. For information about the dot product, see this Wikipedia article.)

Next the method takes the cross product of the first perpendicular vector and the axis. That gives a new vector perpendicular to both of the others (`v1` and `axis`). (To learn why, see this Wikipedia article.)

Now the program has two perpendicular vectors in the plane of the cylinder’s end cap. To generate points along the edges of the end cap, the program will use those vectors multiplied by sines and cosines of angles much as you might generate the points on a circle in two dimensions. To give the end cap the right radius, the program divides `v1` and `v2` by their lengths and multiplies them by `radius`.

Now the program can start calculating points. To make the top, it makes variable `theta` range from 0 to 2π. For each value of `theta`, the program adds the `end_point` to `v1` times sine(theta) plus `v2` times cosine(theta). The triangles it uses to build the end cap connect `end_point` and two adjacent points along the edge of the circle.

The code then makes the bottom similarly. The only difference is that the code reverses the ordering of the three points so the bottom triangle is outwardly oriented. (So WPF can tell which side is on the inside of the cylinder.)

Finally the method makes the cylinder’s sides. To do that, the code loops through the values of `theta` one last time. For each value, it generates points `p1` and `p2` on the edge of the first end cap. It then adds the vector `axis` to those points to get the two corresponding points `p3` and `p4` on the other end cap. Finally it uses those points to make two rectangles between them.

Download the example and look at the code to see how the program uses the `AddCylinder` method to draw cylinders.

You can increase `num_points` to draw cylinders more smoothly, but don’t get too carried away. In my next post I’ll show how you can make the sides of the cylinder look smoother without making `num_points` huge.

Pingback: Draw cones using WPF and C# - C# HelperC# Helper

How can I modify this so I can see the Triangles that make up the cylinders?

Kind of like the “Draw a 3D wireframe using WPF and C#” example.

Download that example and look at its code. Call the ToWireframe method the same way it does to convert the cylinder model into a wireframe.

I have modified this program to call the ToWireframe method and now I have the triangles exposed. What is the best way to control the individual triangle sizes separately. I would like to have each individual triangles size and shape set differently depending on numbers in an array. Im looking to make a cylinder thats ruff and bumpy

Ah. It depends a bit on exactly what effect you have in mind.

One idea would be to break the cylinder into segments and then adjust the radii of the points at each segment. That would make different points bump in and out. You wold need to be sure to use one set of points, though, so the triangles in each segment line up.

If you wanted something spikier, you could add tetrahedrons or pyramids poking out through the cylinder’s sides. You could vary the points’ heights.

I think moving points out away from the axis is probably easiest. If you try to move them in other directions, too, you would have to be careful that they didn’t make their triangles overlap.

Basically i have made classes like .. shape is the abstract class and than derived Point ,from Point derived circle and Cylinder class has been derived from Circle ..

i wanted to draw all the shapes by calling methods of respective shape as shape behaviour

You should be able to adapt the code from this example to do that.

Note that you don’t really call an object’s methods to draw it. Instead the methods should create the 3D data structures that the system uses to draw. Basically you build the data structures that define the shapes’ points and triangles, and then the drawing system uses them to draw the shapes as needed.

Pingback: Draw smooth cylinders using WPF and C# - C# HelperC# Helper

Thanks for sharing. It helped me to build additional debug primitives for Unity at light speed 🙂