Issues with getting column corner XYZ coordinates

Issues with getting column corner XYZ coordinates

kevin.anggrek
Enthusiast Enthusiast
2,028 Views
5 Replies
Message 1 of 6

Issues with getting column corner XYZ coordinates

kevin.anggrek
Enthusiast
Enthusiast

Hi all,

 

I was looking for methods to obtain the column corners/vertices coordinates and I stumbled upon this blog post by Jeremy in Building Coder: https://thebuildingcoder.typepad.com/blog/2012/06/real-world-concrete-corner-coordinates.html?utm_so...

 

I have tried the method posted in the Building Coder above. In the case when the code works properly, the number of unique vertices/corners for a rectangular column should be 8. I tried the method on several different Revit projects that I have. It worked perfectly as intended (giving an output of 8 corners). However, in one of the projects, the output of corners from a single column is 19 corners as shown below:

19 corners.png

I also tried to visualize the coordinates using a 3D plotter and it came out like this:

plotted column.png

As you can see, there are some coordinates at the top face which are actually not the vertices. What is the explanation to this?

 

I understand that In the method posted in Building Coder above, the Element (Column in this case) is used to obtain the GeometryElement. the GeometryElement contains GeometryObjects that could be Solid or GeometryInstance and this varies from column to column. If there are no Solids and only the GeometryInstance inside the GeometryObjects, the Solid is obtained from the Symbol Geometry of the GeometryInstance. The Solid is used to find the Faces of the Solid and each Face contains an EdgeArray object which in turn contains Edges. These Edges were used to find the unique vertices. Using similar approach to this, I also tried to get the Mesh inside the Face instead of the EdgeArray using the Face.Triangulate() method and then collect the vertices of the Mesh from Mesh.Vertices property. The same problem still arise, there are 19 corners found.

 

EDIT: In Debug mode, I tried to check the contents of the Solid where the issue is encountered. The Solid has 6 Faces (which should be correct for a rectangular column). Each Face should ended up with 4 number of Edge objects. However, I noticed that one of the Face contains 6 Edges, which is not normal for rectangular columns.

 

How do I solve this issue? Is it the problem with the columns? How should I fix them? Or can anyone suggest me different alternative ways to obtain the column corner coordinates?

 

Thanks in advance

0 Likes
Accepted solutions (1)
2,029 Views
5 Replies
Replies (5)
Message 2 of 6

RPTHOMAS108
Mentor
Mentor

What does column in question actually look like? Is top modified with cut?

 

When an instance has been modified by cuts it contains top level solids otherwise it will contain a GeometryInstance which then contains solids i.e. when it has not become unique compared to the original instance definition that is copied around.

 

In the arrangement of points at the top would also be wondering why a point is missing at one corner compared with the others. Would probably investigate how many edges for each face (should be four right?).

 

0 Likes
Message 3 of 6

kevin.anggrek
Enthusiast
Enthusiast

Thank you sir for the reply

 

Here, I would like to add some information while answering your question.

First, this is how my building looks in 3D:

 

3D View.png

 

Next, I managed to get the ElementId of the spcific column with 19 corners (the ID is 297426), it is highlighted below:

 

The highlighted column w/ 19 cornersThe highlighted column w/ 19 cornersThe respective column in Isolated ViewThe respective column in Isolated Viewthe column viewed from top of the 3D view that has been cut down by section boxthe column viewed from top of the 3D view that has been cut down by section boxzoomed inzoomed in

 

The column seems rectangular to me, is there any cuts caused by touching with other elements? (beams or slabs?)

 

I used both RevitLookup and the debug mode in C# in order to check the content of the GeometryElement of the Column and it gave the following output:

  • The Column has one GeometryInstance and 2 Solids
  • The GeometryInstance does not contain any SymbolGeometry (as shown in RevitLookup with non-bold texts)

Null SymbolGeom.png

  • The first Solid contains 6 Faces (which should be correct)
    1. The first Face contains 4 Edges
    2. The second Face contains 8 Edges (image as shown)six edge.png
    3. The third Face contains 7 Edges
    4. The fourth Face contains 7 Edges
    5. The fifth Face contains 8 Edges
    6. The sixth Face contains 12 Edges
  • The second Solid contain no Faces

From the result, it should be clear that there is something wrong with the Edges.

 

