Move tags

Move tags

Anonymous
Not applicable
3,195 Views
8 Replies
Message 1 of 9

Move tags

Anonymous
Not applicable

I'm new to C# and need some help on how to interperate the language in order to get this function to work properly. I've highlighted the parts of code that I need help with in red.

 

public void MoveFixtureTags()
        {
            int sc = ActiveUIDocument.ActiveView.Scale;
            object fxtr = null;
            IList<Reference> refs = null;
            Selection sel = ActiveUIDocument.Selection;
            refs = sel.PickObjects(ObjectType.Element, new selFilter(), "Select Electrical fixture tags");
            foreach (Object tag in refs)
            {
                //Get the family object that the tag is referencing and it's rotation angle
                fxtr = tag.Get the fixture that the tag is associated with?

                //Move the tag over a set distance based on that 'fxtr' angle.
                pt0 = tag.Location point?
                pt1 = offset(pt0, fxtr.angle, (sc * 0.125))?
                tag.move(pt0, pt1)?
            }
        }

0 Likes
Accepted solutions (1)
3,196 Views
8 Replies
Replies (8)
Message 2 of 9

Anonymous
Not applicable

I think in this case you are after tags of the class IndependantTag once you have them you get the tags host using:

 

Element host = document.GetElement(tag.TaggedLocalElementId);

 

To Move the tag, in this case 1 foot in the X direction and 1 foot in the Y direction use the element transform utilities:

 

XYZ translation = new XYZ(1, 1, 0);
ElementTransformUtils.MoveElement(document, tag.Id, translation);

 

Hope that Helps,

 

Brett

0 Likes
Message 3 of 9

Anonymous
Not applicable

I can't seem to get this to work. I'm using the Revit macro editor and not the Visual Studio app. I've attached the references and macro. Also below them are the 3 errors I get when I try to build the program. (I right click to show help on the erros but it returns no content found)

using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;

        public void MoveFixtureTags()
        {
            //Reference refs = null;
            //refs = sel.PickObject(ObjectType.Element, "Select Electrical fixture tags");
            int sc = ActiveUIDocument.ActiveView.Scale;
            IList<Reference> refs = null;
            Selection sel = ActiveUIDocument.Selection;
            refs = sel.PickObjects(ObjectType.Element, new selFilter(), "Select Electrical fixture tags");
            foreach (IndependentTag tag in refs)
            {
                //Get the family object that the tag is referencing and it's rotation angle
                Element host = Document.GetElement(tag.TaggedLocalElementId);
                //Move the tag over a set distance based on that angle.
                XYZ translation = new XYZ(1, 1, 0);
                ElementTransformUtils.MoveElement(Document, tag.Id, translation);
               
            }
        }

Cannot convert type 'Autodesk.Revit.DB.Reference' to 'Autodesk.Revit.DB.IndependentTag' (CS0030) - C:\ProgramData\Autodesk\Revit\Macros\2014\Revit\AppHookup\UserTools\Source\UserTools\ThisApplication.cs:57,4

An object reference is required for the non-static field, method, or property 'Autodesk.Revit.DB.Document.GetElement(Autodesk.Revit.DB.ElementId)' (CS0120) - C:\ProgramData\Autodesk\Revit\Macros\2014\Revit\AppHookup\UserTools\Source\UserTools\ThisApplication.cs:60,20

'Autodesk.Revit.DB.Document' is a 'type' but is used like a 'variable' (CS0118) - C:\ProgramData\Autodesk\Revit\Macros\2014\Revit\AppHookup\UserTools\Source\UserTools\ThisApplication.cs:63,39

0 Likes
Message 4 of 9

Anonymous
Not applicable

The first two errors occur because the pick object method returns a list of references. To get independantTags you need to use the reference elementId and the getElement method, to get an element, which you can then cast to an independant tag:

 

IndependentTag tag = document.GetElement(ref.ElementId) as IndependentTag;

 The last error is because you don't have a document object. To get the document try this:

 

