Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.

Revit API Forum

Reply
Highlighted
Post 1 of 5

Retrive In-Place Mass Reference Level

121 Views, 4 Replies
02-22-2016 08:24 AM

Hi everyone.
I'm working with in place masses to make functional diagrams in which each mass represents a room.
But to do this I need to get 2 parameters that we can't retrieve from in place Masses by default. Floor Area and Reference Plane.
To do this I'm creating an updater that works in two steps:
1- gets the floor area applying a floor for each mass at the right level.
2- Set the level name to a new shared Parameter in the document.
The problems are:
1- First time I edit a mass it gives me an error message, but if I copy and paste one element it works properly.
2- I can't set information to any parameter.

 

Here by the code, sorry if it is not clean, I'm just starting with programming.

 

 

    public Result OnStartup(Autodesk.Revit.UI.UIControlledApplication application)
    {
        // Register wall updater with Revit
        MassUpdater updater = new MassUpdater(application.ActiveAddInId);
        UpdaterRegistry.RegisterUpdater(updater);

        // Change Scope = any Part element
        ElementCategoryFilter filterMass = new ElementCategoryFilter(BuiltInCategory.OST_Mass);

        // Add Trigger
        UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), filterMass, Element.GetChangeTypeElementAddition());
        UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), filterMass, Element.GetChangeTypeGeometry());
        return Result.Succeeded;
    }

    public Result OnShutdown(Autodesk.Revit.UI.UIControlledApplication application)
    {
        MassUpdater updater = new MassUpdater(application.ActiveAddInId);
        UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
        return Result.Succeeded;
    }
}

public class MassUpdater : IUpdater
{
    static AddInId m_appId;
    static UpdaterId m_updaterId;


    // constructor takes the AddInId for the add-in associated with this updater
    public MassUpdater(AddInId id)
    {
        m_appId = id;
        m_updaterId = new UpdaterId(m_appId, new Guid("C40D8B95-7897-4ED4-A57F-EC53FDC1DFCB"));
    }

    public void Execute(UpdaterData data)
    {
        Document doc = data.GetDocument();
        // Get level ID
        FilteredElementCollector lvlCollector = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels);
        ElementId lvlId = null;
        string lvlName = "";
        List<ElementId> listElId = new List<ElementId>();

        //Get Masses in model
        FilteredElementCollector docCollector = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Mass);

        //Filter selection by type Name
        foreach (Element massPieces in docCollector)
        {
            ElementId typeId = massPieces.GetTypeId();
            Element type = doc.GetElement(typeId);
            string typeName = type.Name;
            if (typeName == "Room")
            {
                foreach (Element el in docCollector)
                {
                    listElId.Add(el.Id);
                }
                //Select only valid Masses ( I don't Know why but for each mass in place revit gives me 2 ID here I select only the even Elements
                var evenCategories = listElId.Where((c, i) => i % 2 != 0);
                List<ElementId> filter = new List<ElementId>(evenCategories);

                foreach (ElementId mass in filter)
                {
                    //Get Mass Position
                    Element piece = doc.GetElement(mass);
                    Parameter PPlevel = piece.LookupParameter("LEVEL");
                    BoundingBoxXYZ bounding = piece.get_BoundingBox(null);
                    XYZ point = bounding.Min;
                    double elLvl = point.Z;

                    foreach (Element l in lvlCollector)
                    {
                        Level lvl = l as Level;
                        MassInstanceUtils.RemoveMassLevelDataFromMassInstance(doc, mass, lvl.Id);
                        if (lvl.Elevation == elLvl)
                        {
                            lvlId = lvl.Id;
                            lvlName = lvl.Name;
                            MassInstanceUtils.AddMassLevelDataToMassInstance(doc, mass, lvlId);
                            string name = lvlName.ToString();
                            PPlevel.Set(name);
                        }
                    }
                }
            }
        }
    }

    public string GetAdditionalInformation()
    {
        return "Mass area updater example: updates all Masses' area";
    }

    public ChangePriority GetChangePriority()
    {
        return ChangePriority.Masses;
    }

    public UpdaterId GetUpdaterId()
    {
        return m_updaterId;
    }

    public string GetUpdaterName()
    {
        return "Mass Area Updater";
    }

 

 

Post 2 of 5

Re: Retrive In-Place Mass Reference Level

02-23-2016 01:11 AM in reply to: a.ferreira

Dear A.ferreira,

 

Thank you for your query.

 

My main advice to you would be:

 

