Material Tag created by API does not show material data

Material Tag created by API does not show material data

boostyourbim
Advocate Advocate
4,457 Views
24 Replies
Message 1 of 25

Material Tag created by API does not show material data

boostyourbim
Advocate
Advocate

Hi,

 

This code creates a wall and material tags for each layer. The tag leaders are placed correctly (in the center of each wall layer) but the tags do not show the material data. 

 

Manually making any tweak to the tags (such as moving the leader elbow or text location) will get the tag to properly show the material value, but of course the goal of using the API to create the tags is that they will show the correct data without any manual intervention. I've tried different permutations with transactions to no avail. Any ideas?

 

            public void MakeWallAndTag()
        {
            Document doc = this.ActiveUIDocument.Document;
            List<XYZ> bottomFacesPts = new List<XYZ>();
            
            Wall wall = null;
            
            using (Transaction t = new Transaction(doc, "wall"))
            {
                t.Start();
                
                doc.ActiveView.DetailLevel = ViewDetailLevel.Fine;
                
                wall = Wall.Create(doc,
                    Line.CreateBound(XYZ.Zero, new XYZ(10,0,0)),
                    new FilteredElementCollector(doc).OfClass(typeof(Level)).FirstOrDefault().Id,
                    false);
                
                wall.WallType = new FilteredElementCollector(doc).OfClass(typeof(WallType)).Cast<WallType>().FirstOrDefault(q => q.Name == "Exterior - Brick on CMU");
                t.Commit();
            }
            
            using (Transaction t = new Transaction(doc, "Place tag"))
            {
                t.Start();
                List<ElementId> ids = new List<ElementId> { wall.Id };
                if (PartUtils.AreElementsValidForCreateParts(doc, ids))
                {
                    PartUtils.CreateParts(doc, ids);
                    doc.Regenerate();

                    foreach (ElementId id in ids)
                    {
                        if (!PartUtils.HasAssociatedParts(doc, id))
                        {
                            continue;
                        }

                        ICollection<ElementId> partIds = PartUtils.GetAssociatedParts(doc, id, truetrue);

                        foreach (ElementId partId in partIds)
                        {
                            Element part = doc.GetElement(partId);

                            bottomFacesPts.AddRange(GetBottomFacePoints(part));
                        }
                    }
                }
                t.RollBack();
            }
            
            using (Transaction t = new Transaction(doc, "tags"))
            {
                t.Start();
                foreach (XYZ pt in bottomFacesPts)
                {
                    IndependentTag tag = doc.Create.NewTag(doc.ActiveView, wall, true, TagMode.TM_ADDBY_MATERIAL, TagOrientation.Horizontal, pt);
                    tag.LeaderEnd = pt.Add(new XYZ(0.100));
                    tag.TagHeadPosition = pt.Add(new XYZ(-20,0));
                }
                t.Commit();
            }
        }
        
                public List<XYZ> GetBottomFacePoints(Element e)
        {
            List<XYZ> resultingPts = new List<XYZ>();

            FaceExtractor faceExtractor = new FaceExtractor(e);

            FaceArray faces = faceExtractor.Faces;

            if (faces.Size == 0) { return resultingPts; }

            foreach (Face face in faces)
            {
                PlanarFace pf = face as PlanarFace;

                if (pf == null) { continue; }

                if (pf.Normal.IsAlmostEqualTo(XYZ.BasisZ.Negate()))
                {
                    EdgeArrayArray edgeLoops = face.EdgeLoops;

                    foreach (EdgeArray edgeArray in edgeLoops)
                    {
                        foreach (Edge edge in edgeArray)
                        {
                            Line line = edge.AsCurve() as Line;
                            if (line == null)
                                continue;

                            if (!line.Direction.IsAlmostEqualTo(XYZ.BasisY) &&
                                !line.Direction.IsAlmostEqualTo(XYZ.BasisY.Negate()))
                                continue;

                            XYZ end0 = line.GetEndPoint(0);
                            XYZ end1 = line.GetEndPoint(1);

                            if (end0.X > 1)
                                continue;

                            Line ll = Line.CreateBound(end0, end1);

                            //List<XYZ> points = edge.Tessellate() as List<XYZ>;

                            resultingPts.Add(ll.Evaluate(0.5true));
                        }
                    }
                }
            }
            return resultingPts;
        }
        
           public class FaceExtractor
        {
            private Element _element;
            private Document _doc;
            private Autodesk.Revit.ApplicationServices.Application _app;
            private Autodesk.Revit.Creation.Application _appCreator;
            private Transform _matrix;
            private FaceArray _faces;

            /// <summary>
            /// Gets the transform for element
            /// </summary>
            public Transform Matrix
            {
                get { return _matrix; }
            }

            /// <summary>
            /// Gets faces
            /// </summary>
            public FaceArray Faces
            {
                get { return _faces; }
            }

            /// <summary>
            /// Default constructor
            /// </summary>
            /// <param name="element">element</param>
            public FaceExtractor(Element element)
            {
                _element = element;
                _doc = element.Document;
                _app = _doc.Application;
                _appCreator = _app.Create;
                GetFaces();
            }

            /// <summary>
            /// Retrieve all faces from the 
            /// given element's geometry solid.
            /// </summary>
            private void GetFaces()
            {
                Options geoOptions = _appCreator.NewGeometryOptions();
                geoOptions.ComputeReferences = true;
                GeometryElement geoElem = _element.get_Geometry(geoOptions);
                _faces = GetFacesFrom(geoElem);
            }

            /// <summary>
            /// Retrieve all faces from the first solid 
            /// encountered in the given geometry element.
            /// </summary>
            /// <param name="geoElement">geometry element</param>
            /// <returns>faces</returns>
            public FaceArray GetFacesFrom(GeometryElement geoElement)
            {
                foreach (object o in geoElement)
                {
                    Solid geoSolid = o as Solid;
                    if (null == geoSolid)
                    {
                        GeometryInstance instance = o as GeometryInstance;
                        if (null == instance)
                            continue;
                        GeometryElement geoElement2 = instance.SymbolGeometry;
                        _matrix = instance.Transform;
                        if (geoElement2 == null)
                            continue;
                        if (geoElement2.Count() == 0)
                            continue;
                        return GetFacesFrom(geoElement2);
                    }
                    FaceArray faces = geoSolid.Faces;
                    if (faces == null)
                        continue;
                    if (faces.Size == 0)
                        continue;
                    return geoSolid.Faces;
                }
                return null;
            }
        }

