Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

get conection type and geometry between two elements from the model

5 REPLIES 5
Reply
Message 1 of 6
SMarkova
2327 Views, 5 Replies

get conection type and geometry between two elements from the model

Hi Everyone,

 

Does anyone have tried and succeeded in identifiing the connection type between two elements in the model? For instance a point, line, surface conection and the corresponding geometry?

 

For example the connection between a wall and a column would be a surface with geometry  the cross section of the column and so on. The connection between a window and a wall would consist of  multiple faces.

 

 

 

Stani

5 REPLIES 5
Message 2 of 6
JimJia
in reply to: SMarkova

Hi, 

 

What's your API problem to achieve your request? 

 

Revit API provides geometry related API to retrieve solid, face, edges and vertexes of element geometry:

http://thebuildingcoder.typepad.com/blog/2010/01/geometry-options.html

http://thebuildingcoder.typepad.com/blog/2010/02/retrieving-column-and-stair-geometry.html

 

Regarding connection of elements, for example, you can use BooleanOperationsUtils API to get the connection solid of wall and column and then use the geometry API to retrieve your desired geometric information.

http://thebuildingcoder.typepad.com/blog/2011/06/boolean-operations-and-instancevoidcututils.html

 

Do you think this is helpful? 

 


Jim Jia
Autodesk Forge Evangelist
https://forge.autodesk.com
Developer Technical Services
Autodesk Developer Network
Email: Jim.Jia@autodesk.com
Message 3 of 6
SMarkova
in reply to: JimJia

Hi Jim,

 

Thank you very much for the reply!

 

We tried by retrieveng faces and edges of solids. However, we got an unexpected result of elements which accordingly were supposed to cut each other where they were at a significant distance from eacht other. Either me or my colleague would post the code to what we have tried here, because we were really curious of what caused this result.

 

I don't think however, that have tried both steps (BooleanOperationsUtils and geometry) as proposed by Jeremy. So thanks a lot for the hint!, we are going to try this one.

 

Greetings!

Stani

Message 4 of 6
Anonymous
in reply to: JimJia

Hi Jim,

Many thanks for the suggestions. We have tried different functions from the API to solve the problem. Here is our current logic flow to find the adjacent(touching) neighbors of an element:

1. For a particular model element, we apply BoundingBoxIntersectsFilter to find nearby elements. We apply additional constraints on this filter to limit only to nearby model elements. The purpose of this filter is to reduce the search space for the next searches.

 

            // Select something to use as base bounding box.
            Reference r = uiDoc.Selection.PickObject(ObjectType.Element);
            Element element = doc.GetElement(r.ElementId);
            BoundingBoxXYZ bb = element.get_BoundingBox(doc.ActiveView);
            Outline outline = new Outline(bb.Min, bb.Max);

            // Create a BoundingBoxIntersectsFilter to 
            // find everything intersecting the bounding 
            // box of the selected element.
            BoundingBoxIntersectsFilter bbfilter= new BoundingBoxIntersectsFilter(outline);

            // Use a view to construct the filter so we 
            // get only visible elements. 

            FilteredElementCollector collector= new FilteredElementCollector(doc, doc.ActiveView.Id);


            ICollection<ElementId> idsExclude
              = new List<ElementId>();

            idsExclude.Add(element.Id);

            Options opt = new Options();

            collector
              .Excluding(idsExclude)
              .WherePasses(bbfilter)
              .WhereElementIsNotElementType()
              .WhereElementIsViewIndependent()
              .Where<Element>(e
               => null != e.Category
               && !ElementFilterManager.SkipThisBic(e.Category.Id.IntegerValue)
               && e.Category.HasMaterialQuantities //is it true for all geometric elements?
               && null != e.get_Geometry(opt));
        static int[] _bics_to_skip = new int[] {
          ( int ) BuiltInCategory.OST_PreviewLegendComponents,
          ( int ) BuiltInCategory.OST_IOSSketchGrid,
          ( int ) BuiltInCategory.OST_Cameras,
          ( int ) BuiltInCategory.OST_Rooms,
          ( int ) BuiltInCategory.OST_SiteProperty
        };

        public static bool SkipThisBic(int bic)
        {
            return Array.Exists<int>(
              _bics_to_skip,
              delegate (int i)
              {
                  return i == bic;
              });
        }


