/// <summary>
        /// Creates a SimpleSweptSolidAnalyzer and computes the swept solid.
        /// </summary>
        /// <param name="faces">The faces of a solid.</param>
        /// <param name="normal">The normal of the reference plane that a path might lie on.  If it is null, try to guess based on the geometry.</param>
        /// <returns>The analyzer.</returns>
        /// <remarks>This is a simple analyzer, and is not intended to be general - it works in some simple, real-world cases.</remarks>
        public static SimpleSweptSolidAnalyzer Create(ICollection <Face> faces, XYZ normal)
        {
            if (faces == null || faces.Count < 3)
            {
                throw new ArgumentException("Invalid faces.", "faces");
            }

            if (normal == null)
            {
                foreach (Face face in faces)
                {
                    if (face is RevolvedFace)
                    {
                        XYZ faceNormal = (face as RevolvedFace).Axis;
                        if (normal == null)
                        {
                            normal = faceNormal;
                        }
                        else if (!MathUtil.VectorsAreParallel(normal, faceNormal))
                        {
                            throw new InvalidOperationException("Couldn't calculate swept solid normal.");
                        }
                    }
                }
            }

            // find potential profile faces, their normal vectors must be orthogonal to the input normal
            List <PlanarFace> potentialSweepEndFaces = new List <PlanarFace>();

            foreach (Face face in faces)
            {
                PlanarFace planarFace = face as PlanarFace;
                if (planarFace == null)
                {
                    continue;
                }
                if (MathUtil.VectorsAreOrthogonal(normal, planarFace.FaceNormal))
                {
                    potentialSweepEndFaces.Add(planarFace);
                }
            }

            if (potentialSweepEndFaces.Count < 2)
            {
                // Can't find enough potential end faces.
                return(null);
            }

            int        ii = 0;
            PlanarFace candidateProfileFace  = null; // the potential profile face for the swept solid
            PlanarFace candidateProfileFace2 = null;
            Edge       candidatePathEdge     = null;
            bool       foundCandidateFace    = false;

            do
            {
                candidateProfileFace = potentialSweepEndFaces[ii++];

                // find edges on the candidate profile face and the side faces with the edges
                // later find edges on the other candidate profile face with same side faces
                // they will be used to compare if the edges are congruent
                // to make sure the two faces are the potential profile faces

                Dictionary <Face, Edge> sideFacesWithCandidateEdges = new Dictionary <Face, Edge>();
                EdgeArrayArray          candidateFaceEdgeLoops      = candidateProfileFace.EdgeLoops;
                foreach (EdgeArray edgeArray in candidateFaceEdgeLoops)
                {
                    foreach (Edge candidateEdge in edgeArray)
                    {
                        Face sideFace = candidateEdge.GetFace(0);
                        if (sideFace == candidateProfileFace)
                        {
                            sideFace = candidateEdge.GetFace(1);
                        }

                        if (sideFacesWithCandidateEdges.ContainsKey(sideFace)) // should not happen
                        {
                            throw new InvalidOperationException("Failed");
                        }

                        sideFacesWithCandidateEdges[sideFace] = candidateEdge;
                    }
                }

                double candidateProfileFaceArea = candidateProfileFace.Area;
                foreach (PlanarFace theOtherCandidateFace in potentialSweepEndFaces)
                {
                    if (theOtherCandidateFace.Equals(candidateProfileFace))
                    {
                        continue;
                    }

                    if (!MathUtil.IsAlmostEqual(candidateProfileFaceArea, theOtherCandidateFace.Area))
                    {
                        continue;
                    }

                    EdgeArrayArray theOtherCandidateFaceEdgeLoops = theOtherCandidateFace.EdgeLoops;

                    bool failToFindTheOtherCandidateFace = false;
                    Dictionary <Face, Edge> sideFacesWithTheOtherCandidateEdges = new Dictionary <Face, Edge>();
                    foreach (EdgeArray edgeArray in theOtherCandidateFaceEdgeLoops)
                    {
                        foreach (Edge theOtherCandidateEdge in edgeArray)
                        {
                            Face sideFace = theOtherCandidateEdge.GetFace(0);
                            if (sideFace == theOtherCandidateFace)
                            {
                                sideFace = theOtherCandidateEdge.GetFace(1);
                            }

                            if (!sideFacesWithCandidateEdges.ContainsKey(sideFace)) // should already have
                            {
                                failToFindTheOtherCandidateFace = true;
                                break;
                            }

                            if (sideFacesWithTheOtherCandidateEdges.ContainsKey(sideFace)) // should not happen
                            {
                                throw new InvalidOperationException("Failed");
                            }

                            sideFacesWithTheOtherCandidateEdges[sideFace] = theOtherCandidateEdge;
                        }
                    }

                    if (failToFindTheOtherCandidateFace)
                    {
                        continue;
                    }

                    if (sideFacesWithCandidateEdges.Count != sideFacesWithTheOtherCandidateEdges.Count)
                    {
                        continue;
                    }

                    // side faces with candidate profile face edges
                    Dictionary <Face, List <Edge> > sideFacesWithEdgesDic = new Dictionary <Face, List <Edge> >();
                    foreach (Face sideFace in sideFacesWithCandidateEdges.Keys)
                    {
                        sideFacesWithEdgesDic[sideFace] = new List <Edge>();
                        sideFacesWithEdgesDic[sideFace].Add(sideFacesWithCandidateEdges[sideFace]);
                        sideFacesWithEdgesDic[sideFace].Add(sideFacesWithTheOtherCandidateEdges[sideFace]);
                    }

                    if (!AreFacesSimpleCongruent(sideFacesWithEdgesDic))
                    {
                        continue;
                    }

                    // find candidate path edges
                    Dictionary <Face, List <Edge> > candidatePathEdgesWithFace = new Dictionary <Face, List <Edge> >();
                    foreach (KeyValuePair <Face, List <Edge> > sideFaceAndEdges in sideFacesWithEdgesDic)
                    {
                        List <Edge> pathEdges = FindCandidatePathEdge(sideFaceAndEdges.Key, sideFaceAndEdges.Value[0], sideFaceAndEdges.Value[1]);
                        // maybe we found two faces of an opening or a recess on the swept solid, skip in this case
                        if (pathEdges.Count < 2)
                        {
                            failToFindTheOtherCandidateFace = true;
                            break;
                        }
                        candidatePathEdgesWithFace[sideFaceAndEdges.Key] = pathEdges;
                    }

                    if (failToFindTheOtherCandidateFace)
                    {
                        continue;
                    }

                    // check if these edges are congruent
                    if (!AreEdgesSimpleCongruent(candidatePathEdgesWithFace))
                    {
                        continue;
                    }

                    candidatePathEdge = candidatePathEdgesWithFace.Values.ElementAt(0).ElementAt(0);

                    foundCandidateFace    = true;
                    candidateProfileFace2 = theOtherCandidateFace;
                    break;
                }

                if (foundCandidateFace)
                {
                    break;
                }
            } while (ii < potentialSweepEndFaces.Count);

            SimpleSweptSolidAnalyzer simpleSweptSolidAnalyzer = null;

            if (foundCandidateFace)
            {
                simpleSweptSolidAnalyzer = new SimpleSweptSolidAnalyzer();
                Curve pathCurve = candidatePathEdge.AsCurve();
                XYZ   endPoint0 = pathCurve.GetEndPoint(0);

                bool foundProfileFace          = false;
                List <PlanarFace> profileFaces = new List <PlanarFace>();
                profileFaces.Add(candidateProfileFace);
                profileFaces.Add(candidateProfileFace2);

                foreach (PlanarFace profileFace in profileFaces)
                {
                    IntersectionResultArray intersectionResults;
                    profileFace.Intersect(pathCurve, out intersectionResults);
                    if (intersectionResults != null)
                    {
                        foreach (IntersectionResult intersectionResult in intersectionResults)
                        {
                            XYZ intersectPoint = intersectionResult.XYZPoint;
                            if (intersectPoint.IsAlmostEqualTo(endPoint0))
                            {
                                simpleSweptSolidAnalyzer.m_ProfileFace = profileFace;
                                foundProfileFace = true;
                                break;
                            }
                        }
                    }

                    if (foundProfileFace)
                    {
                        break;
                    }
                }

                if (!foundProfileFace)
                {
                    // Failed to find profile face.
                    return(null);
                }

                // TODO: consider one profile face has an opening extrusion inside while the other does not
                List <Face> alignedFaces = FindAlignedFaces(profileFaces.ToList <Face>());

                List <Face> unalignedFaces = new List <Face>();
                foreach (Face face in faces)
                {
                    if (profileFaces.Contains(face) || alignedFaces.Contains(face))
                    {
                        continue;
                    }

                    unalignedFaces.Add(face);
                }

                simpleSweptSolidAnalyzer.m_UnalignedFaces = unalignedFaces;

                simpleSweptSolidAnalyzer.m_PathCurve            = pathCurve;
                simpleSweptSolidAnalyzer.m_ReferencePlaneNormal = normal;
            }

            return(simpleSweptSolidAnalyzer);
        }
        /// <summary>
        /// Creates a SimpleSweptSolidAnalyzer and computes the swept solid. This method should be used when a swept curve (directrix) is already known. Even when it is missing (null)
        /// it will simplu call the original one where it will try to determine the swept curve (directrix) using the connecting faces
        /// </summary>
        /// <param name="faces">The faces of a solid.</param>
        /// <param name="normal">The normal of the reference plane that a path might lie on.  If it is null, try to guess based on the geometry.</param>
        /// <param name="potentialPathGeom">The potential swept path (e.g. in Revit MEP pipe/duct/fitting may already have this defined as part of the model)</param>
        /// <returns>The analyzer.</returns>
        /// <remarks>This is a simple analyzer, and is not intended to be general - it works in some simple, real-world cases.</remarks>
        public static SimpleSweptSolidAnalyzer Create(ICollection <Face> faces, XYZ normal, GeometryObject potentialPathGeom)
        {
            SimpleSweptSolidAnalyzer         simpleSweptSolidAnalyzer = null;
            IList <Tuple <PlanarFace, XYZ> > potentialSweptAreaFaces  = new List <Tuple <PlanarFace, XYZ> >();
            Curve directrix = potentialPathGeom as Curve;

            bool pathGeomExists = potentialPathGeom != null;

            if (!pathGeomExists)
            {
                return(Create(faces, normal));
            }

            // Collect plannar faces as candidates for the swept area
            foreach (Face face in faces)
            {
                if (!(face is PlanarFace))
                {
                    continue;
                }
                PlanarFace planarFace = face as PlanarFace;
                // Candidate face must be Orthogonal to the plane where the directrix curve is
                if (MathUtil.VectorsAreOrthogonal(normal, planarFace.FaceNormal))
                {
                    // We are also interested to get only end faces where the Curve intersect the Face at the same point as the Curve start or end point
                    IntersectionResultArray intersectResults;
                    if (planarFace.Intersect(directrix, out intersectResults) == SetComparisonResult.Overlap)
                    {
                        foreach (IntersectionResult res in intersectResults)
                        {
                            if (res.XYZPoint.IsAlmostEqualTo(directrix.GetEndPoint(0)) ||
                                res.XYZPoint.IsAlmostEqualTo(directrix.GetEndPoint(1)))
                            {
                                Tuple <PlanarFace, XYZ> potentialEndFaceAndPoint = new Tuple <PlanarFace, XYZ>(planarFace, res.XYZPoint);
                                potentialSweptAreaFaces.Add(potentialEndFaceAndPoint);
                            }
                        }
                    }
                }
            }

            // If there are more than 1 candidates, we need to find the congruent faces, and they cannot be on the same plane
            IList <Tuple <PlanarFace, XYZ> > sweptEndFaces = new List <Tuple <PlanarFace, XYZ> >();

            while (potentialSweptAreaFaces.Count > 1)
            {
                bool       foundPair   = false;
                PlanarFace face0       = potentialSweptAreaFaces[0].Item1;
                XYZ        ptDirectrix = potentialSweptAreaFaces[0].Item2;
                potentialSweptAreaFaces.RemoveAt(0);    // remove the item from the List

                IList <Tuple <PlanarFace, XYZ> > potentialPairList = potentialSweptAreaFaces;

                foreach (Tuple <PlanarFace, XYZ> potentialPair in potentialPairList)
                {
                    PlanarFace face1 = potentialPair.Item1;

                    // Cannot handle faces that are on the same plane or intersecting (will cause self-intersection when being swept)
                    // -- Can't do the intersection way because Revit returns intersection of the planes where those faces are defines (unbound)
                    //if (face0.Intersect(face1) == FaceIntersectionFaceResult.Intersecting)
                    //    continue;
                    // If the faces are facing the same direction (or opposite) they may be of the same plane. Skip those of the same plane
                    if (face0.FaceNormal.IsAlmostEqualTo(face1.FaceNormal) || face0.FaceNormal.IsAlmostEqualTo(face1.FaceNormal.Negate()))
                    {
                        // chose any point in face0 and face1
                        XYZ pF0TopF1 = (face0.EdgeLoops.get_Item(0).get_Item(0).AsCurve().GetEndPoint(0)
                                        - face1.EdgeLoops.get_Item(0).get_Item(0).AsCurve().GetEndPoint(0)).Normalize();

                        if (pF0TopF1 == null || pF0TopF1.IsZeroLength())
                        {
                            continue;
                        }
                        // If the vector created from a point in Face0 and a point in Face1 against the face normal is orthogonal, it means the faces are on the same plane
                        if (MathUtil.VectorsAreOrthogonal(face0.FaceNormal, pF0TopF1))
                        {
                            continue;
                        }
                    }

                    if (AreFacesSimpleCongruent(face0, face1))
                    {
                        sweptEndFaces.Add(new Tuple <PlanarFace, XYZ>(face0, ptDirectrix));
                        sweptEndFaces.Add(new Tuple <PlanarFace, XYZ>(face1, potentialPair.Item2));
                        foundPair = true;
                        break;
                    }
                }
                if (foundPair)
                {
                    break;
                }
            }

            if (sweptEndFaces.Count >= 2)
            {
                simpleSweptSolidAnalyzer = new SimpleSweptSolidAnalyzer();
                simpleSweptSolidAnalyzer.m_ProfileFace          = sweptEndFaces[0].Item1;
                simpleSweptSolidAnalyzer.m_PathCurve            = directrix;
                simpleSweptSolidAnalyzer.m_ReferencePlaneNormal = normal;
            }

            return(simpleSweptSolidAnalyzer);
        }
        /// <summary>
        /// Creates a SimpleSweptSolidAnalyzer and computes the swept solid.
        /// </summary>
        /// <param name="faces">The faces of a solid.</param>
        /// <param name="normal">The normal of the reference plane that a path might lie on.  If it is null, try to guess based on the geometry.</param>
        /// <returns>The analyzer.</returns>
        /// <remarks>This is a simple analyzer, and is not intended to be general - it works in some simple, real-world cases.</remarks>
        public static SimpleSweptSolidAnalyzer Create(ICollection<Face> faces, XYZ normal)
        {
            if (faces == null || faces.Count < 3)
                throw new ArgumentException("Invalid faces.", "faces");
            
            if (normal == null)
            {
                foreach (Face face in faces)
                {
                    if (face is RevolvedFace)
                    {
                        XYZ faceNormal = (face as RevolvedFace).Axis;
                        if (normal == null)
                            normal = faceNormal;
                        else if (!MathUtil.VectorsAreParallel(normal, faceNormal))
                            throw new InvalidOperationException("Couldn't calculate swept solid normal.");
                    }
                }
            }

            // find potential profile faces, their normal vectors must be orthogonal to the input normal
            List<PlanarFace> potentialSweepEndFaces = new List<PlanarFace>();
            foreach (Face face in faces)
            {
                PlanarFace planarFace =  face as PlanarFace;
                if (planarFace == null)
                    continue;
                if (MathUtil.VectorsAreOrthogonal(normal, planarFace.Normal))
                    potentialSweepEndFaces.Add(planarFace);
            }

            if (potentialSweepEndFaces.Count < 2)
                throw new InvalidOperationException("Can't find enough potential end faces.");

            int i = 0;
            PlanarFace candidateProfileFace = null; // the potential profile face for the swept solid
            PlanarFace candidateProfileFace2 = null;
            Edge candidatePathEdge = null;
            bool foundCandidateFace = false;
            do 
            {
                candidateProfileFace = potentialSweepEndFaces[i++];

                // find edges on the candidate profile face and the side faces with the edges
                // later find edges on the other candidate profile face with same side faces
                // they will be used to compare if the edges are congruent
                // to make sure the two faces are the potential profile faces

                Dictionary<Face, Edge> sideFacesWithCandidateEdges = new Dictionary<Face, Edge>();
                EdgeArrayArray candidateFaceEdgeLoops = candidateProfileFace.EdgeLoops;
                foreach (EdgeArray edgeArray in candidateFaceEdgeLoops)
                {
                    foreach (Edge candidateEdge in edgeArray)
                    {
                        Face sideFace = candidateEdge.GetFace(0);
                        if (sideFace == candidateProfileFace)
                            sideFace = candidateEdge.GetFace(1);

                        if (sideFacesWithCandidateEdges.ContainsKey(sideFace)) // should not happen
                            throw new InvalidOperationException("Failed");

                        sideFacesWithCandidateEdges[sideFace] = candidateEdge;
                    }
                }

                double candidateProfileFaceArea = candidateProfileFace.Area;
                foreach (PlanarFace theOtherCandidateFace in potentialSweepEndFaces)
                {
                    if (theOtherCandidateFace.Equals(candidateProfileFace))
                        continue;

                    if (!MathUtil.IsAlmostEqual(candidateProfileFaceArea, theOtherCandidateFace.Area))
                        continue;

                    EdgeArrayArray theOtherCandidateFaceEdgeLoops = theOtherCandidateFace.EdgeLoops;

                    bool failToFindTheOtherCandidateFace = false;
                    Dictionary<Face, Edge> sideFacesWithTheOtherCandidateEdges = new Dictionary<Face, Edge>();
                    foreach (EdgeArray edgeArray in theOtherCandidateFaceEdgeLoops)
                    {
                        foreach (Edge theOtherCandidateEdge in edgeArray)
                        {
                            Face sideFace = theOtherCandidateEdge.GetFace(0);
                            if (sideFace == theOtherCandidateFace)
                                sideFace = theOtherCandidateEdge.GetFace(1);

                            if (!sideFacesWithCandidateEdges.ContainsKey(sideFace)) // should already have
                            {
                                failToFindTheOtherCandidateFace = true;
                                break;
                            }

                            if (sideFacesWithTheOtherCandidateEdges.ContainsKey(sideFace)) // should not happen
                                throw new InvalidOperationException("Failed");

                            sideFacesWithTheOtherCandidateEdges[sideFace] = theOtherCandidateEdge;
                        }
                    }

                    if (failToFindTheOtherCandidateFace)
                        continue;

                    if (sideFacesWithCandidateEdges.Count != sideFacesWithTheOtherCandidateEdges.Count)
                        continue;

                    // side faces with candidate profile face edges
                    Dictionary<Face, List<Edge>> sideFacesWithEdgesDic = new Dictionary<Face, List<Edge>>();
                    foreach (Face sideFace in sideFacesWithCandidateEdges.Keys)
                    {
                        sideFacesWithEdgesDic[sideFace] = new List<Edge>();
                        sideFacesWithEdgesDic[sideFace].Add(sideFacesWithCandidateEdges[sideFace]);
                        sideFacesWithEdgesDic[sideFace].Add(sideFacesWithTheOtherCandidateEdges[sideFace]);
                    }

                    if (!AreFacesSimpleCongruent(sideFacesWithEdgesDic))
                        continue;

                    // find candidate path edges
                    Dictionary<Face, List<Edge>> candidatePathEdgesWithFace = new Dictionary<Face, List<Edge>>();
                    foreach (KeyValuePair<Face, List<Edge>> sideFaceAndEdges in sideFacesWithEdgesDic)
                    {
                        List<Edge> pathEdges = FindCandidatePathEdge(sideFaceAndEdges.Key, sideFaceAndEdges.Value[0], sideFaceAndEdges.Value[1]);
                        // maybe we found two faces of an opening or a recess on the swept solid, skip in this case
                        if (pathEdges.Count < 2)
                        {
                            failToFindTheOtherCandidateFace = true;
                            break;
                        }
                        candidatePathEdgesWithFace[sideFaceAndEdges.Key] = pathEdges;
                    }

                    if (failToFindTheOtherCandidateFace)
                        continue;

                    // check if these edges are congruent
                    if (!AreEdgesSimpleCongruent(candidatePathEdgesWithFace))
                        continue;

                    candidatePathEdge = candidatePathEdgesWithFace.Values.ElementAt(0).ElementAt(0);

                    foundCandidateFace = true;
                    candidateProfileFace2 = theOtherCandidateFace;
                    break;
                }

                if (foundCandidateFace)
                    break;
            } while (i < potentialSweepEndFaces.Count);

            SimpleSweptSolidAnalyzer simpleSweptSolidAnalyzer = null;

            if (foundCandidateFace)
            {
                simpleSweptSolidAnalyzer = new SimpleSweptSolidAnalyzer();
                Curve pathCurve = candidatePathEdge.AsCurve();
                XYZ endPoint0 = pathCurve.GetEndPoint(0);

                bool foundProfileFace = false;
                List<PlanarFace> profileFaces = new List<PlanarFace>();
                profileFaces.Add(candidateProfileFace);
                profileFaces.Add(candidateProfileFace2);

                foreach (PlanarFace profileFace in profileFaces)
                {
                    IntersectionResultArray intersectionResults;
                    profileFace.Intersect(pathCurve, out intersectionResults);
                    if (intersectionResults != null)
                    {
                        foreach (IntersectionResult intersectoinResult in intersectionResults)
                        {
                            XYZ intersectPoint = intersectoinResult.XYZPoint;
                            if (intersectPoint.IsAlmostEqualTo(endPoint0))
                            {
                                simpleSweptSolidAnalyzer.m_ProfileFace = profileFace;
                                foundProfileFace = true;
                                break;
                            }
                        }
                    }

                    if (foundProfileFace)
                        break;
                }

                if (!foundProfileFace)
                    throw new InvalidOperationException("Failed to find profile face.");

                // TODO: consider one profile face has an opening extrusion inside while the other does not
                List<Face> alignedFaces = FindAlignedFaces(profileFaces.ToList<Face>());

                List<Face> unalignedFaces = new List<Face>();
                foreach (Face face in faces)
                {
                    if (profileFaces.Contains(face) || alignedFaces.Contains(face))
                        continue;

                    unalignedFaces.Add(face);
                }

                simpleSweptSolidAnalyzer.m_UnalignedFaces = unalignedFaces;

                simpleSweptSolidAnalyzer.m_PathCurve = pathCurve;
                simpleSweptSolidAnalyzer.m_ReferencePlaneNormal = normal;
            }

            return simpleSweptSolidAnalyzer;
        }
        /// <summary>
        /// Creates a SweptSolidExporter.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="element">The element.</param>
        /// <param name="solid">The solid.</param>
        /// <param name="normal">The normal of the plane that the path lies on.</param>
        /// <returns>The SweptSolidExporter.</returns>
        public static SweptSolidExporter Create(ExporterIFC exporterIFC, Element element, SimpleSweptSolidAnalyzer sweptAnalyzer, GeometryObject geomObject)
        {
            try
            {
                if (sweptAnalyzer == null)
                    return null;

                SweptSolidExporter sweptSolidExporter = null;

                IList<Revit.IFC.Export.Utility.GeometryUtil.FaceBoundaryType> faceBoundaryTypes;
                IList<CurveLoop> faceBoundaries = GeometryUtil.GetFaceBoundaries(sweptAnalyzer.ProfileFace, null, out faceBoundaryTypes);

                string profileName = null;
                if (element != null)
                {
                    ElementType type = element.Document.GetElement(element.GetTypeId()) as ElementType;
                    if (type != null)
                        profileName = type.Name;
                }

                // Is it really an extrusion?
                if (sweptAnalyzer.PathCurve is Line)
                {
                    Line line = sweptAnalyzer.PathCurve as Line;

                    // invalid case
                    if (MathUtil.VectorsAreOrthogonal(line.Direction, sweptAnalyzer.ProfileFace.FaceNormal))
                        return null;

                    sweptSolidExporter = new SweptSolidExporter();
                    sweptSolidExporter.RepresentationType = ShapeRepresentationType.SweptSolid;
                    Plane plane = new Plane(sweptAnalyzer.ProfileFace.FaceNormal, sweptAnalyzer.ProfileFace.Origin);
                    sweptSolidExporter.RepresentationItem = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, profileName, faceBoundaries, plane,
                        line.Direction, UnitUtil.ScaleLength(line.Length));
                }
                else
                {
                    sweptSolidExporter = new SweptSolidExporter();
                    if (ExporterCacheManager.ExportOptionsCache.ExportAs4)
                    {
                        // Use tessellated geometry in IFC Reference View
                        if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView)
                        {
                            // TODO: Create CreateSimpleSweptSolidAsTessellation routine that takes advantage of the superior tessellation of this class.
                            BodyExporterOptions options = new BodyExporterOptions(false);
                            sweptSolidExporter.RepresentationItem = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, element, options, geomObject);
                            sweptSolidExporter.RepresentationType = ShapeRepresentationType.Tessellation;
                        }
                        else
                        {
                            sweptSolidExporter.RepresentationItem = CreateSimpleSweptSolid(exporterIFC, profileName, faceBoundaries, sweptAnalyzer.ReferencePlaneNormal, sweptAnalyzer.PathCurve);
                            sweptSolidExporter.RepresentationType = ShapeRepresentationType.AdvancedSweptSolid;
                        }
                    }
                    else
                    {
                        sweptSolidExporter.Facets = CreateSimpleSweptSolidAsBRep(exporterIFC, profileName, faceBoundaries, sweptAnalyzer.ReferencePlaneNormal, sweptAnalyzer.PathCurve);
                        sweptSolidExporter.RepresentationType = ShapeRepresentationType.Brep;
                    }
                }
                return sweptSolidExporter;
            }
            catch (Exception)
            {
                return null;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Creates a SweptSolidExporter.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="element">The element.</param>
        /// <param name="solid">The solid.</param>
        /// <param name="normal">The normal of the plane that the path lies on.</param>
        /// <returns>The SweptSolidExporter.</returns>
        public static SweptSolidExporter Create(ExporterIFC exporterIFC, Element element, SimpleSweptSolidAnalyzer sweptAnalyzer)
        {
            try
            {
                if (sweptAnalyzer == null)
                    return null;

                SweptSolidExporter sweptSolidExporter = null;

                IList<Revit.IFC.Export.Utility.GeometryUtil.FaceBoundaryType> faceBoundaryTypes;
                IList<CurveLoop> faceBoundaries = GeometryUtil.GetFaceBoundaries(sweptAnalyzer.ProfileFace, null, out faceBoundaryTypes);

                string profileName = null;
                if (element != null)
                {
                    ElementType type = element.Document.GetElement(element.GetTypeId()) as ElementType;
                    if (type != null)
                        profileName = type.Name;
                }

                // Is it really an extrusion?
                if (sweptAnalyzer.PathCurve is Line)
                {
                    Line line = sweptAnalyzer.PathCurve as Line;

                    // invalid case
                    if (MathUtil.VectorsAreOrthogonal(line.Direction, sweptAnalyzer.ProfileFace.Normal))
                        return null;

                    sweptSolidExporter = new SweptSolidExporter();
                    sweptSolidExporter.m_IsExtrusion = true;
                    Plane plane = new Plane(sweptAnalyzer.ProfileFace.Normal, sweptAnalyzer.ProfileFace.Origin);
                    sweptSolidExporter.m_RepresentationItem = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, profileName, faceBoundaries, plane,
                        line.Direction, UnitUtil.ScaleLength(line.Length));
                }
                else
                {
                    sweptSolidExporter = new SweptSolidExporter();
                    if (ExporterCacheManager.ExportOptionsCache.ExportAs4)
                        sweptSolidExporter.m_RepresentationItem = CreateSimpleSweptSolid(exporterIFC, profileName, faceBoundaries, sweptAnalyzer.ReferencePlaneNormal, sweptAnalyzer.PathCurve);
                    else
                        sweptSolidExporter.m_Facets = CreateSimpleSweptSolidAsBRep(exporterIFC, profileName, faceBoundaries, sweptAnalyzer.ReferencePlaneNormal, sweptAnalyzer.PathCurve);
                }
                return sweptSolidExporter;
            }
            catch (Exception)
            {
                return null;
            }
        }