/// <summary>
        /// Create geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation 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>
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid);

            IList<GeometryObject> csgGeometries = CreateGeometryInternal(shapeEditScope, lcs, scaledLcs, guid);
            if (csgGeometries != null)
            {
                foreach (GeometryObject csgGeometry in csgGeometries)
                {
                    shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, csgGeometry));
                }
            }
        }
        /// <summary>
        /// Create geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation 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>
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid);

            // Ignoring Inner shells for now.
            if (Shells.Count != 0)
            {
                // This isn't an inherited function; see description for more details.
               IList<GeometryObject> createdGeometries = CreateGeometry(shapeEditScope, lcs, scaledLcs, guid);
               if (createdGeometries != null)
               {
                   foreach (GeometryObject createdGeometry in createdGeometries)
                   {
                       shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, createdGeometry));
                   }
               }
            }
        }
        /// <summary>
        /// Create geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation 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>
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            base.CreateShapeInternal(shapeEditScope, scaledLcs, lcs, guid);

            // Ignoring Inner shells for now.
            if (Outer != null)
            {
                try
                {
                    IList<GeometryObject> solids = CreateGeometry(shapeEditScope, scaledLcs, lcs, guid);
                    if (solids != null)
                    {
                        foreach (GeometryObject solid in solids)
                        {
                            shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, solid));
                        }
                    }
                    else
                        Importer.TheLog.LogError(Outer.Id, "cannot create valid solid, ignoring.", false);
                }
                catch (Exception ex)
                {
                    Importer.TheLog.LogError(Outer.Id, ex.Message, false);
                }
            }
        }
        /// <summary>
        /// Create geometry for a particular representation item, and add to scope.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation 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>
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid);

            IFCRepresentation parentRep = shapeEditScope.ContainingRepresentation;
            
            IList<Curve> transformedCurves = new List<Curve>();
            if (Curve != null)
            {
                Curve transformedCurve = CreateTransformedCurve(Curve, parentRep, lcs);
                if (transformedCurve != null)
                    transformedCurves.Add(transformedCurve);
            }
            else if (CurveLoop != null)
            {
                foreach (Curve curve in CurveLoop)
                {
                    Curve transformedCurve = CreateTransformedCurve(curve, parentRep, lcs);
                    if (transformedCurve != null)
                        transformedCurves.Add(transformedCurve);
                }
            }

            // TODO: set graphics style for footprint curves.
            IFCRepresentationIdentifier repId = (parentRep == null) ? IFCRepresentationIdentifier.Unhandled : parentRep.Identifier;
            bool createModelGeometry = (repId == IFCRepresentationIdentifier.Axis);

            ElementId gstyleId = ElementId.InvalidElementId;
            if (createModelGeometry)
            {
                Category curveCategory = IFCCategoryUtil.GetSubCategoryForRepresentation(shapeEditScope.Document, Id, parentRep.Identifier);
                if (curveCategory != null)
                {
                    GraphicsStyle graphicsStyle = curveCategory.GetGraphicsStyle(GraphicsStyleType.Projection);
                    if (graphicsStyle != null)
                        gstyleId = graphicsStyle.Id;
                }
            }

            foreach (Curve curve in transformedCurves)
            {
                if (createModelGeometry)
                {
                    curve.SetGraphicsStyleId(gstyleId);
                    shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, curve));
                }
                else
                {
                    // Default: assume a plan view curve.
                    shapeEditScope.AddFootprintCurve(curve);
                }
            }
        }
        /// <summary>
        /// Create geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation 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>
        protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid);

            // Check scale; if it is uniform, create an instance.  If not, create a shape directly.
            // TODO: Instead allow creation of instances based on similar scaling.
            double scaleX = MappingTarget.Scale;
            double scaleY = MappingTarget.ScaleY.HasValue ? MappingTarget.ScaleY.Value : scaleX;
            double scaleZ = MappingTarget.ScaleZ.HasValue ? MappingTarget.ScaleZ.Value : scaleX;
            bool isUnitScale = (MathUtil.IsAlmostEqual(scaleX, 1.0) &&
                MathUtil.IsAlmostEqual(scaleY, 1.0) &&
                MathUtil.IsAlmostEqual(scaleZ, 1.0));

            Transform mappingTransform = MappingTarget.Transform;

            Transform newLcs = null;
            if (lcs == null)
                newLcs = mappingTransform;
            else if (mappingTransform == null)
                newLcs = lcs;
            else
                newLcs = lcs.Multiply(mappingTransform);

            Transform newScaledLcs = null;
            if (scaledLcs == null)
                newScaledLcs = mappingTransform;
            else if (mappingTransform == null)
                newScaledLcs = scaledLcs;
            else
                newScaledLcs = scaledLcs.Multiply(mappingTransform);
            
            // Pass in newLCS = null, use newLCS for instance.
            bool isFootprint = (shapeEditScope.ContainingRepresentation.Identifier == IFCRepresentationIdentifier.FootPrint);
            bool canCreateType = (newLcs != null && newLcs.IsConformal) &&
                (newScaledLcs != null && newScaledLcs.IsConformal) &&
                isUnitScale &&
                (shapeEditScope.ContainingRepresentation != null && !isFootprint);

            if (canCreateType)
            {
                MappingSource.CreateShape(shapeEditScope, null, null, guid);
                IList<GeometryObject> instances = DirectShape.CreateGeometryInstance(shapeEditScope.Document, MappingSource.Id.ToString(), newLcs);
                foreach (GeometryObject instance in instances)
                    shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, instance));
            }
            else
            {
                if (!isUnitScale)
                {
                    XYZ xScale = new XYZ(scaleX, 0.0, 0.0);
                    XYZ yScale = new XYZ(0.0, scaleY, 0.0);
                    XYZ zScale = new XYZ(0.0, 0.0, scaleZ);
                    Transform scaleTransform = Transform.Identity;
                    scaleTransform.set_Basis(0, xScale);
                    scaleTransform.set_Basis(1, yScale);
                    scaleTransform.set_Basis(2, zScale);
                    newScaledLcs = newScaledLcs.Multiply(scaleTransform);
                }

                MappingSource.CreateShape(shapeEditScope, newLcs, newScaledLcs, guid);
            }
        }
        private void CreateBoxShape(IFCImportShapeEditScope shapeEditScope, Transform scaledLcs)
        {
            using (IFCImportShapeEditScope.IFCContainingRepresentationSetter repSetter = new IFCImportShapeEditScope.IFCContainingRepresentationSetter(shapeEditScope, this))
            {
                // Get the material and graphics style based in the "Box" sub-category of Generic Models.  
                // We will create the sub-category if this is our first time trying to use it.
                // Note that all bounding boxes are controlled by a sub-category of Generic Models.  We may revisit that decision later.
                SolidOptions solidOptions = null;
                Category bboxCategory = IFCCategoryUtil.GetSubCategoryForRepresentation(shapeEditScope.Document, Id, Identifier);
                if (bboxCategory != null)
                {
                    ElementId materialId = (bboxCategory.Material == null) ? ElementId.InvalidElementId : bboxCategory.Material.Id;
                    GraphicsStyle graphicsStyle = bboxCategory.GetGraphicsStyle(GraphicsStyleType.Projection);
                    ElementId gstyleId = (graphicsStyle == null) ? ElementId.InvalidElementId : graphicsStyle.Id;
                    solidOptions = new SolidOptions(materialId, gstyleId);
                }

                Solid bboxSolid = IFCGeometryUtil.CreateSolidFromBoundingBox(scaledLcs, BoundingBox, solidOptions);
                if (bboxSolid != null)
                {
                    IFCSolidInfo bboxSolidInfo = IFCSolidInfo.Create(Id, bboxSolid);
                    shapeEditScope.AddGeometry(bboxSolidInfo);
                }
            }
            return;
        }
        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));
                    }
                }
            }

        }