/// <summary>
        /// Add one loop of vertices that will define a boundary loop of the current face.
        /// </summary>
        /// <param name="id">The id of the IFCEntity, for error reporting.</param>
        /// <param name="loopVertices">The list of vertices.</param>
        /// <returns>True if the operation succeeded, false oherwise.</returns>
        public bool AddLoopVertices(int id, IList <XYZ> loopVertices)
        {
            int vertexCount = (loopVertices == null) ? 0 : loopVertices.Count;

            if (vertexCount < 3)
            {
                Importer.TheLog.LogComment(id, "Too few distinct loop vertices, ignoring.", false);
                return(false);
            }

            IList <XYZ> adjustedLoopVertices = new List <XYZ>();
            IDictionary <IFCFuzzyXYZ, int> createdVertices = new SortedDictionary <IFCFuzzyXYZ, int>();

            int numCreated = 0;

            for (int ii = 0; ii < vertexCount; ii++)
            {
                IFCFuzzyXYZ fuzzyXYZ = new IFCFuzzyXYZ(loopVertices[ii]);

                int createdVertexIndex = -1;
                if (createdVertices.TryGetValue(fuzzyXYZ, out createdVertexIndex))
                {
                    // We will allow the first and last point to be equivalent, or the current and last point.  Otherwise we will throw.
                    if (((createdVertexIndex == 0) && (ii == vertexCount - 1)) || (createdVertexIndex == numCreated - 1))
                    {
                        continue;
                    }

                    Importer.TheLog.LogComment(id, "Loop is self-intersecting, ignoring.", false);
                    return(false);
                }

                XYZ adjustedXYZ;
                if (!m_TessellatedFaceVertices.TryGetValue(fuzzyXYZ, out adjustedXYZ))
                {
                    adjustedXYZ = m_TessellatedFaceVertices[fuzzyXYZ] = loopVertices[ii];
                }

                adjustedLoopVertices.Add(adjustedXYZ);
                createdVertices[new IFCFuzzyXYZ(adjustedXYZ)] = numCreated;
                numCreated++;
            }

            // Checking start and end points should be covered above.
            if (numCreated < 3)
            {
                Importer.TheLog.LogComment(id, "Loop has less than 3 distinct vertices, ignoring.", false);
                return(false);
            }

            m_TessellatedFaceBoundary.Add(adjustedLoopVertices);
            return(true);
        }
        /// <summary>
        /// Add one loop of vertices that will define a boundary loop of the current face.
        /// </summary>
        /// <param name="id">The id of the IFCEntity, for error reporting.</param>
        /// <param name="loopVertices">The list of vertices.</param>
        /// <returns>True if the operation succeeded, false oherwise.</returns>
        public bool AddLoopVertices(int id, List <XYZ> loopVertices)
        {
            int vertexCount = (loopVertices == null) ? 0 : loopVertices.Count;

            if (vertexCount < 3)
            {
                Importer.TheLog.LogComment(id, "Too few distinct loop vertices, ignoring.", false);
                return(false);
            }

            List <XYZ> adjustedLoopVertices         = null;
            IList <Tuple <int, int> > interiorLoops = null;

            int numOuterCreated = 0;

            bool succeeded = false;

            for (int pass = 0; pass < 2 && !succeeded; pass++)
            {
                // If we have AnyGeometry as a target, we are using Solid tolerances on a first pass.
                // If that would fail, try again using Mesh tolerances.
                if (pass == 1 && !RevertToMeshIfPossible())
                {
                    break;
                }

                succeeded = true;

                // numOuterCreated is the size of the main "outer" loop after removing duplicates
                // and self-intersecting loops.  In all valid cases, numOuterCreated = numTotalCreated.
                numOuterCreated = 0;

                // The total number of non-duplicate loops.  This can differ if we are trying to create
                // a solid vs. a mesh.
                int numTotalCreated = 0;

                // The vertices of the main (presumably outer) loop.
                adjustedLoopVertices = new List <XYZ>();

                // The list of vertices of the self-intersecting loops.
                // Note that we will check that the self-interecting loops do not themselves self-intersect.
                interiorLoops = new List <Tuple <int, int> >();
                int lastInteriorLoopIndex = -1;

                IDictionary <IFCFuzzyXYZ, int> createdVertices = new SortedDictionary <IFCFuzzyXYZ, int>();

                for (int ii = 0; ii < vertexCount; ii++)
                {
                    IFCFuzzyXYZ fuzzyXYZ = new IFCFuzzyXYZ(loopVertices[ii]);

                    int createdVertexIndex = -1;
                    if (createdVertices.TryGetValue(fuzzyXYZ, out createdVertexIndex))
                    {
                        // We will allow the first and last point to be equivalent, or the current and last point.  Otherwise we will throw.
                        if (((createdVertexIndex == 0) && (ii == vertexCount - 1)) || (createdVertexIndex == numTotalCreated - 1))
                        {
                            continue;
                        }

                        // If we have a real self-intersection, mark the loop created by the intersection
                        // for removal later.
                        if (loopVertices[ii].DistanceTo(loopVertices[createdVertexIndex]) < MathUtil.SmallGap())
                        {
                            if (lastInteriorLoopIndex > createdVertexIndex)
                            {
                                // The interior loops overlap; this is probably too much to try to fix.
                                succeeded = false;
                                break;
                            }
                            // Sorted in reverse order so we can more easily create the interior loops later.
                            int numToRemove = ii - createdVertexIndex;
                            interiorLoops.Insert(0, new Tuple <int, int>(createdVertexIndex, numToRemove));
                            lastInteriorLoopIndex = ii;
                            numOuterCreated      -= numToRemove;
                            continue;
                        }

                        // Note that if pass == 1, CanRevertToMesh will be false.
                        if (!CanRevertToMesh())
                        {
                            Importer.TheLog.LogWarning(id, "Loop is self-intersecting, truncating.", false);
                        }
                        succeeded = false;
                        break;
                    }

                    XYZ adjustedXYZ;
                    if (!m_TessellatedFaceVertices.TryGetValue(fuzzyXYZ, out adjustedXYZ))
                    {
                        adjustedXYZ = m_TessellatedFaceVertices[fuzzyXYZ] = loopVertices[ii];
                    }

                    adjustedLoopVertices.Add(adjustedXYZ);
                    createdVertices[new IFCFuzzyXYZ(adjustedXYZ)] = numTotalCreated;
                    numTotalCreated++;
                    numOuterCreated++;
                }

                if (numOuterCreated < 3)
                {
                    succeeded = false;
                }
            }

            // Checking start and end points should be covered above.
            if (numOuterCreated < 3)
            {
                Importer.TheLog.LogComment(id, "Loop has less than 3 distinct vertices, ignoring.", false);
                return(false);
            }

            // Remove the interior loops from the loop boundary, in reverse order, and add them
            // to the tessellated face boundary.
            foreach (Tuple <int, int> interiorLoop in interiorLoops)
            {
                int startIndex = interiorLoop.Item1;
                int count      = interiorLoop.Item2;
                if (count >= 3)
                {
                    m_TessellatedFaceBoundary.Add(loopVertices.GetRange(startIndex, count));
                }
                adjustedLoopVertices.RemoveRange(startIndex, count);
            }

            if (interiorLoops.Count > 0)
            {
                Importer.TheLog.LogWarning(id, "Loop is self-intersecting, fixing.", false);
            }

            m_TessellatedFaceBoundary.Add(adjustedLoopVertices);
            return(true);
        }