/// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        /// <remarks>As this doesn't inherit from IfcSolidModel, this is a non-virtual CreateGeometry function.</remarks>
        protected IList<GeometryObject> CreateGeometry(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            if (Shells.Count == 0)
                return null;

            IList<GeometryObject> geomObjs = null;

            using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder))
            {
                TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope;
                tsBuilderScope.StartCollectingFaceSet();

                foreach (IFCConnectedFaceSet faceSet in Shells)
                    faceSet.CreateShape(shapeEditScope, lcs, scaledLcs, guid);

                geomObjs = tsBuilderScope.CreateGeometry(guid);
            }
            if (geomObjs == null || geomObjs.Count == 0)
                return null;

            return geomObjs;
        }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        /// <remarks>As this doesn't inherit from IfcSolidModel, this is a non-virtual CreateSolid function.</remarks>
        protected IList<GeometryObject> CreateGeometry(
              IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
           if (Shells.Count == 0)
              return null;

           IList<GeometryObject> geomObjs = null;
           int numExpectedFaces = 0;
           foreach (IFCConnectedFaceSet faceSet in Shells)
           {
              numExpectedFaces += faceSet.Faces.Count;
           }

           // We are going to start by trying to create a Solid, even if we are passed a shell-based model, since we can frequently
           // do so.  However, if we have even one missing face, we'll loosen the requirements and revert to mesh only.
           for (int pass = 0; pass < 2; pass++)
           {
              IFCImportShapeEditScope.BuildPreferenceType target =
                 (pass == 0) ? IFCImportShapeEditScope.BuildPreferenceType.AnyGeometry : IFCImportShapeEditScope.BuildPreferenceType.AnyMesh;
              using (IFCImportShapeEditScope.BuildPreferenceSetter setter =
                 new IFCImportShapeEditScope.BuildPreferenceSetter(shapeEditScope, target))
              {
                 using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder))
                 {
                    TessellatedShapeBuilderScope tsBuilderScope = shapeEditScope.BuilderScope as TessellatedShapeBuilderScope;

                    tsBuilderScope.StartCollectingFaceSet();

                    foreach (IFCConnectedFaceSet faceSet in Shells)
                    {
                       faceSet.CreateShape(shapeEditScope, lcs, scaledLcs, guid);
                    }

                    // If we are on our first pass, try again.  If we are on our second pass, warn and create the best geometry we can.
                    if (tsBuilderScope.CreatedFacesCount != numExpectedFaces)
                    {
                       if (pass == 0)
                          continue;

                       Importer.TheLog.LogWarning
                           (Id, "Processing " + tsBuilderScope.CreatedFacesCount + " valid faces out of " + numExpectedFaces + " total.", false);
                    }

                    geomObjs = tsBuilderScope.CreateGeometry(guid);

                    WarnOnTooFewCreatedFaces(geomObjs, numExpectedFaces);

                    break;
                 }
              }
           }

           if (geomObjs == null || geomObjs.Count == 0)
           {
              if (numExpectedFaces != 0)
              {
                 Importer.TheLog.LogError
                     (Id, "No valid geometry found.  This may be due to slivery triangles or other similar geometric issues.", false);
                 return null;
              }
           }

           return geomObjs;
        }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        protected override IList<GeometryObject> CreateGeometryInternal(
           IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            if (Outer == null || Outer.Faces.Count == 0)
                return null;

            IList<GeometryObject> geomObjs = null;
            bool canRevertToMesh = false;
            
            using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder))
            {
                TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope;

                tsBuilderScope.StartCollectingFaceSet();
                Outer.CreateShape(shapeEditScope, lcs, scaledLcs, guid);

                if (tsBuilderScope.CreatedFacesCount == Outer.Faces.Count)
                {
                    geomObjs = tsBuilderScope.CreateGeometry(guid);
                }

                canRevertToMesh = tsBuilderScope.CanRevertToMesh();
            }


            if (geomObjs == null || geomObjs.Count == 0)
            {
                if (canRevertToMesh)
                {
                    using (IFCImportShapeEditScope.BuildPreferenceSetter setter =
                        new IFCImportShapeEditScope.BuildPreferenceSetter(shapeEditScope, IFCImportShapeEditScope.BuildPreferenceType.AnyMesh))
                    {
                        using (BuilderScope newBuilderScope = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder))
                        {
                            TessellatedShapeBuilderScope newTsBuilderScope = newBuilderScope as TessellatedShapeBuilderScope;
                            // Let's see if we can loosen the requirements a bit, and try again.
                            newTsBuilderScope.StartCollectingFaceSet();

                            Outer.CreateShape(shapeEditScope, lcs, scaledLcs, guid);

                            // This needs to be in scope so that we keep the mesh tolerance for vertices.
                            if (newTsBuilderScope.CreatedFacesCount != 0)
                            {
                                if (newTsBuilderScope.CreatedFacesCount != Outer.Faces.Count)
                                    Importer.TheLog.LogWarning
                                        (Outer.Id, "Processing " + newTsBuilderScope.CreatedFacesCount + " valid faces out of " + Outer.Faces.Count + " total.", false);

                                geomObjs = newTsBuilderScope.CreateGeometry(guid);
                            }

                        }
                    }
                }
            }
            
            if (geomObjs == null || geomObjs.Count == 0)
            {
                // Couldn't use fallback, or fallback didn't work.
                Importer.TheLog.LogWarning(Id, "Couldn't create any geometry.", false);
                return null;
            }

            return geomObjs;
        }
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder))
            {
                base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid);

                TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope;

                tsBuilderScope.StartCollectingFaceSet();

                // Create triangle face set from CoordIndex. We do not support the Normals yet at this point
                foreach (List<int> triIndex in CoordIndex)
                {
                    // This is a defensive check in an unlikely situation that the index is larger than the data
                    if (triIndex[0] > Coordinates.CoordList.Count || triIndex[1] > Coordinates.CoordList.Count || triIndex[2] > Coordinates.CoordList.Count)
                    {
                        continue;
                    }

                    tsBuilderScope.StartCollectingFace(GetMaterialElementId(shapeEditScope));

                    IList<XYZ> loopVertices = new List<XYZ>();

                    IList<double> v1 = Coordinates.CoordList[triIndex[0] - 1];
                    IList<double> v2 = Coordinates.CoordList[triIndex[1] - 1];
                    IList<double> v3 = Coordinates.CoordList[triIndex[2] - 1];

                    loopVertices.Add(new XYZ(v1[0], v1[1], v1[2]));
                    loopVertices.Add(new XYZ(v2[0], v2[1], v2[2]));
                    loopVertices.Add(new XYZ(v3[0], v3[1], v3[2]));

                    IList<XYZ> transformedVertices = new List<XYZ>();
                    foreach (XYZ vertex in loopVertices)
                    {
                        // Need to apply the project unit scaling here
                        XYZ scaledVertex = applyProjectUnitScaleVertex(vertex);
                        transformedVertices.Add(scaledLcs.OfPoint(scaledVertex));
                    }

                    // Check triangle that is too narrow (2 vertices are within the tolerance
                    IList<XYZ> validVertices;
                    IFCGeometryUtil.CheckAnyDistanceVerticesWithinTolerance(Id, shapeEditScope, transformedVertices, out validVertices);

                    // We are going to catch any exceptions if the loop is invalid.  
                    // We are going to hope that we can heal the parent object in the TessellatedShapeBuilder.
                    bool bPotentiallyAbortFace = false;

                    int count = validVertices.Count;
                    if (validVertices.Count < 3)
                    {
                        Importer.TheLog.LogComment(Id, "Too few distinct loop vertices (" + count + "), ignoring.", false);
                        bPotentiallyAbortFace = true;
                    }
                    else
                    {
                        if (!tsBuilderScope.AddLoopVertices(Id, validVertices))
                            bPotentiallyAbortFace = true;
                    }

                    if (bPotentiallyAbortFace)
                        tsBuilderScope.AbortCurrentFace();
                    else
                        tsBuilderScope.StopCollectingFace();
                }

                IList<GeometryObject> createdGeometries = tsBuilderScope.CreateGeometry(guid);
                if (createdGeometries != null)
                {
                    foreach (GeometryObject createdGeometry in createdGeometries)
                    {
                        shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, createdGeometry));
                    }
                }
            }

        }