Material Tag created by API does not show material data

Material Tag created by API does not show material data

boostyourbim
Advocate Advocate
4,389 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,390 Views
24 Replies
Replies (24)
Message 2 of 25

jeremytammik
Autodesk
Autodesk

Dear Harry,

 

If you say a manual tweak does the job, you might also want to try some of the tricks listed to refresh element graphics, such as moving the tag by a zero distance, or a non-zero Z offset up and then back down again, jiggling it a bit:

 

http://thebuildingcoder.typepad.com/blog/2014/06/refresh-element-graphics-display.html

 

That might work programmatically as well.

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 3 of 25

boostyourbim
Advocate
Advocate
Hi Jeremy,

I tried various combinations of doc.regenerate(), transactions, tweaks, etc. None of them worked. Can you forward this to the development team for review?

Thanks
Harry
0 Likes
Message 4 of 25

jeremytammik
Autodesk
Autodesk

Dear Harry, 

 

Sure, with pleasure.

 

Please put together a full reproducible case for me to pass on to them, including minimal sample RVT model, one-click-to-compile-and-debug minimal sample code, preferably embedded within a macro in the document, and detailed step-by-step instructions to reproduce:

 

http://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

Thank you!

 

I wish you a wonderful weekend!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 5 of 25

Anonymous
Not applicable
Did you try the move by zero distance? That will fix it.
0 Likes
Message 6 of 25

boostyourbim
Advocate
Advocate

Hi Scott,

 

Thanks for your suggestion, but no this doesn't fix it

 

            List<ElementId> tagIds = new List<ElementId>();
            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));
                    tagIds.Add(tag.Id);
                }
                t.Commit();
            }

            using (Transaction t = new Transaction(doc, "move"))
            {
                t.Start();
                foreach (ElementId id in tagIds)
                {
                    ElementTransformUtils.MoveElement(doc, id, new XYZ(0.100));
                }
                t.Commit();
            }

0 Likes
Message 7 of 25

boostyourbim
Advocate
Advocate

Thank you Jeremy. The RVT with a document macro is at

https://drive.google.com/open?id=0BwszsfY3OsZHdi1aMkt6ZU9pVmM

0 Likes
Message 8 of 25

jeremytammik
Autodesk
Autodesk

Dear Harry,

 

Thank you for your reproducible case.

 

I logged the issue REVIT-90853 [Material Tag created by API does not show material data -- 11762052] with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.

 

You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.

 

This issue is important to me. What can I do to help?

 

This issue needs to be assessed by our engineering team, and prioritised against all of the other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

I hope this helps.

 

Best regards,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 9 of 25

Anonymous
Not applicable

I took a look at your example and yup, it's a stubborn one alright, you can flip the orientation of the tag, enable/ disable leader, move the wall, flip the wall and even change the wall type and the tag refuses to show the materials until the position is changed manually in the GUI.

 

Hopefully the dev team come up with something for you.

 

In the meantime I came up with an ingenious workaround:

 

 TaskDialog.Show("API bug detected","Please jiggle the position of each created tag to display material labels"); 

Smiley LOL

 

 

Message 10 of 25

YarUnderoaker
Collaborator
Collaborator

Hello guis.

Revit 2018.3 still have same problem!

I there is any other workaround?

Message 11 of 25

YarUnderoaker
Collaborator
Collaborator

I was find workaround - copy to clipboard newly created elements with the following paste using post command mechanics.

		public void CopyPasta()
		{
         	Document doc = this.ActiveUIDocument.Document;
         	var id = RevitCommandId.LookupPostableCommandId(PostableCommand.CutToClipboard);

    		var commandMonitor = new RevitCommandEndedMonitor(this);
    		commandMonitor.CommandEnded += OnCommandEnded;
    		PostCommand(id);
    		        	    
		}
		
		private void OnCommandEnded(object sender, EventArgs eventArgs)
		{
		    RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.PasteFromClipboard);
		    PostCommand(id);
		}
Message 12 of 25

harrymattison
Advocate
Advocate

Hi Jeremy,

Could you check with the Dev team about the status of a fix for this bug? It is still happening in 2019.2.

 

Bug:

private void create(FamilySymbol fs, XYZ pt, Material m, Level level)
        {
            Document doc = fs.Document;
            FamilyInstance fi = null;
            using (Transaction t = new Transaction(doc, "a"))
            {
                t.Start();
                if (!fs.IsActive)
                    fs.Activate();
                fi = doc.Create.NewFamilyInstance(pt, fs, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
                Family materialTagFamily = new FilteredElementCollector(doc).OfClass(typeof(Family)).Cast<Family>().
                    FirstOrDefault(q => q.FamilyCategoryId.IntegerValue == (int)BuiltInCategory.OST_MaterialTags);
                if (materialTagFamily != null)
                {
                    IndependentTag tag = IndependentTag.Create(doc,
                        doc.ActiveView.Id,
                        new Reference(fi),
                        false,
                        TagMode.TM_ADDBY_MATERIAL,
                        TagOrientation.Horizontal,
                        pt);
                    tag.TagHeadPosition = pt.Add(new XYZ(0.1, 0, 0));
                }
                t.Commit();
            }

Workaround. Put the creation and "tweak" of the tag in separate transactions:

        private void create(FamilySymbol fs, XYZ pt, Material m, Level level)
        {
            Document doc = fs.Document;
            FamilyInstance fi = null;
            using (Transaction t = new Transaction(doc, "a"))
            {
                t.Start();
                if (!fs.IsActive)
                    fs.Activate();
                fi = doc.Create.NewFamilyInstance(pt, fs, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
                t.Commit();
            }
            using (Transaction t = new Transaction(doc, "b"))
            {
                t.Start();
                Family materialTagFamily = new FilteredElementCollector(doc).OfClass(typeof(Family)).Cast<Family>().
                    FirstOrDefault(q => q.FamilyCategoryId.IntegerValue == (int)BuiltInCategory.OST_MaterialTags);
                if (materialTagFamily != null)
                {
                    IndependentTag tag = IndependentTag.Create(doc,
                        doc.ActiveView.Id,
                        new Reference(fi),
                        false,
                        TagMode.TM_ADDBY_MATERIAL,
                        TagOrientation.Horizontal,
                        pt);
                    tag.TagHeadPosition = pt.Add(new XYZ(0.1, 0, 0));
                }
                t.Commit();
            }
        }
Message 13 of 25

jeremytammik
Autodesk
Autodesk

Dear Harry,

 

Thank you for raising this issue again and above all for discovering and sharing this effective workaround!

 

First, here is some news on the development issue REVIT-90853 [Material Tag created by API does not show material data -- 11762052]:

 

This is related to other, older issues:

 

  • REVIT-20249 [As a Revit user, I want my material tags to stop displaying "?" after minor changes to the model, so that I don't have to waste time regening or nudging all material tags right before printing a drawing set]
  • REVIT-31149 [Material tags' information displays only question marks after placing them]
  • REVIT-90853 [Material Tag created by API does not show material data -- 11762052]

 

We therefore closed REVIT-90853 as Duplicate.

 

Unfortunately, this is not a simple bug fix.

 

It involves reworking the underlying code of material tags and we don't have a good solution, so we have not been able to prioritise this for the near future.

 

For the sake of completeness, please raise a wish list item for this in the Revit Idea Station as well and ensure that it gets lots of votes.

 

Thank you!

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 14 of 25

Anonymous
Not applicable

Hi Jeremy,

 

I'm not sure if this issue has been officially solved but I also encountered this problem a few days ago and finally found a workaround.

 

I tried to create a material tag with leader with Revit API but the tagtext was always a question mark and none of the solutions that I could find from the Internet ever worked. You have to manually click on the tag or move it a little bit to activate it to show the right tagtext but you couldn't activate it with codes which is quite frustrating. But after some more experiment I happen to find a workaround which is quite simple:

 

Always set bool addLeader to false when you use IndependentTag.Create() and then set tag.HasLeader to true and LeaderEndCondition to Free, then you can place the LeaderEndLeaderElbow and TagHeadPosition wherever you want and the tagtext still shows correctly.

 

Hope this helps!

 

Best,

Leo

Message 15 of 25

jeremytammik
Autodesk
Autodesk

Thank you very much for your update to this thread.

 

As I just mentioned in our other discussion, here are a few other related threads:

 

This issue has been discussed repeatedly here in the past, but not really explained in depth:

 

 

Apparently, there can be several different causes and it is important to understand from an end user point of view first.

 

I searched the Internet for 'revit material tag question mark':

 

https://duckduckgo.com/?q=revit+material+tag+question+mark

 

That returns a number of useful explanations:

 

This knowledgebase article explains some reasons and how to handle them:

 

 

Here is a real-world discussion that explains various additional aspects and problems that may arise:

 

 

I shared three development ticket numbers in a previous answer above; one was closed as duplicate, the other two remain open:

 

  • REVIT-20249 [As a Revit user, I want my material tags to stop displaying "?" after minor changes to the model, so that I don't have to waste time regening or nudging all material tags right before printing a drawing set]
  • REVIT-31149 [Material tags' information displays only question marks after placing them]

 

I added notes of your updates to both threads to both of these issues.

 

You say you tried all available workarounds, and you also list your own.

 

Several more are listed earlier in this very thread, and the developers reported success.

 

Are you absolutely sure you tried all of them?

 

Why would they work for the other developers and not for you?

 

So, does the workaround you describe yourself work better for you?

 

In that case, I hope it does for others as well.

 

Maybe the suggestion below to toggle the view template view scale is the simplest and most effective?

 

Would you like to try that out as well?

 

Thank you!

 

Workarounds:

 

  • In REVIT-31149 by Kelsey Skaug: change the scale in the view template and then change it back; this toggles all the views that use that view template
  • Workaround by YarUnderoaker: Copy to clipboard newly created elements followed by paste using PostCommand
  • Workaround by Harry Mattison: Put the creation and "tweak" of the tag in separate transactions
  • Workaround by Leo 229739876: Set bool addLeader to false in IndependentTag.Create and then set tag.HasLeader to true and LeaderEndCondition to Free; then you can place the LeaderEnd, LeaderElbow and TagHeadPosition wherever you want and the tagtext still shows correctly.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 16 of 25

Anonymous
Not applicable

Hi Jeremy,

 

Thanks a lot for your reply and suggestion. Here's my feedback on the other workarounds:

 

Workarounds: 

  • In REVIT-31149 by Kelsey Skaug: change the scale in the view template and then change it back; this toggles all the views that use that view template

     Feedback: After having those tags with question marks, I tried to switch between different view scales but the question marks remained(.rvt file attached). See pic below:

Different Scales.jpg 

 

  • Workaround by YarUnderoaker: Copy to clipboard newly created elements followed by paste using PostCommand

     Feedback: PostableCommand.PasteFromClipboard can reveal the right tag text but you need to manually define a new location in the user interface after that command. As I mentioned, I would like to do all of this in background without user interface, so it doesn't actually work for me. See pic below:

PostableCommand.PasteFromClipboard.jpg

 

  • Workaround by Harry Mattison: Put the creation and "tweak" of the tag in separate transactions

     Feedback: I also tried this but it didn't work. Then I found my workaround as stated in the earlier post which actually doesn't need to do the tweaking. But the thing is the view has to be activated(no need to be the current view) otherwise you still got those question marks.

 

I hope these workarounds do work for the other developers in their scenarios but they didn't work in mine. I would be grateful if you or any other developer could have any further suggestion. Thanks a lot.

 

Best,

Leo

 

Message 17 of 25

n_mulconray
Advocate
Advocate

Hi,

What is the latest and greatest of solutions to this problem. I have tried so far the following...

-utils to move translate tag

-doc regen

-turning on tag.leader, freeing end

-turning on crfopbox for view section.

 

 

0 Likes
Message 18 of 25

n_mulconray
Advocate
Advocate

-changing the view template scle did not work in my case.

0 Likes
Message 19 of 25

Illia
Explorer
Explorer

It is the end of 2023 and it is still a problem!

Changing the view template scale worked for us (Revit 2023.1):


in view template we had original scale of 1/50:
- change from 1/50 to 1/25;
- apply;
- change back from 1/25 to 1/50;
- apply.

this restores the material tag data, however this may need to be repeated every time after the project is closed and re-opened. 

Hey Autodesk, this bug has been  around for so long! please don't tell us you don't have resources to fix this being $50B worth!

0 Likes
Message 20 of 25

jeremy_tammik
Alumni
Alumni

Sorry about that. The Building Coder mentioned another, similar, workaround:

  

https://thebuildingcoder.typepad.com/blog/2023/02/pyramid-builder-commandloader-et-al.html#7

  

I'll check for an updated status on this with the development team. 

  

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