Exemple #1
0
        /// <summary>
        ///     Gets the element's projection area.
        /// </summary>
        /// <param name="elm">A element</param>
        /// <exception cref="T:Autodesk.Revit.Exceptions.ArgumentNullException">The input element is invalid.</exception>
        /// <returns>Returns projection area.</returns>
        public static double GetShadowArea(this Element elm)
        {
            if (elm is null)
            {
                throw new ArgumentNullException(nameof(elm));
            }

            if (!elm.IsValidObject)
            {
                throw new InvalidDataException(nameof(elm));
            }

            if (elm.Id.IntegerValue == -1)
            {
                throw new InvalidDataException(nameof(elm));
            }

            var areas = new List <double>();
            var geo   = elm.get_Geometry(new Options());

            foreach (var instance in geo.Select(s => s as GeometryInstance))
            {
                if (instance is null)
                {
                    continue;
                }

                foreach (var item in instance.GetInstanceGeometry())
                {
                    var solid = item as Solid;

                    if (null == solid || solid.Faces.Size <= 0)
                    {
                        continue;
                    }

                    var plane = XYZ.BasisZ.CreatePlane(XYZ.Zero);

                    ExtrusionAnalyzer analyzer;

                    try
                    {
                        analyzer = ExtrusionAnalyzer.Create(solid, plane, XYZ.BasisZ);
                    }
                    catch
                    {
                        continue;
                    }

                    if (analyzer is null)
                    {
                        continue;
                    }

                    areas.Add(analyzer.GetExtrusionBase().Area);
                }
            }

            return(areas.Max());
        }
Exemple #2
0
        /// <summary>
        /// Gets the element's projection area.
        /// </summary>
        /// <param name="elm">A element</param>
        /// <remarks>Returns projection area, that area unit is square meter.</remarks>
        /// <exception cref="T:Autodesk.Revit.Exceptions.ArgumentNullException">The input element is invalid.</exception>
        /// <returns>Returns projection area.</returns>
        public static double GetShadowArea(this Element elm)
        {
            if (elm == null)
            {
                throw new ArgumentNullException(nameof(elm));
            }

            var areas = new List <double>();
            var geo   = elm.get_Geometry(new Options());

            foreach (var instance in geo.Select(s => s as GeometryInstance))
            {
                if (instance == null)
                {
                    continue;
                }

                foreach (var item in instance.GetInstanceGeometry())
                {
                    var solid = item as Solid;

                    if (null == solid || solid.Faces.Size <= 0)
                    {
                        continue;
                    }

                    var plane = Plane.CreateByOriginAndBasis(XYZ.Zero, XYZ.BasisX, XYZ.BasisY);

                    ExtrusionAnalyzer analyzer;

                    try
                    {
                        analyzer = ExtrusionAnalyzer.Create(solid, plane, XYZ.BasisZ);
                    }
                    catch
                    {
                        continue;
                    }

                    if (analyzer == null)
                    {
                        continue;
                    }

                    areas.Add(analyzer.GetExtrusionBase().Area *FT2_TO_M2);
                }
            }

            return(areas.Max());
        }
Exemple #3
0
        /// <summary>
        /// Add all plan view boundary loops from
        /// given solid to the list of loops.
        /// The creation application argument is used to
        /// reverse the extrusion analyser output curves
        /// in case they are badly oriented.
        /// </summary>
        /// <returns>Number of loops added</returns>
        static int AddLoops(
            Autodesk.Revit.Creation.Application creapp,
            JtLoops loops,
            GeometryObject obj,
            ref int nExtrusionAnalysisFailures)
        {
            int nAdded = 0;

            Solid solid = obj as Solid;

            if (null != solid &&
                0 < solid.Faces.Size)
            {
                //Plane plane = new Plane(XYZ.BasisX,
                //  XYZ.BasisY, XYZ.Zero); // 2016

                Plane plane = Plane.CreateByOriginAndBasis(
                    XYZ.Zero, XYZ.BasisX, XYZ.BasisY); // 2017

                ExtrusionAnalyzer extrusionAnalyzer = null;

                try
                {
                    extrusionAnalyzer = ExtrusionAnalyzer.Create(
                        solid, plane, XYZ.BasisZ);
                }
                catch (Autodesk.Revit.Exceptions
                       .InvalidOperationException)
                {
                    ++nExtrusionAnalysisFailures;
                    return(nAdded);
                }

                Face face = extrusionAnalyzer
                            .GetExtrusionBase();

                loops.Add(GetLoop(creapp, face));

                ++nAdded;
            }
            return(nAdded);
        }