2. Among these nearby elements, we want to filter the elements that touch or intersect with the selected element. There are couple of methods in the API to find intersection between solids or elements. This methods don't provide desirable results when two elements are only touching each other and not intersecting. We tried the following approaches:

i. We tried the method ExecuteBooleanOperation of BooleanOperationsUtils class to find intersection between two solids. For this we first identified the list of solids from each element. For every pair of solids, one from each list,  we apply ExecuteBooleanOperation to find whether there is any intersection. It returns null when two elements are only adjacent to each other.

 

        public static double ComputeIntersectionVolume(Solid solidA, Solid solidB)
        {
            //double volumeOfIntersection = 0.0;
            double surfaceAreaOfIntersection = 0.0;
            Solid intersection = BooleanOperationsUtils.ExecuteBooleanOperation(solidA, solidB, BooleanOperationsType.Intersect);
            if (intersection != null)
                surfaceAreaOfIntersection = intersection.SurfaceArea;
            return surfaceAreaOfIntersection;
        }


ii. The next approach we tried is intersection of faces. We extracted the visible faces from the elements into two lists, one for each element. For every pair of faces, one from each list, we applied the Face.Intersect method to identify intersecting faces. If two faces are intersecting, we can say that the elements they are originating from also intersects.

        public static List<double> ComputeIntersectionOfElements(Document doc, Element elementA, Element elementB)
        {
            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.IncludeNonVisibleObjects = false;

            List<double> results = new List<double>();
            double NoOfIntersectingFaces = 0.0;
            double NoOfIntersectingFacesFromManualCalculation = 0.0;

            GeometryElement elementAGeoElement = elementA.get_Geometry(opt);
            GeometryElement elementBGeoElement = elementB.get_Geometry(opt);

            CurveArray curvesA = new CurveArray();
            List<Solid> solidsA = new List<Solid>();

            AddCurvesAndSolids(elementAGeoElement, ref curvesA, ref solidsA);

            CurveArray curvesB = new CurveArray();
            List<Solid> solidsB = new List<Solid>();

            AddCurvesAndSolids(elementBGeoElement, ref curvesB, ref solidsB);

            List<Face> facesOfA = new List<Face>();
            List<Face> facesOfB = new List<Face>();

            FacesFromSolids(solidsA, facesOfA);
            FacesFromSolids(solidsB, facesOfB);

            foreach (Face fa in facesOfA)
            {
                foreach (Face fb in facesOfB)
                {
                    FaceIntersectionFaceResult fir = fa.Intersect(fb);
                    if (fir == FaceIntersectionFaceResult.Intersecting
                        && fa.Visibility == Visibility.Visible && fb.Visibility == Visibility.Visible
                        )
                    {

                        NoOfIntersectingFaces += 1;
                    }

                    if (DoFacesIntersect(fa, fb))
                    {
                        NoOfIntersectingFacesFromManualCalculation += 1;
                    }
                }
            }

            results.Add(NoOfIntersectingFaces);
            results.Add(NoOfIntersectingFacesFromManualCalculation);

            return results;
        }

        private static void FacesFromSolids(List<Solid> solidsA, List<Face> facesOfA)
        {
            foreach (Solid A in solidsA)
            {
                foreach (Face fa in A.Faces)
                {
                    ElementId mid = fa.MaterialElementId;
                    if (mid == null)
                    {
                        continue;
                    }

                    facesOfA.Add(fa);
                }
            }
        }

        private static void AddCurvesAndSolids(Autodesk.Revit.DB.GeometryElement geomElem,
                                ref Autodesk.Revit.DB.CurveArray curves,
                                ref System.Collections.Generic.List<Autodesk.Revit.DB.Solid> solids)
        {
            foreach (Autodesk.Revit.DB.GeometryObject geomObj in geomElem)
            {

                Autodesk.Revit.DB.Curve curve = geomObj as Autodesk.Revit.DB.Curve;
                if (null != curve)
                {

                    curves.Append(curve);
                    continue;
                }
                Autodesk.Revit.DB.Solid solid = geomObj as Autodesk.Revit.DB.Solid;
                if (null != solid && solid.Volume != 0 && solid.Visibility == Visibility.Visible && !solid.Edges.IsEmpty)
                {

                    solids.Add(solid);
                    continue;
                }
                //If this GeometryObject is Instance, call AddCurvesAndSolids
                Autodesk.Revit.DB.GeometryInstance geomInst = geomObj as Autodesk.Revit.DB.GeometryInstance;
                if (null != geomInst)
                {
                    Autodesk.Revit.DB.GeometryElement transformedGeomElem
                      = geomInst.GetInstanceGeometry(geomInst.Transform);
                    AddCurvesAndSolids(transformedGeomElem, ref curves, ref solids);
                }
            }
        }