Document doc = this.ActiveUIDocument.Document;

 

Also because we are making changes to the document database all this needs to be done inside of a transaction.

 

Here is my complete code:

using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;

public void MoveTags()
{
    Document doc= this.ActiveUIDocument.Document;
    UIDocument uidoc= new UIDocument(document);

	IList<Reference> selection = uidoc.Selection.PickObjects(ObjectType.Element, "Select tags to move");

	using (Transaction rvtTransaction = new Transaction(doc)) {
		rvtTransaction.Start("Move Tag");

		foreach (Reference ref in selection) {
			IndependentTag tag = doc.GetElement(ref.ElementId) as IndependentTag;
XYZ translation = new XYZ(1, 1, 0); ElementTransformUtils.MoveElement(doc, tag.Id, translation); } rvtTransaction.Commit(); } return Result.Succeeded; }

 

I haven't added a selection filter when picking the objects, so i suspect if the user picks something other than an independant tag, an error will occur.

 

 

Brett.

 

 

0 Likes
Message 5 of 9

Anonymous
Not applicable

Thanks Brett. It looks like I needed to change a few things to get it to work in the Revit macro editor. (for some reason an error occured on return succedded.) I need to figure out how to get the rotation of 'host'  for example when I do if I find that host is rotated 45 degrees then the tag moves 45 degrees It looks like it has something to do with gettting the 'host' x and y point, then offsetting from that point a set distance 45 degrees. Don't know how to do that. (too bad this isn't AutoLISP. The learning curve for c# seems to be very steep.)

 

 

        public void MoveTags()
{
    Document doc= this.ActiveUIDocument.Document;
    UIDocument uidoc= new UIDocument(doc);
    int sc = ActiveUIDocument.ActiveView.Scale;
    IList<Reference> selection = uidoc.Selection.PickObjects(ObjectType.Element, new selFilter(), "Select tags to move");

    using (Transaction rvtTransaction = new Transaction(doc))
    {
        rvtTransaction.Start("Move Tag");

        foreach (Reference ckt in selection)
        {
            IndependentTag tag = doc.GetElement(ckt.ElementId) as IndependentTag;
            Element host = doc.GetElement(tag.TaggedLocalElementId);

            hx = host x point? hy = host y point?

            hx = offset(hx, host rotation, sc * 0.125) 

            hy = offset(hy host rotation, sc * 0.125)
            XYZ translation = new XYZ(hx, hy0);
            ElementTransformUtils.MoveElement(doc, tag.Id, translation);
        }

        rvtTransaction.Commit();
    }


    //return Result.Succeeded;
}

0 Likes
Message 6 of 9

Anonymous
Not applicable
Accepted solution

Appolgies for the errors, I normally write in visual studio using VB so i tried my best to convert for you.

 

we are getting there. Smiley Happy

 

so you have the host element, to get its insertion point and rotation you can use the location property, however I don't think you actually need the insertion point. In this case we want to move the tag a given distance, not from a point to a point.

 

To calculate the translation i would break it into X, Y, Z components and use abit of trig.

 

here is my code:

 

//get the host rotation
LocationPoint hostLocation = host.Location as LocationPoint;
double hostRotation = hostLocation.Rotation;

//calcualte translation components
double distanceToMove = viewScale * 0.125;
double x = distanceToMove * Math.Cos(hostRotation);
double y = distanceToMove * Math.Sin(hostRotation);
double z = 0;

//setup translation
XYZ translation = new XYZ(x, y, z);

//move tag
ElementTransformUtils.MoveElement(document, tag.Id, translation);

 

 

Brett

 

Message 7 of 9

Anonymous
Not applicable

Brett,

 

 Your help with this has been outstanding. thank you so much for taking the time to work with me on this.

 