Exemple #4
0
        private static IEnumerable <CurveLoop> GetCountours(
            Solid solid,
            Element element)
        {
            try
            {
                var plane = Plane.CreateByNormalAndOrigin(
                    XYZ.BasisZ, element.get_BoundingBox(null).Min);

                var analyzer = ExtrusionAnalyzer.Create(
                    solid, plane, XYZ.BasisZ);

                var face = analyzer.GetExtrusionBase();

                return(face.GetEdgesAsCurveLoops());
            }
            catch (InvalidOperationException)
            {
                return(Enumerable.Empty <CurveLoop>());
            }
        }
        /// <summary>
        /// Set the ExtrusionBase from the ExtrusionAnalyzer
        /// </summary>
        /// <param name="extrusionAnalyzer">Extrusion Analyzer</param>
        /// <param name="lcs">the LCS</param>
        /// <param name="baseLoopOffset">offset</param>
        public FootPrintInfo(ExtrusionAnalyzer extrusionAnalyzer, Transform lcs = null, XYZ baseLoopOffset = null)
        {
            Face extrusionBase = extrusionAnalyzer.GetExtrusionBase();
            IList <GeometryUtil.FaceBoundaryType> boundaryTypes;

            if (lcs == null)
            {
                lcs = Transform.Identity;
            }

            if (baseLoopOffset == null)
            {
                baseLoopOffset = XYZ.Zero;
            }

            IList <CurveLoop> extrusionBoundaryLoops =
                GeometryUtil.GetFaceBoundaries(extrusionBase, baseLoopOffset, out boundaryTypes);

            if (extrusionBoundaryLoops == null || extrusionBoundaryLoops.Count == 0 || extrusionBoundaryLoops[0] == null)
            {
                return;
            }

            // Move base plane to start parameter location.
            Plane extrusionBasePlane = null;

            try
            {
                extrusionBasePlane = extrusionBoundaryLoops[0].GetPlane();
            }
            catch
            {
                return;
            }

            // Only the first CurveLoop will be used as the foorprint
            ExtrusionBaseLoops = extrusionBoundaryLoops;
            ExtrusionBaseLCS   = lcs;
        }
        /// <summary>
        /// Group the extra faces in the extrusion by element id, representing clippings, recesses, and openings.
        /// </summary>
        /// <param name="elem">The element generating the base extrusion.</param>
        /// <param name="analyzer">The extrusion analyzer.</param>
        /// <returns>A list of connected faces for each element id that cuts the extrusion</returns>
        public static IDictionary<ElementId, ICollection<ICollection<Face>>> GetCuttingElementFaces(Element elem, ExtrusionAnalyzer analyzer)
        {
            IDictionary<ElementId, HashSet<Face>> cuttingElementFaces = new Dictionary<ElementId, HashSet<Face>>();

            IDictionary<Face, ExtrusionAnalyzerFaceAlignment> allFaces = analyzer.CalculateFaceAlignment();
            foreach (KeyValuePair<Face, ExtrusionAnalyzerFaceAlignment> currFace in allFaces)
            {
                if (currFace.Value == ExtrusionAnalyzerFaceAlignment.FullyAligned)
                    continue;

                EdgeArrayArray faceEdges = currFace.Key.EdgeLoops;
                int numBoundaries = faceEdges.Size;
                if (numBoundaries == 0)
                    continue;
                if (numBoundaries > 1)
                    throw new Exception("Can't handle faces with interior boundaries.");

                ICollection<ElementId> generatingElementIds = elem.GetGeneratingElementIds(currFace.Key);
                foreach (ElementId generatingElementId in generatingElementIds)
                {
                    HashSet<Face> elementFaces;
                    if (cuttingElementFaces.ContainsKey(generatingElementId))
                    {
                        elementFaces = cuttingElementFaces[generatingElementId];
                    }
                    else
                    {
                        elementFaces = new HashSet<Face>();
                        cuttingElementFaces[generatingElementId] = elementFaces;
                    }
                    elementFaces.Add(currFace.Key);
                }
            }

            IDictionary<ElementId, ICollection<ICollection<Face>>> cuttingElementFaceCollections =
                new Dictionary<ElementId, ICollection<ICollection<Face>>>();
            foreach (KeyValuePair<ElementId, HashSet<Face>> cuttingElementFaceCollection in cuttingElementFaces)
            {
                ICollection<ICollection<Face>> faceCollections = new List<ICollection<Face>>();
                // Split into separate collections based on connectivity.
                while (cuttingElementFaceCollection.Value.Count > 0)
                {
                    IList<Face> currCollection = new List<Face>();
                    IEnumerator<Face> cuttingElementFaceCollectionEnumerator = cuttingElementFaceCollection.Value.GetEnumerator();
                    cuttingElementFaceCollectionEnumerator.MoveNext();
                    Face currFace = cuttingElementFaceCollectionEnumerator.Current;
                    currCollection.Add(currFace);
                    cuttingElementFaceCollection.Value.Remove(currFace);

                    IList<Face> facesToProcess = new List<Face>();
                    facesToProcess.Add(currFace);

                    if (cuttingElementFaceCollection.Value.Count > 0)
                    {
                        while (facesToProcess.Count > 0)
                        {
                            currFace = facesToProcess[0];
                            EdgeArray faceOuterBoundary = currFace.EdgeLoops.get_Item(0);

                            foreach (Edge edge in faceOuterBoundary)
                            {
                                Face adjoiningFace = edge.get_Face(1);
                                if (adjoiningFace.Equals(currFace))
                                    adjoiningFace = edge.get_Face(0);

                                if (cuttingElementFaceCollection.Value.Contains(adjoiningFace))
                                {
                                    currCollection.Add(adjoiningFace);
                                    cuttingElementFaceCollection.Value.Remove(adjoiningFace);
                                    facesToProcess.Add(adjoiningFace);
                                }
                            }

                            facesToProcess.Remove(facesToProcess[0]);
                        }
                    }

                    faceCollections.Add(currCollection);
                }

                cuttingElementFaceCollections[cuttingElementFaceCollection.Key] = faceCollections;
            }

            return cuttingElementFaceCollections;
        }
        /// <summary>
        /// Retrieve all plan view boundary loops from
        /// all solids of the given element geometry
        /// united together.
        /// </summary>
        internal static JtLoops GetPlanViewBoundaryLoopsGeo(
            Autodesk.Revit.Creation.Application creapp,
            GeometryElement geo,
            ref int nFailures)
        {
            Solid union = null;

            Plane plane = new Plane(XYZ.BasisX,
                                    XYZ.BasisY, XYZ.Zero);

            foreach (GeometryObject obj in geo)
            {
                Solid solid = obj as Solid;

                if (null != solid &&
                    0 < solid.Faces.Size)
                {
                    // Some solids, e.g. in the standard
                    // content 'Furniture Chair - Office'
                    // cause an extrusion analyser failure,
                    // so skip adding those.

                    try
                    {
                        ExtrusionAnalyzer extrusionAnalyzer
                            = ExtrusionAnalyzer.Create(
                                  solid, plane, XYZ.BasisZ);
                    }
                    catch (Autodesk.Revit.Exceptions
                           .InvalidOperationException)
                    {
                        solid = null;
                        ++nFailures;
                    }

                    if (null != solid)
                    {
                        if (null == union)
                        {
                            union = solid;
                        }
                        else
                        {
                            try
                            {
                                union = BooleanOperationsUtils
                                        .ExecuteBooleanOperation(union, solid,
                                                                 BooleanOperationsType.Union);
                            }
                            catch (Autodesk.Revit.Exceptions
                                   .InvalidOperationException)
                            {
                                ++nFailures;
                            }
                        }
                    }
                }
            }

            JtLoops loops = new JtLoops(1);

            AddLoops(creapp, loops, union, ref nFailures);

            return(loops);
        }
        /// <summary>
        /// Generates an IFCExtrusionCreationData from ExtrusionAnalyzer results
        /// </summary>
        /// <remarks>This will be used to populate certain property sets.</remarks>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="projDir">The projection direction of the extrusion.</param>
        /// <param name="analyzer">The extrusion analyzer.</param>
        /// <returns>The IFCExtrusionCreationData information.</returns>
        public static IFCExtrusionCreationData GetExtrusionCreationDataFromAnalyzer(ExporterIFC exporterIFC, XYZ projDir, ExtrusionAnalyzer analyzer)
        {
            IFCExtrusionCreationData exportBodyParams = new IFCExtrusionCreationData();

            XYZ extrusionDirection = analyzer.ExtrusionDirection;

            double zOff = MathUtil.IsAlmostEqual(Math.Abs(projDir[2]), 1.0) ? (1.0 - Math.Abs(extrusionDirection[2])) : Math.Abs(extrusionDirection[2]);
            double scaledAngle = UnitUtil.ScaleAngle(MathUtil.SafeAsin(zOff));

            exportBodyParams.Slope = scaledAngle;
            exportBodyParams.ScaledLength = UnitUtil.ScaleLength(analyzer.EndParameter - analyzer.StartParameter);
            exportBodyParams.ExtrusionDirection = extrusionDirection;

            // no opening data support yet.

            Face extrusionBase = analyzer.GetExtrusionBase();
            if (extrusionBase == null)
                return null;

            IList<GeometryUtil.FaceBoundaryType> boundaryTypes;
            IList<CurveLoop> boundaries = GeometryUtil.GetFaceBoundaries(extrusionBase, XYZ.Zero, out boundaryTypes);
            if (boundaries.Count == 0)
                return null;

            Plane plane = null;
            double height = 0.0, width = 0.0;
            if (ExtrusionExporter.ComputeHeightWidthOfCurveLoop(boundaries[0], plane, out height, out width))
            {
                exportBodyParams.ScaledHeight = UnitUtil.ScaleLength(height);
                exportBodyParams.ScaledWidth = UnitUtil.ScaleLength(width);
            }

            double area = extrusionBase.Area;
            if (area > 0.0)
            {
                exportBodyParams.ScaledArea = UnitUtil.ScaleArea(area);
            }

            double innerPerimeter = ExtrusionExporter.ComputeInnerPerimeterOfCurveLoops(boundaries);
            double outerPerimeter = ExtrusionExporter.ComputeOuterPerimeterOfCurveLoops(boundaries);
            if (innerPerimeter > 0.0)
                exportBodyParams.ScaledInnerPerimeter = UnitUtil.ScaleLength(innerPerimeter);
            if (outerPerimeter > 0.0)
                exportBodyParams.ScaledOuterPerimeter = UnitUtil.ScaleLength(outerPerimeter);

            return exportBodyParams;
        }