But this method gives us unexpected results. It returns false positive when there is an element close to a Window element. For example, in the attached Revit model, the window (next to tag 46) and the "Furniture:Seating - Artemis" element are intersecting even though they are not adjacent(highlighted in the attached picture). If we flip the facing of the Window instance, they are not intersecting anymore.  We are quite curious what could be the reason behind this.

We have tried with our own face intersection method instead of the Face.Intersect method from the API. They are not giving us false positive, but they return negative for adjacent elements.

        static private bool DoFacesIntersect(Face faceA, Face faceB)
        {
            foreach (EdgeArray edges in faceB.EdgeLoops)
            {
                foreach (Edge edge in edges)
                {
                    IList<XYZ> epts = edge.Tessellate();
                    foreach (XYZ ept in epts)
                    {
                        // project the point to face and then check if the distance of point
                        // to face is zero.
                        // Note: if the nearest point is outside of this face,the result will null,
                        IntersectionResult intResult = faceA.Project(ept);
                        if (intResult != null)
                        {
                            // The project distance should be zero if point is on face
                            if (Math.Abs(intResult.Distance) < Double.Epsilon)
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }



iii. We have investigated ElementIntersectsFilter and ElementIntersectsSolidFilter, still no success for adjacent elements. It seems they return null when the elements are adjacent only and non intersecting. It seems all methods or filters for finding intersection do not identify when two elements are only adjacent each other.

iv. We saw a discussion about filter for touching beams in buildingcoder. Here a new sphere is created at the end of a beam. ElementIntersectsSolidFilter is used to find the elements touching at the end of the beam. We are yet to find a solution which can be applied to any model element. Is there any efficient way to apply this solution  for a model element with many curved faces and irregular shape?

Filter for Touching Beams Using Solid Intersection

Greetings!
Sharif

Message 5 of 6
JimJia
in reply to: Anonymous

Hi,

Please accept our sincerer apology for the delay!

Revit has some known issues on ElementIntersectsSolidFilter, this should be reason why some unexpected results occur, please refer to similar pages below:
http://forums.autodesk.com/t5/revit-api-forum/light-source-with-elementintersectsfilter/m-p/6304618/...

http://forums.autodesk.com/t5/revit-api-forum/find-roof-soffits-using-elementintersectssolidfilter/m...

Jim Jia
Autodesk Forge Evangelist
https://forge.autodesk.com
Developer Technical Services
Autodesk Developer Network
Email: Jim.Jia@autodesk.com
Message 6 of 6
Anonymous
in reply to: JimJia

Hi,

 

Many thanks for the reply  and the links to the discussions on similar topics. We are planning to use the filter for some parts of our logic. It would be great if there is an update on issue REVIT-100856 .

 

Greetings!

Sharif

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community