After running the program I realized that I needed to add 90 degrees to the angle, (family at zero degrees is actually pointed 90 degrees) as well as remebering Revit deals with feet. So of course the tags were being moved over 20 feet and not 20 inches.

 

 Everything works for this.

 

A couple of minor questions I have though. The importance of answering these are not important as I already got the program to work.

 

1. When selecting items separatly, nothing gets hightlighted even though it is selected. Need some sort of highlight mode?

 

2. Is there some sort of C# Revit function for "Tag all not tagged" that can be used to tag the fixtures and then I can use that  as a selection to run this program?

 

Anyway here is the complete code that I got to work:

 

        public void MoveFixtureTags()
        {
            Document doc= this.ActiveUIDocument.Document;
            int sc = ActiveUIDocument.ActiveView.Scale;
            IList<Reference> refs = null;
            Selection sel = ActiveUIDocument.Selection;
            refs = sel.PickObjects(ObjectType.Element, new selFilter(), "Select Electrical fixture tags");
            using (Transaction rvtTransaction = new Transaction(doc))
            {
                rvtTransaction.Start("Move Tag");
                foreach (Reference ckt in refs)
                {
                    //Get the family object that the tag is referencing
                    IndependentTag tag = doc.GetElement(ckt.ElementId) as IndependentTag;
                    Element host = doc.GetElement(tag.TaggedLocalElementId);

                    //get the host rotation
                    LocationPoint hostLocation = host.Location as LocationPoint;
                    double hostRotation = hostLocation.Rotation + Math.PI/2//+90 degrees
                
                    //calcualte translation components
                    double distanceToMove = sc / 57.6//move 20 inches for 1/8" scale, 10 for 1/4", etc.
                    double x = distanceToMove * Math.Cos(hostRotation);
                    double y = distanceToMove * Math.Sin(hostRotation);
                    double z = 0;
                
                    //move tag set distance
                    XYZ translation = new XYZ(x, y, z);
                       ElementTransformUtils.MoveElement(doc, tag.Id, translation);
                }

                rvtTransaction.Commit();
               }
            
            
        }
        
        /// Filter to constrain picking to model groups. Only model groups
        /// are highlighted and can be selected when cursor is hovering.
        class selFilter : ISelectionFilter
        {
              public bool AllowElement (Element e)
              {
                  if (e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_ElectricalFixtureTags) return true;
                  //if (e.Category.Id.IntegerValue == (int)BuiltInCategory.OST_ElectricalFixtures) return true;
                  return false;
              }
              
              public bool AllowReference(Reference r, XYZ p)
              {
                    return false;
             }
        }

0 Likes
Message 8 of 9

Anonymous
Not applicable

No problem. Was a good little challange to get you started.

 

To Answer your questions,

 

1. Revit Selection tools aren't as good as what you are used to AutoCAD. As far as I know you can't highlight objects during PickObjects.

 

2. As far as i know there is no tag all method. Would be fairly easy to create, select what you want to tag, iterate over each element, get its location, place the tag at that location. Sounds like your next project, start a new discussion thread Smiley Wink

 

 

Brett

0 Likes
Message 9 of 9

Anonymous
Not applicable

Brett,

 

I've noticed after running this program that if the tag is already moved it moves it again further. How can I move it to the host location point first and then move it a set distance?

 

//get the host rotation
                    LocationPoint hostLocation = host.Location as LocationPoint;
                    double hostRotation = hostLocation.Rotation + Math.PI/2//+90 degrees
                    
                    //calcualte translation components
                    double distanceToMove = sc / 48//move 24 inches for 1/8" scale, 12 for 1/4", etc.
                    double x = distanceToMove * Math.Cos(hostRotation);
                    double y = distanceToMove * Math.Sin(hostRotation);
                    double z = 0;
                
                    //move tag set distance

******I want to move the tag to the hostLocation point first.*****
                    XYZ translation = new XYZ(x, y, z);
                       ElementTransformUtils.MoveElement(doc, tag.Id, translation);

0 Likes