0 Likes
4,458 Views
24 Replies
Replies (24)
Message 21 of 25

jeremy_tammik
Alumni
Alumni

... still digging for this...

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 22 of 25

julianX4N5F
Explorer
Explorer

-

0 Likes
Message 23 of 25

Julian.Wandzilak
Advocate
Advocate

I had a similar problem in my toolbar (I hope to see it this week on Autodesk App Store – proud developer 😊). In one of my scripts, I wanted to list all empty material tags.

To the best of my knowledge in some cases “standard way” (Moving, view refreshing etc) does not work with some material tags and they still show empty. I didn’t find out why it is happening, but my script had the problem with the same material tags – In presentation project from Revit 2024 I had a problem with I think 25% of material tags. I think that moving them manually helped them – doing it automatic with Revit API for sure didn’t.   

To make my script work, I ended up completely rewriting the script. I looked for tags which did not refresh correctly, grouped them by the view, opened the view, added auto closing form (which needed at least 250 milliseconds -> It didn’t work with something super quick). This way, finally the material tags showed the correct values.

Example how it works below (I added some empty tags to the file so there is more than in standard Revit file):

 

https://drive.google.com/uc?export=view&id=1AxXl-a9nB0w8ji8VJm4NqfAdeAZQktB2

 

Sorry, for mess. I have too many different accounts on myself (with different licences) 😉

 

blog: w7k.pl more about me: Linkedin Profile
My add-ins for Revit: Drafter(180+ scripts) & Leveler
0 Likes
Message 24 of 25

jeremy_tammik
Alumni
Alumni

The development team says: The missing material tag issue is a known limitation and has not been completely resolved. To tackle this issue, we have implemented a multi-faceted approach. In some situations a short-term solution is feasible. This makes the tracking somewhat confusing for the uninitiated. In cases where a short-term solution is not possible, a Dynamo script can be used as a workaround. Such a script can automatically interact with the material tag and trigger its regeneration, similar to the approaches described above. For a long-term solution, we have initiated a release epic for redesign and research. This solution has undergone review and prioritization with our Product Manager (PM) and Engineering Manager (EM) teams, alongside other initiatives. Although addressing this issue remains a top priority, its complexity has led us to primarily focus on a future Revit release.

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 25 of 25

dhanait_ajay13
Enthusiast
Enthusiast

Found any solutions? i have same issue, when Manually making any tweak to the tags ( moving) will get the tag to properly show the material value, but using the API to create the tags is show the blank data.

0 Likes