Below, I also attached the ExternalCommand Code that I used, most of them are adapted from Building Coder

 

 

 

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    class Tester4 : IExternalCommand
    {
        Result IExternalCommand.Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            Autodesk.Revit.Creation.Application app = commandData.Application.Application.Create;
            View currentView = doc.ActiveView;
            Options geomOpts = new Options();
            
            #region Column Vertices Tester
            IList<FamilyInstance> columnList = GetAllRevitColumns(doc);
            foreach (FamilyInstance column in columnList)
            {
                Solid solid = GetSolid(column, geomOpts);
                Dictionary<XYZ, int> corners = GetCorners(solid);
            }
            #endregion
            return Result.Succeeded;
        }
        public static IList<FamilyInstance> GetAllRevitColumns(Document M_doc)
        {
            // Category Filter
            BuiltInCategory[] bics = new BuiltInCategory[] {
                                        BuiltInCategory.OST_StructuralColumns,
                                        BuiltInCategory.OST_Columns
                                        };
            IList<ElementFilter> categoryFilterList = new List<ElementFilter>();
            foreach (BuiltInCategory category in bics)
            {
                categoryFilterList.Add(new ElementCategoryFilter(category));
            }
            LogicalOrFilter elementCategoryFilter = new LogicalOrFilter(categoryFilterList);

            // Collector (Quick Filters)
            FilteredElementCollector columnCtor = new FilteredElementCollector(M_doc)
                                                .WherePasses(elementCategoryFilter)
                                                .WhereElementIsNotElementType();

            IList<FamilyInstance> filteredColumnList = columnCtor
                                                            .Cast<FamilyInstance>()
                                                            .ToList();
            return filteredColumnList;
        }
        /// <summary>
        /// Define equality for Revit XYZ points.
        /// Very rough tolerance, as used by Revit itself.
        /// </summary>
        class XyzEqualityComparer : IEqualityComparer<XYZ>
        {
            const double _sixteenthInchInFeet
              = 1.0 / (16.0 * 12.0);

            public bool Equals(XYZ p, XYZ q)
            {
                return p.IsAlmostEqualTo(q,
                  _sixteenthInchInFeet);
            }

            public int GetHashCode(XYZ p)
            {
                return Util.PointString(p).GetHashCode();
            }
        }
        /// <summary>
        /// Return all the "corner" vertices of a given solid.
        /// Note that a circle in Revit consists of two arcs
        /// and will return a "corner" at each of the two arc
        /// end points.
        /// </summary>
        Dictionary<XYZ, int> GetCorners(Solid solid)
        {
            Dictionary<XYZ, int> corners
              = new Dictionary<XYZ, int>(
                new XyzEqualityComparer());

            foreach (Face f in solid.Faces)
            {
                foreach (EdgeArray ea in f.EdgeLoops)
                {
                    foreach (Edge e in ea)
                    {
                        XYZ p = e.AsCurveFollowingFace(f)
                          .GetEndPoint(0);

                        if (!corners.ContainsKey(p))
                        {
                            corners[p] = 0;
                        }
                        ++corners[p];
                    }
                }
            }
            return corners;
        }
        /// <summary>
        /// Retrieve the first non-empty solid found for 
        /// the given element. In case the element is a 
        /// family instance, it may have its own non-empty
        /// solid, in which case we use that. Otherwise we 
        /// search the symbol geometry. If we use the 
        /// symbol geometry, we have to keep track of the 
        /// instance transform to map it to the actual
        /// instance project location.
        /// </summary>
        Solid GetSolid(Element e, Options opt)
        {
            GeometryElement geo = e.get_Geometry(opt);

            Solid solid = null;
            GeometryInstance inst = null;
            Transform t = Transform.Identity;

            // Some columns have no solids, and we have to 
            // retrieve the geometry from the symbol; 
            // others do have solids on the instance itself 
            // and no contents in the instance geometry 
            // (e.g. in rst_basic_sample_project.rvt).

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

                if (null != solid
                  && 0 < solid.Faces.Size)
                {
                    break;
                }

                inst = obj as GeometryInstance;
            }

            if (null == solid && null != inst)
            {
                geo = inst.GetSymbolGeometry();
                t = inst.Transform;

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

                    if (null != solid
                      && 0 < solid.Faces.Size)
                    {
                        break;
                    }
                }
            }
            return solid;
        }

 

 

I also attached my Revit Project along with this reply. Should you need more information, I would be glad to add more. Thank you

0 Likes
Message 4 of 6

kevin.anggrek
Enthusiast
Enthusiast

I just did a further calculation on the coordinates of the 19 corners and I find that some coordinates at the top arrangement are 15 cm from each other. 15 cm is the exact thickness of the slabs adjacent to the columns and 15 cm is also the distance between column corners to the slab corners at their meeting point:

 

As an illustration, please see the following constructed 3D model from the 19 corner coordinates:

column in 3D with legend.png

 

Point 1 to 4 are located at the bottom face of the column (they are on the same height), point 5 to 16 are all located at the topmost face of the column (they are on the same height), while point 17 to 19 are located 15 cm below point 5 to 16. 15 cm is exactly the thickness of adjacent slabs to the column

 

Furthermore, I can confirm that point 5, 8, 11, and 14 are the correct corners of the top face of the column, while point 6, 7, 9, 10, 12, 13, 15, and 16 are the meeting points between the slabs and the column. What I mean by meeting point between slabs and column is shown below:

The meeting points are circled in redThe meeting points are circled in red

 

The distance between column corners and the meeting points circled in red are exactly 15 cm (150 mm) as shown in my CAD drawings:

150 mm.png

 

And I can confirm this because the distance between column corners (point 5 for example) to the meeting points next to it (point 6 and 16) are also 15 cm.

 

These facts indicate that the these incorrect corner coordinates are most likely caused by the slabs, but how did this happen and how do I fix this?

 

0 Likes
Message 5 of 6

RPTHOMAS108
Mentor
Mentor
Accepted solution

For geometry Options I would try setting the DetailLevel to Fine. Not sure this would have any benefit, only know that when this is set the geometry is not view specific.

 

There is probably an easier way to get the eight corners of a rectangular column based on parameter values. When you have section rotation, section size and length.

 

Alternatively if you need to eliminate those erroneous points you could align to a local system and compare XYZ's looking for all permutations of max and min for each ord. Each corner of a cube has a coordinate where each ord is either max/min for that ord. For slanted column you could also group points by level and then solve the max/min XY's for each.

 

At the same time you can compare the points in relation to face UV, since these extra points are not the max/min on any face that their parent edge corresponds to.

 

I think the geometry is created for graphical purposes so extra points may be to show different materials on different parts of face i.e. why no similar points further down the columns where the underside of beams intersect? So your task is probably one of noise reduction. 

 

Geometry extraction and analysis has overhead. If you get the parameters that define that geometry and determine from those the mathematical location of vertices, this is usually much quicker.

 

 

0 Likes
Message 6 of 6

kevin.anggrek
Enthusiast
Enthusiast

Thank you sir. For now I have decided to just filter out the unneeded points that are not the corners by following your suggestions. It works well for now!

0 Likes