Icosahedron Wireframe Factory

/// <summary>
/// Creates new Wireframe objects from Icosahedron geometry.
/// </summary>
public class IcosahedronWireframeFactory : Singleton<IcosahedronWireframeFactory>
{
    #region Instance Members

    #region Methods

    #region Public

    #region Create Wireframe

    /// <summary>
    /// Creates a new Wireframe from the vertices of an Icosahedron.
    /// </summary>
    /// <param name="ico">
    /// The Icosahedron to make a wireframe of.
    /// </param>
    /// <returns>A Wireframe of an Icosahedron.</returns>
    public Wireframe CreateWireframe(Icosahedron ico)
    {
        Wireframe frame = new Wireframe();

        // Dictionary has faster lookup via TryGetValue than List.Contains
        Dictionary<LineSegment3D, bool> lines = new Dictionary<LineSegment3D, bool>();
        List<Vector3> vertices = new List<Vector3>();

        for (int i = 0; i < ico.Indices.Length; i += 3)
        {
            LineSegment3D lineA = new LineSegment3D()
            {
                Point1 = ico.Vertices[ico.Indices[i]].Position,
                Point2 = ico.Vertices[ico.Indices[i + 1]].Position,
            };
            LineSegment3D lineB = new LineSegment3D()
            {
                Point1 = ico.Vertices[ico.Indices[i + 1]].Position,
                Point2 = ico.Vertices[ico.Indices[i + 2]].Position,
            };
            LineSegment3D lineC = new LineSegment3D()
            {
                Point1 = ico.Vertices[ico.Indices[i]].Position,
                Point2 = ico.Vertices[ico.Indices[i + 2]].Position,
            };

            // Check if the lines or their reverses already have been
            // accounted for.  If not, add the vertices to the list.
            bool nothing = false;
            if (!lines.TryGetValue(lineA, out nothing))
            {
                if (!lines.TryGetValue(LineSegment3D.Reverse(lineA), out nothing))
                {
                    lines.Add(lineA, false);
                    vertices.Add(lineA.Point1);
                    vertices.Add(lineA.Point2);
                }
            }
            if (!lines.TryGetValue(lineB, out nothing))
            {
                if (!lines.TryGetValue(LineSegment3D.Reverse(lineB), out nothing))
                {
                    lines.Add(lineB, false);
                    vertices.Add(lineB.Point1);
                    vertices.Add(lineB.Point2);
                }
            }
            if (!lines.TryGetValue(lineC, out nothing))
            {
                if (!lines.TryGetValue(LineSegment3D.Reverse(lineC), out nothing))
                {
                    lines.Add(lineC, false);
                    vertices.Add(lineC.Point1);
                    vertices.Add(lineC.Point2);
                }
            }
        }

        IndexVertices(vertices, out frame.Vertices, out frame.Indices);

        return frame;
    }

    #endregion

    #endregion

    #endregion

    #endregion

    #region Static Members

    #region Methods

    #region Private

    #region Index Vertices

    /// <summary>
    /// Takes a list of Vector3 positions and indexes them while removing 
    /// duplicates.
    /// </summary>
    /// <param name="originalVertices">
    /// The list of Vector3 positions to index.
    /// </param>
    /// <param name="outVertices">
    /// The indexed and unduplicated vertices.
    /// </param>
    /// <param name="outIndices">
    /// Indices of the unduplicated vertices.
    /// </param>
    public void IndexVertices(List<Vector3> originalVertices,
                              out VertexPosition[] outVertices,
                              out int[] outIndices)
    {
        Dictionary<Vector3, int> vertexIndices = new Dictionary<Vector3, int>();
        List<VertexPosition> vertices = new List<VertexPosition>();
        int indexCounter = 0;

        foreach (Vector3 position in originalVertices)
        {
            if (!vertexIndices.ContainsKey(position))
            {
                vertexIndices.Add(position, indexCounter++);
                vertices.Add(new VertexPosition(position));
            }
        }

        List<int> indices = new List<int>();
        foreach (Vector3 position in originalVertices)
        {
            indices.Add(vertexIndices[position]);
        }

        outVertices = vertices.ToArray();
        outIndices = indices.ToArray();
    }

    #endregion

    #endregion

    #endregion

    #endregion
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: