This example basically combines and rearranges the techniques used by previous three-dimensional examples to make them easier to use. Its methods let you build platonic solids, geodesic spheres, and stellate spheres relatively easily.

One real change in this example is that it lets you pass a transformation into the solid creation methods so you can create the solids at locations other than the origin. That makes it easier to add multiple shapes at different locations to the same mesh.

The following `AddTetrahedron` method shows the general idea.

// Add a Tetrahedron to the mesh. public static void AddTetrahedron(this MeshGeometry3D mesh, double side_length, Transform3D transform) { Point3D[] points = TetrahedronVertices(side_length).ToArray(); if (transform != null) transform.Transform(points); // Create the solid tetrahedron. MeshGeometry3D solid_mesh = new MeshGeometry3D(); mesh.AddTriangle(points[0], points[1], points[2]); mesh.AddTriangle(points[0], points[2], points[3]); mesh.AddTriangle(points[0], points[3], points[1]); mesh.AddTriangle(points[3], points[2], points[1]); }

The method first calls the `TetrahedronVertices` method to get an array containing the tetrahedron’s vertices. Then if the `transform` object isn’t null, the method applies it to the points. The method then uses the points to create the tetrahedron as usual.

For example, the example program uses the following code to create its cube.

MeshGeometry3D cube_mesh = new MeshGeometry3D(); cube_mesh.AddCube(1, new TranslateTransform3D(0, 0, 2));

This code creates a `MeshGeometry3D`. It then calls its `AddCube` extension method to add a cube to it. It passes the method a new `TranslateTransform3D` object that translates the cube’s points by distance 2 in the Z direction. If you look at the picture above, you’ll see that the cube is shifted to the left, which is the Z direction in this picture.

The following list shows the classes and methods used in this example that are intended for building shapes. They are grouped by the classes that contain them.

– Represents 2 points that make up an edge. Implements**Edge**`IEquatable<Edge>`so you can use it to make a list without duplicates.

– Represents an array of points that make up a polygon. Assumes the points are coplanar.**Polygon**

– Represents 3 points that make up a triangle.**Triangle**`Subdivide`– Subdivides a triangle for use in making a geodesic sphere`Stellate`– Adds a pyramid on top of a triangle for use in making a stellate geodesic sphere

– Adds 1 extension method to the**TransformExtensions**`Transform3D`class.`Transform`– Make a`Transform3D`object transform a`Triangle`object.

– Adds 1 extension method to the**VectorExtensions**`Vector3D`class.`Scale`– Adjusts a`Vector3D`to have a given length and returns the result.

– Adds extension methods to the**MeshExtensions**`MeshGeometry3D`class. Most of these methods either add shapes to a`MeshGeometry3D`object or return a new`MeshGeometry3D`object containing a shape.`AddPolygonNormal`– Adds a segment showing the normal for a polygon.`AddPolygonNormal`(with vertex names) – Adds a segment showing the normal for a polygon defined by vertex names and an array of points that include vertices that are not part of the polygon. (For the dodecahedron.)`ToTriangleNormals`– Returns a new`MeshGeometry3D`object containing segments representing the triangles in this mesh.`FindTriangleNormal`– Returns a`Vector3D`representing a triangle’s normal.`ToWireFrame`– Returns a new`MeshGeometry3D`object containing segments representing the edges of the mesh’s triangles. (Uses a`HashSet`of`Edge`objects to add shared edges only once.)`AddPolygonWireframe`– Adds a wireframe for a polygon to the mesh. (This is necessary for cubes and dodecahedrons because their faces are not triangles.)`AddPolygonWireframe`(with vertex names) – Adds a wireframe for a polygon defined by an array of points and vertex names. (For use with the dodecahedron.)`ToVertexBoxes`– Returns a new`MeshGeometry3D`object containing small boxes representing a mesh’s vertices.`AddTriangle`– Adds a new triangle to the mesh. Assumes the points are outwardly oriented.`AddSegment`– Adds a thin box to a mesh to represent a line segment. This method has several overloaded versions. For example, different versions take as parameters the segment’s end points as`Point3D`objects or end point coordinates. (Used to add normals, edges, axes, etc.)`AddBox`– Adds a box defined by a corner and three vectors giving the box’s edge directions. If the vectors are parallel to the X, Y, and Z axes, you get a box parallel to the coordinate planes. If the axes are mutually perpendicular, you get a rectangular prism. If the axes are not perpendicular, you get a parallelepiped. (Which is a cool word that you don’t get to use very often.) (Assumes the vectors are outwardly oriented. In other words, the first vector crossed with the second should point in the same direction as the third.)`AddRectangle`– Adds two triangles to the mesh to represent a rectangle. Defined by a corner point and two vectors. Assumes the points are outwardly oriented and actually do define a rectangle.`AddAxes`– Adds segments representing the coordinate axes to the mesh. Parameters let you determine whether the axes extend on both sides of the origin and whether the axes include tick marks.`AddTriangles`– Adds a list of`Triangle`objects to the mesh.`AddPolygon`– Adds triangles representing a polygon to the mesh. Assumes the points are outwardly oriented and coplanar.`AddPolygon`(with vertex names) – Adds triangles representing a polygon defined by an array of points and vertex names to the mesh. Assumes the points are outwardly oriented and coplanar.`MakeModel`– Makes a solid colored model from a mesh.`MergeWith`– Merges a mesh into this one.