If you are "just starting with programming", as you say, leave your hands away from the Dynamic Model Updater framework completely to start with.

 

Do some other, simpler things first and gather more experience with programming and the Revit API.

 

The next step is something I addressed in my last blog post:

 

How to Debug a Complex Issue

 

http://thebuildingcoder.typepad.com/blog/2016/02/happy-monkey-year-how-to-ask-a-question-and-debug.h...

 

In this case, you are describing multiple steps.

 

Some of them fail sometimes.

 

Remove the DMU stuff and separate the steps into individual pieces.

 

Continue cleaning them up until they all work all of the time.

 

Once you have that set up, try putting them together again piece by piece.

 

I hope this helps.

 

Best regards,

 

Jeremy



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

Post 3 of 5

Re: Retrive In-Place Mass Reference Level

02-23-2016 02:38 AM in reply to: jeremytammik

OK, thank you and sorry if I wasn't clear.

I'll rephrase my question:


I'm applying a floor to mass base level in order to retrieve it Area. Then I'm trying to set the levels' name in a shared parameter on file.
first part works just fine, but the line param.Set(lvlName) just does nothing.

 

Can you identify the problem?

 

// Get doc levels IDs
        
FilteredElementCollector lvlCollector = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels);
       
//Get Masses in model
        
FilteredElementCollector docCollector = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Mass);
       
	if (docCollector != null)
        
	{             
	    //Get all only masses from type Pieces (those are in-place masses)
            
		foreach (Element massPieces in docCollector)
            	{
                	ElementId typeId = massPieces.GetTypeId();
                	Element type = doc.GetElement(typeId);
               	 	string typeName = type.Name;
                	if (typeName == "Piéce")
                	{
                        	//Get Mass Position
                        	Element piece = doc.GetElement(mass);
                        
                       		BoundingBoxXYZ bounding = piece.get_BoundingBox(null);
                       		XYZ point = bounding.Min;
                        	double elLvl = point.Z;
                        	
                       	//Aplly floor to mass
			foreach (Element l in lvlCollector)
                        {
                            Level lvl = l as Level;
                            MassInstanceUtils.RemoveMassLevelDataFromMassInstance(doc, mass, lvl.Id);//first need to remove the precend floors in order to have only base floor
                            
			    if (lvl.Elevation == elLvl) // gets the base floor by comparing it z cordinate
                            {
                                ElementId lvlId = lvl.Id;
                                MassInstanceUtils.AddMassLevelDataToMassInstance(doc, mass, lvlId);
                                lvlName = lvl.Name;
                            }
                        }
                       
			Parameter param= piece.LookupParameter("NIVEAU"); //new shared parameter
                        param.Set(lvlName); //and here is my problem
			}
		}
	}

 

Post 4 of 5

Re: Retrive In-Place Mass Reference Level

02-23-2016 03:21 AM in reply to: a.ferreira

Dear A.ferreira,

 

Thank you for your update and super important clarification.

 

Oh dear.

 

Well, in that case, I am afraid you have a problem.

 

So does this thread of yours. You say 'retrive level'. That should be 'retrieve level', I assume.

 

The problem is that it is really about setting the level.

 

That was already discussed here in some depth in the past:

 

http://forums.autodesk.com/t5/revit-api/associate-element-to-level/m-p/5784286

 

Unfortunately, for many Revit elements, the level property is read-only and cannot be set at all after creation.

 

We have a wish list item CF-3268 [API wish: set level of element] to provide access to modify element level properties. Please make a note of this number for future reference.

 

I have added your wish to this issue to underline its importance.

 

The good thing about the way we handled this discussion is that it proves how effective the 'divide and conquer' approach is that I pointed out in my discussion on How to Debug a Complex Issue:

 

http://thebuildingcoder.typepad.com/blog/2016/02/happy-monkey-year-how-to-ask-a-question-and-debug.h...

 

Sorry about the bad news!

 

I would suggest exploring an alternative workflow that does not require you to set the level on the existing instances.

 

I hope this helps.

 

Best regards,

 

Jeremy



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

Post 5 of 5

Re: Retrive In-Place Mass Reference Level

11-08-2016 02:23 AM in reply to: jeremytammik

Did you ever have any luck with this? I am running into a similar problem. 

 

thanks

Ken

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post

Revit Exchange Apps

Created by the community for the community, Autodesk Exchange Apps for Revit helps you achieve greater speed, accuracy, and automation from concept to manufacturing.