I had a pint with a friend last week who keeps extolling the virtues of the Macintosh. One of his big plus points was the multiple desktops offered by the Unix OS.
Multiple desktops are indeed great for the busy multi-tasking programmer, but using a Mac clearly isn't an option for us Revit lot. So I dabbled with a couple of 'virtual desktop' apps for my XP machine and have found VirtuaWin to be pretty cool.
Now I can separate comms, development, support etc. A lot neater!
Thursday, 26 February 2009
Monday, 23 February 2009
Looping through selected elements
Fred emailed and asked about how to iterate through a selection set and make a modification to each element in that set, in particular regarding adding a leader to selected text notes.
The API provides the ElementSetIterator class. I used its method MoveNext in a While loop, and this takes us through each selected element, on which you can then test for type and act accordingly.
I didn't really test the textNote.AddLeader part. Fred reports that it works but the new leader only becomes visible when you move the textnote. Something to look into when I've got a spare five mins :)
The API provides the ElementSetIterator class. I used its method MoveNext in a While loop, and this takes us through each selected element, on which you can then test for type and act accordingly.
Public Sub LoopSelectedElements()
Dim activeDoc As Document = revitApp.ActiveDocument
Dim selectionIterator As Autodesk.Revit.ElementSetIterator
selectionIterator = revitApp.ActiveDocument.Selection.Elements.ForwardIterator
'loop through iterator
While selectionIterator.MoveNext
Dim currElement As Autodesk.Revit.Element = selectionIterator.Current
'see what elements we've found
Debug.Print(currElement.Name.ToString)
'check for type and make mods
If TypeOf currElement Is Autodesk.Revit.Elements.TextNote Then
Dim textNote As Autodesk.Revit.Elements.TextNote = currElement
textNote.AddLeader(Enums.TextNoteLeaderTypes.TNLT_STRAIGHT_R)
End If
End While
End Sub
I didn't really test the textNote.AddLeader part. Fred reports that it works but the new leader only becomes visible when you move the textnote. Something to look into when I've got a spare five mins :)
Friday, 20 February 2009
Simple menu and toolbar in VB
The focus on C# in the Revit SDK code samples can be a hindrance to those of us who prefer VB. Yesterday I had a request from a reader (or is it a viewer? subscriber? follower? what do you call someone that visits your blog?) asking for a sample of VB code that creates a simple menu and toolbar. Well, here's some that should do the trick:
Create a dll from this, and then in your .ini file drop in the following:
[ExternalApplications]
EACount=1
EAClassName1=EdsTools.EdsToolbar
EAAssembly1=C:\Program Files\Revit Architecture 2009\Program\EdsTools.dll
Obviously if you already have some External Applications you need to modify this to suit.
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Autodesk.Revit
Public Class EdsToolbar
Implements Autodesk.Revit.IExternalApplication
Public Function OnShutdown(ByVal application As Autodesk.Revit.ControlledApplication) As Autodesk.Revit.IExternalApplication.Result Implements Autodesk.Revit.IExternalApplication.OnShutdown
Return Autodesk.Revit.IExternalApplication.Result.Succeeded
End Function
Public Function OnStartup(ByVal application As Autodesk.Revit.ControlledApplication) As _
Autodesk.Revit.IExternalApplication.Result Implements Autodesk.Revit.IExternalApplication.OnStartup
Try
'custom tool bar with buttons
Dim toolBar As Autodesk.Revit.Toolbar = application.CreateToolbar()
toolBar.Name = "Ed's Tools"
'image for toolbar, set to nothing by default
Dim imagePath As String = ""
toolBar.Image = imagePath
'menu
Dim menuItem As MenuItem = application.CreateTopMenu("Ed's Tools")
Dim menuItem1 As MenuItem = menuItem.Append(menuItem.MenuType.BasicMenu, "Open Working Directory", "C:\Program Files\Revit Architecture 2009\Program\EdPittOpenWrkDir.dll", "EdPittOpenWrkDir.OpenWD")
'toolbar
Dim item As ToolbarItem = toolBar.AddItem("C:\Program Files\Revit Architecture 2009\Program\OpenWorkingDirectory.dll", "OpenWorkingDirectory.OpenWorkingDirectory")
item.ItemType = ToolbarItem.ToolbarItemType.BtnRText
item.StatusbarTip = "Open Working Directory"
item.ToolTip = "Open Working Directory"
item.ItemText = "Open Working Directory"
Catch ex As Exception
MsgBox("Failed")
Return IExternalApplication.Result.Failed
End Try
Return IExternalApplication.Result.Succeeded
End Function
End Class
Create a dll from this, and then in your .ini file drop in the following:
[ExternalApplications]
EACount=1
EAClassName1=EdsTools.EdsToolbar
EAAssembly1=C:\Program Files\Revit Architecture 2009\Program\EdsTools.dll
Obviously if you already have some External Applications you need to modify this to suit.
Monday, 16 February 2009
Creating a new drafting view
I saw a query on the discussion groups about creating a draft view and setting the title on sheet, so I thought I'd have a stab at it and make a little post-ette on t'blog.
And of course if you want to create other types of view these are the available methods:
Document.NewView3D - Creates a new 3D view.
Document.NewViewDrafting - Creates a new drafting view.
Document.NewViewPlan - Creates a plan view based on the specified level.
Document.NewViewSection - Creates a new section view.
Document.NewViewSheet - Creates a new sheet view.
Dim newView As ViewDrafting = revitApp.ActiveDocument.Create.NewViewDrafting
newView.ViewName = viewName
newView.Scale = viewScale
newView.Parameter("Title on Sheet").Set(sheetName)
And of course if you want to create other types of view these are the available methods:
Document.NewView3D - Creates a new 3D view.
Document.NewViewDrafting - Creates a new drafting view.
Document.NewViewPlan - Creates a plan view based on the specified level.
Document.NewViewSection - Creates a new section view.
Document.NewViewSheet - Creates a new sheet view.
Thursday, 5 February 2009
Calculating building height - again
My last post was an attempt to calculate building height, but I quickly realised after posting (and luckily before being rumbled by some smart alec) that what I was doing was calculating the height at which the uppermost level was placed. Any thing on the uppermost level was being ignored.
So, here's another idea, and it assumes that your building has a roof at the top, which I'm sure in most cases is a fair assumption(?). It uses a category filter to look for roofs and then it queries the Max Z value of the BoundingBox of the roof:
You could of course remove the 'If TypeOf' conditional and replace it with a try catch which would be a cheeky way of looking for the Max.Z in every element that the roof category filter returns, catching those that don't support it, and returning values for those that do. This would then return the Max Z value for all types of roof in your model.
In fact that's given me an idea. How about this, this will scan through every element in your model and return the largest Z value it can find. Is this the height of your building? :
The answer is no, I just tried this last idea on the Revit training sample c_Condo_Complex.rvt and of course it takes a long time to run, but it gave me the value for the 3D view. If you look for all elements, they won't all be part of your building!
So stick with the first idea above. I bet there'll be a comment in soon telling me there's a really easy way to do this, like building.height :)
So, here's another idea, and it assumes that your building has a roof at the top, which I'm sure in most cases is a fair assumption(?). It uses a category filter to look for roofs and then it queries the Max Z value of the BoundingBox of the roof:
Dim element As Autodesk.Revit.Element Dim zValue As String 'active view used later for boundingbox Dim activeView = revitApp.ActiveDocument.ActiveView 'get all elements in the Roof category Dim CatFilter As Autodesk.Revit.Filter CatFilter = revitApp.Create.Filter.NewCategoryFilter(Autodesk.Revit.BuiltInCategory.OST_Roofs) Dim result As New List(Of Autodesk.Revit.Element) Dim NumLevels As String = revitApp.ActiveDocument.Elements(CatFilter, result) For Each element In result 'change this to footprintRoof etc if you wish If TypeOf element Is Elements.ExtrusionRoof Then If element.BoundingBox(activeView).Max.Z > zValue Then zValue = element.BoundingBox(activeView).Max.Z End If WriteOutput(element.BoundingBox(activeView).Max.Z) End If Next
You could of course remove the 'If TypeOf' conditional and replace it with a try catch which would be a cheeky way of looking for the Max.Z in every element that the roof category filter returns, catching those that don't support it, and returning values for those that do. This would then return the Max Z value for all types of roof in your model.
In fact that's given me an idea. How about this, this will scan through every element in your model and return the largest Z value it can find. Is this the height of your building? :
Dim elementIterator As Autodesk.Revit.ElementIterator elementIterator = revitApp.ActiveDocument.Elements Dim topElement As Autodesk.Revit.Element Dim element As Autodesk.Revit.Element Dim zValue As Double zValue = 0 Dim activeView = revitApp.ActiveDocument.ActiveView While (elementIterator.MoveNext()) element = elementIterator.Current Try If element.BoundingBox(activeView).Max.Z > zValue Then zValue = element.BoundingBox(activeView).Max.Z topElement = element End If Catch ex As Exception Debug.Print(Err.Description) End Try End While WriteOutput("The highest Z value is: " & zValue) WriteOutput("The element is: " & topElement.Name) WriteOutput("The element ID is: " & topElement.Id.Value)
The answer is no, I just tried this last idea on the Revit training sample c_Condo_Complex.rvt and of course it takes a long time to run, but it gave me the value for the 3D view. If you look for all elements, they won't all be part of your building!
So stick with the first idea above. I bet there'll be a comment in soon telling me there's a really easy way to do this, like building.height :)
Wednesday, 4 February 2009
Calculating building height
I saw a query on the Revit API discussion groups about how to calculate the height of a building, so I thought I'd have a quick go. Admittedley they wanted it in C#, but I like my VB.
Loop through your elements looking for a level type, and when you find one use the level.ProjectElevation property to get its height - in decimal feet of course. At first I added these up to get total height, but then realised that ProjectElevation returns the elevation of the level relative to the project origin, so all we want is the highest figure we can find of all our levels.
UPDATE: This only retrieves the elevation of the uppermost level, which isn't the height of the building - see my next post for a different approach!
Loop through your elements looking for a level type, and when you find one use the level.ProjectElevation property to get its height - in decimal feet of course. At first I added these up to get total height, but then realised that ProjectElevation returns the elevation of the level relative to the project origin, so all we want is the highest figure we can find of all our levels.
Dim elementIterator As Autodesk.Revit.ElementIterator elementIterator = revitApp.ActiveDocument.Elements Dim height As Double While (elementIterator.MoveNext()) 'look for level types If TypeOf elementIterator.Current Is Autodesk.Revit.Elements.Level Then Dim level As Elements.Level = elementIterator.Current 'is current value higher than previous values? If level.ProjectElevation > height Then height = level.ProjectElevation End If End If End While MessageBox.Show("Height: " & height)
UPDATE: This only retrieves the elevation of the uppermost level, which isn't the height of the building - see my next post for a different approach!
Subscribe to:
Posts (Atom)