**PlatonicSolids**`AddStellateSphere`– Adds a stellate sphere to a mesh.`StellateSphereTriangles`– Returns triangles representing a stellate sphere.`AddGeodesicSphere`– Adds a geodesic sphere to a mesh.`GeodesicSphereTriangles`– Returns triangles representing a geodesic sphere.`AddIcosahedron`– Adds an icosahedron to a mesh.`IcosahedronTriangles`– Returns triangles representing an icosahedron.`IcosahedronVertices`– Returns an icosahedron’s vertices.`AddDodecahedron`– Adds a dodecahedron to a mesh.`AddDodecahedronWireframe`– Adds segments representing a dodecahedron’s wireframe to a mesh. (This is different from most other solids because its faces are not triangles. For most other solids you can use the`MeshExtensions`class’s`ToWireframe`method.)`AddDodecahedronNormals`– Adds segments representing a dodecahedron’s normals to a mesh. (This is different from most other solids because its faces are not triangles. For most other solids you can use the`MeshExtensions`class’s`ToTriangleNormals`method.)`DodecahedronVertices`– Returns a dodecahedron’s vertices.`AddOctahedron`– Adds an octahedron to a mesh.`OctahedronVertices`– Returns an octahedron’s vertices.`AddCube`– Adds a cube to a mesh.`AddCubeWireframe`– Adds segments representing a cube’s wireframe to a mesh. (This is different from most other solids because its faces are not triangles. For most other solids you can use the`MeshExtensions`class’s`ToWireframe`method.)`AddCubeNormals`– Adds segments representing a cube’s normals to a mesh. (This is different from most other solids because its faces are not triangles. For most other solids you can use the`MeshExtensions`class’s`ToTriangleNormals`method.)`CubeVertices`– Returns a cube’s vertices.`AddTetrahedron`– Adds a tetrahedron to a mesh.`TetrahedronVertices`– Returns a tetrahedron’s vertices.

The example uses those methods to create a collection of example objects. The following code shows how the program creates its octahedron.

// Octahedron. MeshGeometry3D octahedron_mesh = new MeshGeometry3D(); octahedron_mesh.AddOctahedron(1, new TranslateTransform3D(-2, 0, 0)); SolidModels.Add(octahedron_mesh.MakeModel(Colors.Pink)); wireframe_mesh.MergeWith( octahedron_mesh.ToWireframe(line_thickness)); normal_mesh.MergeWith( octahedron_mesh.ToTriangleNormals( normal_length, line_thickness)); vertices_mesh.MergeWith( octahedron_mesh.ToVertexBoxes(vertex_width));

This code creates a new mesh for the octahedron and then calls its `AddOctahedron` extension method to add a new octahedron to the mesh. It passes in a `TranslateTransform3D` object to translate the new object by distance -2 in the X direction.

Next the code calls the `MakeModel` extension method to make a solid colored model for the mesh and it saves the model in the `SolidModels` list. (Each solid is saved as a separate model so they can each have different colors.)

Next the code calls `ToWireframe` to make a wireframe for the octahedron and merges the result into the `wireframe_mesh` mesh. (All of the objects’ wireframes are stored in the single mesh `wireframe_mesh` so they all have the same color.)

The code then calls `ToTriangleNormals` to get the octahedron’s normal segments and merges the result into the `normal_mesh` mesh. (All of the objects’ normals are stored in the single mesh `normal_mesh` so they all have the same color.)

Finally the code calls `ToVertexBoxes` to get boxes representing the octahedron’s vertices and merges the result into the `vertices_mesh` mesh. (All of the objects’ vertices are stored in the single mesh `vertices_mesh` so they all have the same color.)

The following `DisplaySelectedModels` method displays the models selected by the program’s check boxes.

// Display the selected models. private void DisplaySelectedModels() { MainModelGroup.Children.Clear(); foreach (Light light in Lights) MainModelGroup.Children.Add(light); if (chkAxes.IsChecked.Value) MainModelGroup.Children.Add(AxesModel); if (chkFaces.IsChecked.Value) foreach (GeometryModel3D model in SolidModels) MainModelGroup.Children.Add(model); if (chkWireframe.IsChecked.Value) MainModelGroup.Children.Add(WireframesModel); if (chkNormals.IsChecked.Value) MainModelGroup.Children.Add(NormalsModel); if (chkVertices.IsChecked.Value) MainModelGroup.Children.Add(VerticesModel); }

The code first empties the model group’s `Children` collection and then adds all of the program’s lights to it. It then examines the check boxes and adds the appropriate models to the `Children` collection.

The only unusual step is where the code loops through the solid models to add them all. That’s different from the way the other models work because each solid is stored in a separate model contained in the `SolidModels` list.

That’s how the program works at a medium-high level. The extension methods defined by the example’s classes make building these objects relatively easy. Download the example and look at the code to see additional details.