Exemple #9
0
        /// <summary>
        /// Group the extra faces in the extrusion by element id, representing clippings, recesses, and openings.
        /// </summary>
        /// <param name="elem">The element generating the base extrusion.</param>
        /// <param name="analyzer">The extrusion analyzer.</param>
        /// <returns>A list of connected faces for each element id that cuts the extrusion</returns>
        public static IDictionary <ElementId, ICollection <ICollection <Face> > > GetCuttingElementFaces(Element elem, ExtrusionAnalyzer analyzer)
        {
            IDictionary <ElementId, HashSet <Face> > cuttingElementFaces = new Dictionary <ElementId, HashSet <Face> >();

            IDictionary <Face, ExtrusionAnalyzerFaceAlignment> allFaces = analyzer.CalculateFaceAlignment();

            foreach (KeyValuePair <Face, ExtrusionAnalyzerFaceAlignment> currFace in allFaces)
            {
                if (currFace.Value == ExtrusionAnalyzerFaceAlignment.FullyAligned)
                {
                    continue;
                }

                EdgeArrayArray faceEdges     = currFace.Key.EdgeLoops;
                int            numBoundaries = faceEdges.Size;
                if (numBoundaries == 0)
                {
                    continue;
                }
                if (numBoundaries > 1)
                {
                    throw new Exception("Can't handle faces with interior boundaries.");
                }

                ICollection <ElementId> generatingElementIds = elem.GetGeneratingElementIds(currFace.Key);
                foreach (ElementId generatingElementId in generatingElementIds)
                {
                    HashSet <Face> elementFaces;
                    if (cuttingElementFaces.ContainsKey(generatingElementId))
                    {
                        elementFaces = cuttingElementFaces[generatingElementId];
                    }
                    else
                    {
                        elementFaces = new HashSet <Face>();
                        cuttingElementFaces[generatingElementId] = elementFaces;
                    }
                    elementFaces.Add(currFace.Key);
                }
            }

            IDictionary <ElementId, ICollection <ICollection <Face> > > cuttingElementFaceCollections =
                new Dictionary <ElementId, ICollection <ICollection <Face> > >();

            foreach (KeyValuePair <ElementId, HashSet <Face> > cuttingElementFaceCollection in cuttingElementFaces)
            {
                ICollection <ICollection <Face> > faceCollections = new List <ICollection <Face> >();
                // Split into separate collections based on connectivity.
                while (cuttingElementFaceCollection.Value.Count > 0)
                {
                    IList <Face>       currCollection = new List <Face>();
                    IEnumerator <Face> cuttingElementFaceCollectionEnumerator = cuttingElementFaceCollection.Value.GetEnumerator();
                    cuttingElementFaceCollectionEnumerator.MoveNext();
                    Face currFace = cuttingElementFaceCollectionEnumerator.Current;
                    currCollection.Add(currFace);
                    cuttingElementFaceCollection.Value.Remove(currFace);

                    IList <Face> facesToProcess = new List <Face>();
                    facesToProcess.Add(currFace);

                    if (cuttingElementFaceCollection.Value.Count > 0)
                    {
                        while (facesToProcess.Count > 0)
                        {
                            EdgeArray faceOuterBoundary = facesToProcess[0].EdgeLoops.get_Item(0);

                            foreach (Edge edge in faceOuterBoundary)
                            {
                                Face adjoiningFace = edge.get_Face(1);
                                if (adjoiningFace.Equals(currFace))
                                {
                                    adjoiningFace = edge.get_Face(0);
                                }

                                if (cuttingElementFaceCollection.Value.Contains(adjoiningFace))
                                {
                                    currCollection.Add(adjoiningFace);
                                    cuttingElementFaceCollection.Value.Remove(adjoiningFace);
                                    facesToProcess.Add(adjoiningFace);
                                }
                            }

                            facesToProcess.Remove(facesToProcess[0]);
                        }
                    }

                    faceCollections.Add(currCollection);
                }

                cuttingElementFaceCollections[cuttingElementFaceCollection.Key] = faceCollections;
            }

            return(cuttingElementFaceCollections);
        }