tag:blogger.com,1999:blog-233824082024-03-17T23:03:34.546-04:00CAD Application DevelopmentDiscussions on CAD, and developing software that works with CAD, PLM, et al... Mostly around the Autodesk Product line, but I'm up for anything.Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.comBlogger100125tag:blogger.com,1999:blog-23382408.post-85665673133508491262019-09-24T19:10:00.000-04:002019-09-24T19:10:05.293-04:00A quick note for Vault API developer posterity: PromoteComponentLinksSo - I haven't posted on this blog in forever, but it seems like the best place for this.<br />
<br />
Unless you're some kind of regular reader from the mid-2000s and I'm still in your feed - I'm guessing that you found me by googling something like:<br />
<br />
<b>How the @#$#%#% do I get Autodesk Vault Items to update their secondary links to files with the Vault API!?!??!</b><br />
<br />
After struggling with this for a while, I figured I would share my knowledge gained so that you don't have to bang your head on the table as long as I did.<br />
<br />
Here's the trick:<br />
You need to call a method called ItemService.PromoteComponentLinks.<br />
<br />
Here's the code:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> wsm.ItemService.UpdatePromoteComponents(new long[] { item.RevId }, ItemAssignAll.Default, false);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> DateTime timestamp;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> GetPromoteOrderResults promoteOrder =</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wsm.ItemService.GetPromoteComponentOrder(out timestamp);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if (promoteOrder.PrimaryArray != null && (promoteOrder.PrimaryArray.Length>0))</span><br />
<span style="font-family: Courier New, Courier, monospace;">{</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wsm.ItemService.PromoteComponents(timestamp, promoteOrder.PrimaryArray);</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if (promoteOrder.NonPrimaryArray != null && (promoteOrder.NonPrimaryArray.Length>0))</span><br />
<span style="font-family: Courier New, Courier, monospace;">{</span><br />
<span style="font-family: Courier New, Courier, monospace;"> <span style="background-color: yellow;">wsm.ItemService.PromoteComponentLinks( promoteOrder.NonPrimaryArray);</span></span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> ItemsAndFiles itemsAndFiles =</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wsm.ItemService.GetPromoteComponentsResults(timestamp);</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">newItem = itemsAndFiles.ItemRevArray[0];</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wsm.ItemService.UpdateAndCommitItems(new Item[] { newItem });</span><br />
<br />
<br />
How did I figure it out? I broke down and turned on Fiddler to watch the traffic between my Vault Explorer and the server. It's actually a pretty nice hack - thank you to whomever on the Autodesk side added what the currently running command was to the URL query.<br />
<br />
Anyway - I'm hopeful that your googling finds the above results, instead of various articles and support forum posts from Doug and Wayne from the beginning of this decade :).<br />
<br /><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-65623301861822830622017-06-21T17:51:00.000-04:002017-06-21T17:51:26.439-04:00Everybody Lies....One of the ongoing themes of the show "<a href="https://en.wikipedia.org/wiki/House_(TV_series)" target="_blank">House</a>" (a medical drama from a few years back, starring Hugh Laurie as a modern medical Sherlock Holmes) - is that "<a href="https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwjhluHm8s_UAhVFcT4KHZk0DDoQtwIIKjAB&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DCZR2k5c_198&usg=AFQjCNGklgX8KJYGUTpmjFLKyVObW0GqfQ&sig2=4JAKcEYf0hT08qBsLzhs_A" target="_blank">Everybody Lies</a>". This credo is applied generally to patients, some of whom lie deliberately, and some of whom lie incidentally. In either case, these lies present obstacles and sometimes trainwrecks in the way of getting to the truth...<br />
<br />
I've recently run into a couple of examples of this with the Revit API. If you've discovered this page, maybe you're searching and this will help you too.<br />
<br />
We've got an addin that's fairly old - goes back to the 2008 or 2009 era of Revit. The app scans all of the elements in the model and attempts to categorize them and process them. We started encountering customer models that could not be processed because what looked like duplicate element IDs. Surely Revit would not allow for multiple element IDs to share the same number, right? Seems fundamental!<br />
<br />
After digging for a while in two different support cases, we found issues where when you interrogate elements about their ID or their Category, they lie!<br />
<br />
For reasons lost to history, there are several places in the old code where instead of accessing the Id via "Element.Id" or the category via "Element.Category", the code instead used parameters:<br />
<br />
Parameter idParam = elem.get_Parameter( BuiltInParameter.ID_PARAM);<br />
Parameter catParam = elem.get_Parameter( BuiltInParameter.ELEM_CATEGORY_ID );<br />
<br />
When we started digging into looking at each grouping of a category of elements to be processed, we would see things in the array of elements where some of the elements were "concrete types" like Pipes or Ceilings - but half of the elements to process were just abstract "Element" type objects.<br />
<br />
Whatever these "Element" type objects are in the Revit Database, they seem to be related to the "actual" element in question. When you delete the actual element, they go away as well. But when you ask them for their ID or Category, they respond back with their friend's category. And if you ask them their Id, they respond with their friend's Id.<br />
<br />
So - maybe you'll never run into this issue. Certainly if we had been using the more traditional way of retrieving Categories and IDs, we wouldn't have.<br />
<br />
But it's probably worth knowing that this is out here, and that Revit is tricky, and you can't always trust an element not to lie. ;)<br />
<br /><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-41960222581073767452016-08-14T12:45:00.000-04:002016-08-14T12:46:18.149-04:00The future minefield of DirectShape Elements.When Autodesk released the DirectShape API a few years back - I thought it was fantastic. Finally a way to be able to create arbitrary geometry that could live on within Revit - rather than only the elements that the API let us create in the ways that the API let us create them.<br />
<br />
We used this to interesting effect in our own Scan to BIM product - <a href="https://www.youtube.com/watch?v=v6vnlsdJstw&list=PLGzJTXx9gbj_6009uaZV_ofTUzSZuKdWY&index=1" target="_blank">providing a mechanism to capture irregular shapes as Revit geometry</a>. What's also interesting - beyond the creation of geometry, the API allows you to assign these objects to be just about any category you want. Think about that for a moment - you can make any arbitrary piece of geometry, and declare that it is a wall, room, stairs, etc.<br />
This felt incredibly cool but also incredibly dangerous to me, from a BIM perspective. And while assigning some characteristics of a wall come from assigning the wall category - it's not an actual wall element, and there are a lot of limitations there.<br />
<br />
<b>This Week</b><br />
This week I experienced for the first time the down side of this approach. A customer was using one of our other tools on one of their models, and it was throwing a weird exception in our app. We were looking through the logs, and based on what we were seeing, it seemed like a model corruption issue. We had a method which retrieved all of the phases that had rooms assigned to that phase - and one of the rooms apparently had a phase which was not actually a phase in this model. How could this happen? maybe corruption? maybe some kind of issue with the cut-and-paste between models?<br />
<br />
We started working on a workaround from that angle - but a day later, the customer was able to share the model with us. When we actually ran it via the debugger, we saw which room the phase was associated with: -1 (nothing). This hadn't seemed possible in our experience. Then we looked closer - the element in question was not actually a Room - it was a DirectShape element. How the heck did that get in there?!?<br />
<br />
The real problem in the code, which we had written stuff like this a thousand times over the past 6 or 7 years (since the FilteredElementCollector was invented), looked something like this:<br />
<br />
FilteredElementCollector coll = new FilteredElementCollector( myDoc );<br />
IList<element> elements = coll.OfCategory( BuiltInCategory.OST_Rooms ).ToElements();</element><br />
<br />
Historically, if all you wanted was the elements that were rooms, this was all that you needed.<br />
That said - some API developer had created an addin that made a DirectShape box and assigned it to the Room category.<br />
<br />
So - going forward, we as API developers can no longer rely on the category (or even Category/IsElementNotElementType) as reliable indicators of the .NET type in the Revit API.<br />
<br />
Our quick fix for this particular issue was:<br />
<br />
IList<element> elements = </element><br />
coll.OfCategory( BuiltInCategory.OST_Rooms ).OfClass( typeof(SpatialElement) ).ToList();<br />
<br />
This would ignore any DirectShape elements that were showing up as rooms. We quickly found other places (in other methods) where we had made the bad assumption, and had casting errors like:<br />
<br />
IList<room> rooms = </room><br />
coll.OfCategory( BuiltInCategory.OST_Rooms).Cast<room>().ToList();</room><br />
<br />
The DirectShape elements failed the Cast at runtime.<br />
<br />
Even when fixed, these issues are bound to get confusing. I believe in many cases the DirectShape elements may still schedule as their assigned category, so our customers will believe they have N rooms in the model, when in fact only some of them are "real" rooms.<br />
<br />
I'm still wrapping my head around it, but I think ultimately you'll just always have to have an "OfClass(typeof(MyDesiredClass))" on the collector. If you don't, you're liable to get things you don't expect.<br />
<br />
All-in-all, it's not too bad to address it, if you know about it. The key is that it's a loophole that other developers can open, and all of us who make software where you don't know what other addins have been used will have to make sure that we're double-careful about our assumptions. And I'm not looking forward to digging back through all the code I've ever written and am still supporting to find all of the bad assumptions I made.<br />
<br />
<br />
<br /><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-66593773693541201332016-05-19T17:49:00.000-04:002016-05-19T17:49:21.964-04:00Autodesk Vault API 2017: 32-bit/64-bit challenges....For end-users of Autodesk Vault - it's probably a welcome development that Autodesk Vault 2017 now supports a 64-bit version (and a 32-bit version if you're still running on a 32-bit OS).<br />
<br />
Less so - however, for Vault developers, whose lives may get more complicated. The explanations in documentation and social media have been somewhat lacking (<b>Where are you Doug Redmond? The citizens of Vault API land need you!</b>).<br />
<br />
Here's what I've managed to piece together so far:<br />
<br />
<b>The SDK</b><br />
You'll see that the SDK ships with two subfolders of the "bin" folder - "x86" and "x64". The bulk of the DLLs inside of both folders are technically "ANYCPU (64-bit preferred)" - with the exception of the new Clic License Manager loader DLL, which seems to be platform-specific. (The Clic thing is something else that could use a bit more explaining than we've been given).<br />
<br />
<b>The Vault Explorer Environment</b><br />
If you're doing Extensions within Vault Explorer, it's pretty straightforward: If you install on a 64-bit machine, you get the 64-bit versions. The documentation says that you'll have to make sure your DLLs match the bit-ness of Vault Explorer... But I believe that it IS possible to use ANYCPU for your explorer customization DLLs (they should match the Vault Explorer automatically, and all of the referenced DLLs are ANYCPU). So that's not really bad at all (unless you've got 32-bit-specific dependencies in your project - and then you're in for a longer day, even after you've got things worked out... Separate DLLs, separate installers, etc).<br />
<br />
<b>Vault Job Processor</b><br />
Seems to be the same as the Explorer issues above.<br />
<br />
<b>Standalone Vault Applications</b><br />
This is the one that really had me puzzled for a little while. I was naively thinking that I could leave my standalone Vault apps as 32-bit (even on a 64-bit machine). That might work in some cases, but if you've used any of the higher level pieces of the framework (VDF, etc) - then you're out of luck. Those pieces of the framework will attempt to load any Vault Extensions that you have loaded on the current machine - and seem to cause problems if ANY of the Vault Extensions don't match the bit-ness of your standalone app.<br />
<br />
So - if you're doing standalone apps for sale, or other cases where you can't guarantee the bit-ness of the operating system, then you may need to do two versions of the apps... One 32-bit and one 64-bit.<br />
<br />
<br />
All in all, this stuff just kind of snuck up on me - I don't recall hearing about it back at Developer Days - so it's been a more complicated upgrade process than I anticipated.<br />
<br />
Good luck out there...<br />
<br /><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-42588289575912225382012-05-31T12:05:00.002-04:002012-05-31T12:05:18.135-04:00Which way am I looking?One of the somewhat obscure but interesting features that I had been looking forward to in the Revit 2013 API, I finally got a chance to use recently when updating our <a href="http://imaginit.com/software-solutions/building-architecture/scan-to-bim" target="_blank">Scan To BIM for Revit</a> application.<br />
<br />
That is - you can finally look at the ViewRange settings for a particular plan view. Now, there are <a href="https://www.google.com/search?q=Revit+View+Range&rls=com.microsoft:en-us&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1#hl=en&rls=com.microsoft:en-us&sclient=psy-ab&q=Revit+%22View+Range%22&oq=Revit+%22View+Range%22&aq=f&aqi=g4&aql=&gs_l=serp.3..0l4.6120.7056.0.7392.2.2.0.0.0.0.99.181.2.2.0...0.0.mytch-lCzBA&pbx=1&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&fp=3beae772ccad557c&biw=1057&bih=582" target="_blank">a thousand posts</a> out there about how View Range works, and I think you can also ask a hundred Revit users and get at least 30 different answers. The truth is, there are a LOT of complications to it.<br />
<br />
From the API persective, there are 5 kinds of PlaneViewPlanes:<br />
<br />
<ul>
<li>Top Clip Plane</li>
<li>Cut Plane</li>
<li>Bottom Clip Plane</li>
<li>View Depth Plane</li>
<li>Underlay Bottom Plane</li>
</ul>
<div>
Finding out the ViewRange is pretty easy:</div>
<div>
<br /></div>
<pre><div>
PlanViewRange range = myPlanView.GetViewRange();</div>
<div>
// for a given plane, find the associated level and offset</div>
<div>
ElementId cutLevelId = range.GetLevelId( PlanViewPlane.CutPlane );</div>
<div>
double cutLevelOffset = range.GetOffset( PlanViewPlane.CutPlane );</div>
<div>
</div>
</pre>
<div>
Of course, you can set the view range data as well.</div>
<div>
<br /></div>
<h2>
The Real Reason For My Post: View Direction</h2>
<div>
This is all well and good, but now we come to the REAL reason for my post. As happens so often within the Revit API, you think you can see the way to get from point A to point B and accomplish your mission. And then you are blindsided by some strange Revit complexity that you might have heard about, but had not dealt with before.</div>
<div>
<br /></div>
<div>
The fundamental problem I was trying to solve was to identify what parts of a point cloud were visible in the Plan View. Much of this you can determine from the the PlanViewRange, shown above. But it soon became clear that there was a bit more to it than that. As you may know, Plan Views may face upwards or downwards within Revit. That is to say - a FloorPlan is always "looking down" at the floor - but a Reflected Ceiling Plan or Mechanical Plan is always "looking up" at the ceiling. Apparently structural views could not be decided, so you can actually edit the setting on the view type to be up or down for a model.</div>
<div>
<br /></div>
<div>
I had originally guessed that the ViewDirection property would be a different vector to represent the direction that you're looking ... but that's not the case. So - if you have to know the direction, how do you find it?</div>
<div>
<br /></div>
<div>
It hinges upon the ViewFamilyType (this concept existed as an Element in 2012, but has a fully exposed class in 2013 - so you wouldn't have been stuck in 2012). Views all derive from a ViewFamilyType. Inside the ViewFamilyType, there is a hidden BuiltInParameter (it's only a visible parameter on the aforementioned Structural ViewType). </div>
<div>
<br /></div>
<div>
<pre><div>
// determine the view direction</div>
<div>
ElementId vftId = vp.GetTypeId();</div>
<div>
Element vft = vp.Document.GetElement(vftId);</div>
<div>
if (vft == null) throw new ArgumentException("Unable to find view family type for view: " + vp.Name);</div>
<div>
</div>
<div>
Parameter viewDirParam = vft.get_Parameter(BuiltInParameter.PLAN_VIEW_VIEW_DIR);</div>
</pre>
</div>
<div>
<br /></div>
<div>
So once you have that, you're all set - the parameter tells you, for your view, whether you're looking up or down.</div>
<div>
<br /></div>
<div>
It's obscure, but as always, I hope you stumble upon this when it's useful to you!</div>
<br />
<br /><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-76427484706802541682011-06-28T15:28:00.010-04:002011-06-29T10:44:29.571-04:00Point Cloud Fix in Revit 2012 Web Update 1<div><div><div><div><div>One of the biggest problems that people have had with the new Point Cloud capabilities of Revit 2012 is how it dealt with multiple point clouds inserted into your Revit project.</div><div> </div><div>If you had multiple scans that all were from the same origin, and you inserted them all origin-to-origin, then they would all line up, right? wrong...Some of the problem related to how Revit handled large coordinate values (as you may know, Revit doesn't like it when elements start showing up miles from the model origin). If you inserted a PCG file which was indexed from something where the coordinates were in state-plane (which is not all that uncommon) - Revit would basically reset the coordinates and insert it center-to-center. And then how are you going to insert the next one so that it is consistent?</div><div> </div><div>The answer was supposed to be the third insert option: Auto - Origin to Last Placed (meaning that it would make sure that the origin matched the origin of the previous model). But it didn't work :).<br /></div><div> <a href="http://3.bp.blogspot.com/-cqLCYb15qWg/TgovUEhiXxI/AAAAAAAAAKY/rHGg0ak4bFk/s1600/AlignmentIssue3WebUpdate1.PNG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="width: 320px; height: 232px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5623359106583781138" border="0" alt="" src="http://3.bp.blogspot.com/-cqLCYb15qWg/TgovUEhiXxI/AAAAAAAAAKY/rHGg0ak4bFk/s320/AlignmentIssue3WebUpdate1.PNG" /></a></div><br /><div>So what's new in 2012 Web Update 1? It works!</div><div> </div><div>Before:</div><div> </div></div><br /><a href="http://3.bp.blogspot.com/-niMmhJOFFmg/TgowcP4CcdI/AAAAAAAAAKg/PsAhr4a2Dsk/s1600/AlignmentIssueWebUpdate1.PNG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="width: 304px; height: 320px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5623360346581529042" border="0" alt="" src="http://3.bp.blogspot.com/-niMmhJOFFmg/TgowcP4CcdI/AAAAAAAAAKg/PsAhr4a2Dsk/s320/AlignmentIssueWebUpdate1.PNG" /></a><br /><div>After:</div><div> </div><div> </div></div></div><br /><a href="http://1.bp.blogspot.com/-Ugiueun7FVw/Tgow9YMPHhI/AAAAAAAAAK4/0Ypg4NuFvMo/s1600/AlignmentIssue2WebUpdate1.PNG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="width: 290px; height: 320px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5623360915749412370" border="0" alt="" src="http://1.bp.blogspot.com/-Ugiueun7FVw/Tgow9YMPHhI/AAAAAAAAAK4/0Ypg4NuFvMo/s320/AlignmentIssue2WebUpdate1.PNG" /></a><br /><br /><div>While no one likes to see bugs like this, it's nice to see decent turnaround on it. I had been worried it was going to involve having to re-index all of the PCG files - that would have been bad.</div></div><div><br /></div><div><div><em>[Editor's Note: Jason Seck just pointed out to me... you might still be annoyed that they haven't addressed the "first cloud" issue... Your first large coordinate cloud is still going to come in Center-to-Center. All they have fixed is the "relative placement" of clouds issues. I think it will be a while before the "first cloud" issue is fixed, because to do that they would need to fix the "two-miles-from-the-origin issue", and that seems like a big one.]</em></div></div><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com2tag:blogger.com,1999:blog-23382408.post-77758332963887100852011-05-28T21:20:00.004-04:002011-05-28T21:37:26.095-04:00An oddity with Drafting View mirroringSo I was asked if it was possible to mirror a drafting view using the API (apparently the built-in project mirroring doesn't cover drafting views).<br /><br />It seemed straightforward enough... so I wrote a quick test... and it didn't work...<br />- it worked fine in a floor plan view<br />- it didn't work in a drafting view<br />- the code completed just fine - it just didn't really seem to show any difference.<br /><br />My initial code is below...<br />- Get all the elements in the current view<br />- Use the new ElementTransformUtil class to figure out which could be mirrored, and mirror them.<br /><br /><br /><pre><br />FilteredElementCollector coll =<br />new FilteredElementCollector(uiDoc.Document, uiDoc.ActiveView.Id);<br /><br />IList<element> elems = coll.ToElements();<br /><br />// make sure that stuff can be mirrored<br />List<elementid> toMirror = new List<elementid>();<br /><br />foreach (Element elem in elems)<br />{<br />if (ElementTransformUtils.CanMirrorElement(uiDoc.Document, elem.Id) == false) continue;<br />toMirror.Add(elem.Id);<br />}<br /><br /></pre><br /><br />So why did this complete successfully, but not show any difference?<br />The answer is one of those great undocumented elements in the wilds of the Revit database. When I looked in the debugger at what I was actually attempting to mirror, I saw this:<br /><a href="http://2.bp.blogspot.com/-K_bvQRzLmrM/TeGhY1F_rtI/AAAAAAAAAKM/n1LkpyEOkXw/s1600/ExtentElement.jpg"><img style="MARGIN: 0px 10px 10px 0px; WIDTH: 400px; HEIGHT: 309px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5611944058621505234" border="0" alt="" src="http://2.bp.blogspot.com/-K_bvQRzLmrM/TeGhY1F_rtI/AAAAAAAAAKM/n1LkpyEOkXw/s400/ExtentElement.jpg" /></a><br /><br /><br /><br /><p>What I see here is a mystery element called "ExtentElem" which is being copied. I have a sneaking suspicion that it might be telling the view the actual extent of what is in it... So how can we exclude it? well - it has no actual category (which is probably a sign that in general we don't want to mirror an element like that!).</p><br /><p>So - we add a line like:<br /><pre>if (elem.Category == null) continue;</pre><br />and voila! we have our drafting view being mirrored.<br /><br /><br /><br /><p>I wish that I could say that all Revit database mysteries are "easily" solvable like this - there's plenty of times where you just run into a wall, and can't get to what you want... but today's story has a happy ending!</p><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com6tag:blogger.com,1999:blog-23382408.post-6049460954986479872011-05-16T16:15:00.004-04:002011-05-16T16:30:42.537-04:00DWFplus for Revit 2012Well, it has been forever since I've last posted... I missed the release of the 2012 API and a variety of other announcements. But I'm trying to get back on the horse.<br /><br />To that end - a quick video to show what I think is a cool new feature of our Utilities for Revit 2012 product - a new utility called "DWFplus".<br /><br />If you've ever looked at distributing a DWF file, and figuring that Revit ought to be making it chock-full of all my BIM data... you may have been slightly disappointed. The rules for when Revit published a parameter or didn't were arcane - and I'm still not sure if we've accurately reverse engineered them. And certain features like hyperlinks... how is it that AutoCAD can have hyperlinks but not Revit!<br /><br />So DWFplus is an attempt to change that. It starts with a regular DWF export, but adds in a variety of neat stuff:<br /><br /><ul><br /><li>All parameters (or selected parameters) that you want to publish</li><br /><li>Parameters are attached to Tags - not just the elements</li><br /><li>Includes 2D Hyperlinks for any URL parameters (even multiples)</li><br /><li>Parameters are published in 3D as well as 2D.</li><br /><li>Includes some neat 3d viewpoints for 3D DWF views.</li></ul><br /><p>Here's a little video to demonstrate:</p><br /><p><br /><iframe width="425" height="349" src="http://www.youtube.com/embed/CeJfrMBRhUc" frameborder="0" allowfullscreen></iframe><br /></p><br /><br /><p> Note: IMAGINiT Utilities for Revit is available <a href="http://imaginit.com/software-solutions/building-architecture/imaginit-utilities-for-revit">here</a>, and is free for clients that keep their Revit subscription with IMAGINiT.<div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com3tag:blogger.com,1999:blog-23382408.post-84996715629718399482010-04-22T01:02:00.001-04:002010-04-22T01:02:32.888-04:00Revit API 2011: Revit AddIn Manager – Almost Edit & Continue<p><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">(part of our ongoing series)</a> <br />If you’ve been developing for Revit for a while – you groaned significantly when, in Revit 2010, changes were made to Revit that disabled the “Edit-and-Continue” capability within a Revit add-in. That is to say – if you wanted to make a minor code change while Revit was debugging – you had to close Revit (wait for Revit to be totally closed), perform the change, then restart Revit, re-load your model, and then try to get back to the same location. Argh – seems like 2+ minutes down the drain any time this happens.</p> <p>Enter the “Revit AddIn Manager” – part of the Software Development Kit. This tool has been around since 2009, I think – it historically provided handy mechanism for a developer to test External commands or applications – even when they forgot to add them to the REVIT.INI file. It could both update the INI file for you, or even just launch the command in session.</p> <p><a href="http://lh6.ggpht.com/_dHu6uapG2Tg/S8_YYmfAtuI/AAAAAAAAAJQ/XMPKCbV2hYQ/s1600-h/image%5B5%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_dHu6uapG2Tg/S8_YZOzEdTI/AAAAAAAAAJU/A2GeJYOICCs/image_thumb%5B1%5D.png?imgmax=800" width="244" height="232" /></a> </p> <p><strong>What’s Different in 2011?</strong></p> <p>I suspect due to some conversations and <a href="http://thebuildingcoder.typepad.com/blog/2010/03/dynamically-load-and-debug-plugins.html">posts that were had on Jeremy Tammik’s blog</a> late in the development process, the AddIn Manager has been notably improved – such that while you can’t support edit-and-continue, you can now support updating your code while Revit is running, and just re-running your command inside of Revit.</p> <p>How does this work? The Addin utility is doing some lifting behind the scenes, including copying the DLL and related files to a temporary folder, and loading the .NET assembly DLL from that location.</p> <p>What does this mean for us? That when we start up Revit with the debugger attached, we can run the AddInManager. From the AddInManager we can launch our command in a way that loads it into memory before starting the debug process.</p> <p>While we <em>still </em>cannot edit and continue, we CAN open a second copy of Visual Studio, and make changes by rebuilding the project.</p> <p>- it allows us to overwrite the project, because the running project was copied to somewhere else.</p> <p>- we are now able to just re-start the AddIn Manager in order to start our updated version of the command.</p> <p><strong>The Features of the AddIn Manager</strong></p> <p>The behind-the-scenes mechanics are described above. It also has (obviously) been enhanced to support the new “.addin file” mechanism rather than the Revit.INI mechanism of registering addins. The command also supports some additional options which can be a little confusing at first. The list of AddIn Manager commands looks like this:</p> <p><a href="http://lh4.ggpht.com/_dHu6uapG2Tg/S8_YZcdnG9I/AAAAAAAAAJY/kuuoegu9pfU/s1600-h/image%5B2%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_dHu6uapG2Tg/S8_YZ0KEiqI/AAAAAAAAAJc/1ciKQnkz2Pc/image_thumb.png?imgmax=800" width="239" height="187" /></a> </p> <p>What’s the deal with all this manual, automatic and faceless?</p> <p>The Manual vs. Automatic entries refer to the new <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-upgrading-existing-add.html">TransactionMode and RegenerationMode</a> that must be assiged to each command. Because the AddIn Manager is going to invoke your AddIn, it would be a problem if AddInManager specified Automatic mode but your code specified manual mode. So you have to pick automatic or manual based on what YOUR command is defined as. NOTE: No mix/match on transaction and regeneration mode… you have to be either Auto/Auto or Manual/Manual. The application will stop you if you pick the wrong one (although the error message leaves something to be desired).</p> <p>Faceless, while the mechanism seems a little clumsy – is a nice little feature. Fundamentally – it remembers the last command that you executed, and will just execute that again (no user interface, it just does it – that way you don’t need to re-browse, re-select, and re-run the command in question).</p> <p><strong>Conclusion</strong></p> <p>If you occasionally work with API developers – get a copy of the AddIn Manager to make it easier to test and setup API AddIns! If you’re a developer, there are now many good reasons to set up the AddIn Manager. So get to it! It’s in the Revit SDK installation folder.</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-9816230290251092122010-04-22T00:16:00.001-04:002010-04-22T00:16:37.629-04:00Revit 2011 API: What’s New in Element Creation<p><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">(part of our ongoing series)</a> <br />Each new version, I go through what is new in the specific API area of element creation. Every CAD API has some logical divisions, from information retrieval, to element creation, to interactivity – and you can tell from how strong each area is what the factory’s focus is in the API.</p> <p>Revit’s start in this area was weak – the API was more about finding elements and updating parameters than actually creating new elements and geometry. In recent releases, Revit really played catch up – I believe it now supports 101 different element creation methods.</p> <p>So what’s new in 2011 in this area: in short, not much… This was not an area of focus in 2011, so there’s only a few new things in this specific area:</p> <ol> <li>NewTruss() – now available in architecture</li> <li>NewRebarType()</li> <li>NewRebarHookType()</li> <li>NewRebarCoverType()</li> <li>FaceWall.Create()</li> </ol> <p>The last one is of the greatest interest to me personally. This enables you to create a wall based on a face (typically a face that is on a mass element). This is an advanced technique used in Revit to create complex wall shapes.</p> <p>Two other items deserve honorable mention here as well:</p> <ul> <li>UIDocument.PromptForFamilyInstancePlacement() – while not technically a “Element Creation” capability, it opens up some significant doors to more interactive design applications within Revit – by letting the end-user help the developer place the family instance visually.</li> <li>SolidSolidCutUtils – A new utility class to help with doing solid-to-solid cuts in the modeling environment. This is typically used either for GenericForm kind of family solids or family instances.</li> </ul> <p>All in all, while this category doesn’t seem like it got much attention in 2011, the fact is that with 101 element types that can be created, it has attained a certain level of maturity. For example, if I scan the Home ribbon in 2011 – it is possible to create almost everything that is available on that toolbar (I think the exceptions are: Ceiling, Model Group (you can’t create a new one), Railing, Ramp, Stairs. That’s really not too bad – and the remaining ones are a little on the obscure/complex side.</p> <p>So let me hear from you by comments? Are you <em>really </em>waiting for one of the missing elements that can’t be created? or are you just reluctant to do API work with geometry creation until it supports 100%? How many different kinds of elements are YOU creating in your app?</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com8tag:blogger.com,1999:blog-23382408.post-61252806635230693762010-04-17T11:47:00.001-04:002010-04-17T11:47:05.204-04:00Revit 2011 API Series: RevitLookup: The New Name for RvtMgdDbg<p><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">(part of our ongoing series)</a> <br />Since the beginning of Revit development time – in the 8.0/8.1 range, the best way to learn about what is possible with the Revit API was to use a “Snoop Tool” – something that could interrogate all of the elements in the model and all of their properties.</p> <p>In the beginning, there was RevitDbg – a tool by Fenton Webb at Autodesk. It used reflection to browse through a massive tree structure of all the elements in the model. It was slow, but cool.</p> <p>Later, Jim Awe of Autodesk brought his Snoop tool (called “RvtMgdDbg”) from AutoCAD to Revit – bringing not just browsing of elements but also event testing as well as some test commands. This became the tool that most Revit developers cut their teeth on. That said – I’m still amazed at the number of developers who have tried to learn the API without the benefit of RvtMgdDbg… I have to imagine it’s like developing in the dark! </p> <p>For all of its importance to Revit developers, RvtMgdDbg was always somewhat of a step-child at Autodesk… No one really owned it (so it was nice that they provided the source – at least 3 times over the past few years I had to upgrade it myself to support the latest version before someone at Autodesk took care of it). It was also unclear over time how it was going to be distributed – was it only for ADN members? Did you have to attend a particular AU session? Or did you just have to know the right people? Thankfully, in the past year or so Autodesk has caught on to how important RvtMgdDbg is to getting developers up-to-speed and has made it available to anyone, usually via <a href="http://thebuildingcoder.typepad.com/">Jeremy Tammik’s blog</a>.</p> <p>Which brings us to 2011… While not revolutionary – it is an important evolution for RvtMgdDbg. It has been adopted by the Revit API team – which means that there are resources devoted to updating it and providing it along with the SDK – under a new, more accessible name: RevitLookup. Kevin Vandecar as well as some of the Shanghai developers have done yeoman’s work in upgrading it (it is a grueling task – I know because I had to do it myself at least twice during the 2011 alpha/beta cycle).</p> <p>RevitLookup can be found in the SDK folder under RevitLookup – it appears that you’ll have to build it yourself (binaries were not shipped) – but it’s great to see that this tool getting its proper due from Autodesk. </p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com1tag:blogger.com,1999:blog-23382408.post-16830697184769378312010-04-08T07:52:00.001-04:002010-04-08T08:48:36.155-04:00Revit 2011 API: SDK Posted (a while ago)<p>We’re all still waiting anxiously for the official Revit 2011 product to become available… They set the expectation for today – but it’s not there yet! and it’s 7:58 AM! What’s the deal? :)</p> <p>That said – I noticed last night that the final Revit 2011 SDK is available as a standalone download on the ADN page (posted back on 4/1 – and I didn’t notice).</p> <p>In other news, I hope to get back onto posting the rest of my 2011 articles – I’m just temporarily buried in project work.</p> <p>[Editor: And I can see that I have to go back and add to a few previously written articles. I can see at least 15 enhancements in the new SDK that were added late enough in the process that I was unaware of them! Woo-hoo, more toys!]</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-61665641068368708662010-03-28T11:48:00.001-04:002010-03-29T09:13:17.081-04:00Revit API 2011: The New Way to Find Elements<p>(Part of our <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">Revit API 2011 Series</a>) <br />[Editor’s Note: Updated with some late-breaking additions that will only be documented in the released documentation] <br /> <br />For the uninitiated, much of the core work in a Revit application involves finding elements within the Revit database. Whether it’s finding exterior walls, 3D Views, or wall types – it’s always the same concept… Doing a lookup from the Revit to get a list of elements.</p> <p>This is an area that “the factory” has improved upon release-after-release… From the early days, where you always had to cycle through everything – through the newest incarnation, today. I think I’m counting right that this is the 4th generation of the element iteration API. And no more ignoring what’s new – because you’re <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-upgrading-existing-add.html">required</a> to use the new method in 2011!</p> <h3>The 2011 Approach</h3> <p>The factory has really created something great here – something that is mature and answers almost anything you could want in an element iteration API. And they’ve really tried to do it in a way that matched the best and most modern approaches in .NET – such as LINQ.</p> <p>The fundamental concept for iteration is the <strong><em>FilteredElementCollector </em></strong>class.</p> <h3>Getting Started</h3> <p>You construct the class in one of three ways:</p> <table border="1" cellspacing="0" cellpadding="2" width="453"><tbody> <tr> <td valign="top" width="451">// get ready to filter across an entire document <br />FilteredElementCollector coll = <br />     new FilteredElementCollector( myDoc );</td> </tr> </tbody></table> <p>or</p> <table border="1" cellspacing="0" cellpadding="2" width="456"><tbody> <tr> <td valign="top" width="454">// get ready to filter across just my pre-selected set of <br />// elements! <br />FilteredElementCollector coll = <br />     new FilteredElementCollector( myDoc, myElementCollection );</td> </tr> </tbody></table> <p>This is great when you’d rather not search your entire model when you’ve already got the subset you want…</p> <p>or</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">// get ready to filter across just the elements visible in a view <br />FilteredElementCollector coll = <br />    new FilteredElementCollector( myDoc, viewId );</td> </tr> </tbody></table> <p>This is equivalent to the old mechanism of the View.Elements collection – which is now gone.</p> <p>These constructors just get you started… Then it’s time to move on to the filtering.</p> <h3>Filtering Mechanisms with FilteredElementCollection</h3> <p>The factory has introduced three different categories of filtering in 2011:</p> <ul> <li>Logical (operations like AND/OR) </li> <li>Quick (operations that are FAST) </li> <li>Slow (operations that take a bit longer) </li> </ul> <p>While these kinds of things have probably conceptually always existed, but they were found out by experimentation rather than Autodesk documenting and sharing them up front…</p> <ul> <li>Quick <ul> <li>ElementCategoryFilter / OfCategoryId() </li> <li>ElementTypeFilter / OfType() </li> <li>ElementIsElementTypeFilter / <br />    WhereElementIsElementType() <br />    WhereElementIsNotElementType() </li> <li>ElementOwnerViewFilter / OwnedByView(), WhereElementIsViewIndependent() </li> <li>ElementDesignOptionFilter / ContainedInDesignOption() </li> <li>ElementIsCurveDriven / WhereElementIsCurveDriven() </li> <li>ElementStructuralTypeFilter </li> <li>BoundingBoxContainsPointFilter</li> <li>BoundingBoxIntersectsFilter</li> <li>BoundingBoxIsInsideFilter</li> <li>ExclusionFilter</li> <li>FamilySymbolFilter</li> </ul> </li> <li>Slow <ul> <li>ElementParameterFilter </li> <li>ElementLevelFilter</li> <li>FamilyInstanceFilter</li> <li>FamilyStructuralMaterialTypeFilter</li> <li>PrimaryDesignOptionMemberFilter</li> <li>StructuralInstanceUsageFilter</li> <li>StructuralMaterialTypeFilter</li> <li>StructuralWallUsageFilter</li> <li>CurveElementFilter</li> <li>RoomFilter </li> <li>SpaceFilter </li> <li>AreaFilter </li> <li>RoomTagFilter </li> <li>SpaceTagFilter </li> <li>AreaTagFilter </li> </ul> </li> </ul> <p>These are documented further in the API help file in its own introductory section called “Element Iteration API”.</p> <p>I’ll give some of the typical situations here:</p> <p>If you know the type:</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">// we want walls <br />coll.OfClass( typeof(Wall) );</td> </tr> </tbody></table> <p>or if you know the category:</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">// we want Curtain Wall Panels: <br />coll.OfCategoryId( BuiltInCategory.OST_CurtainWallPanels );</td> </tr> </tbody></table> <p>Now here’s where it starts to get interesting… If you want to put different filters together, it can look something like this:</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">// We want door instances <br />coll.OfCategoryId( BuiltInCategory.OST_Doors ).OfClass( typeof(FamilyInstance));</td> </tr> </tbody></table> <p>What’s going on here? each filter ADDs requirements to the collector. And to make the whole thing more friendly towards combining, the methods return a pointer to their object, so that you can “chain” them together. For example, the code above would be equivalent to:</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">// we want door instances <br />coll.OfCategoryId( BuiltInCategory.OST_Doors); <br />coll.OfClass( typeof(FamilyInstance) );</td> </tr> </tbody></table> <p>We are updating our collector two times with the filter requirements.</p> <h3>The ElementType Topic</h3> <p>The ElementType / NotElementType can be a little confusing at first… There are two filters, the short-hand versions are:</p> <ul> <li>WhereElementIsElementType() </li> <li>WhereElementIsNotElementType() </li> </ul> <p>What is <u>ElementType</u>? This is the renamed <em>Symbol</em> class in the API (re-named to match better what interactive users call things). So an “ElementType” refers to a symbol/type/definition kind of thing (a “block definition” for you AutoCAD-types). Something which is “Not an ElementType”, on the other hand – is typically something which is physically IN the model – like a specific door, line, or wall. Technically it’s a bit more broad – because it also includes items like views, etc.</p> <p>That said – these two can be key filters to use to distinguish between whether you want Doors vs. Door Types, for example.</p> <h3>What’s the Deal with Rooms/Areas/Spaces/Tags?</h3> <p>Here’s a place where Autodesk’s new strategy of matching up more closely with the internal API will cause you a little bit of hassle. With Rooms/Areas/Spaces and their tags (as well as about 9 other types – see the API Introduction for the list) – there is no internal Revit type which matches them.</p> <p>For example, if you look at the Room class in the 2011 API, you’ll see that it is actually a descendant of the Enclosure Class. Enclosure covers Rooms, Spaces, and Areas… Here’s the trick – Revit’s internals are obviously modeled on the “Enclosure” class – so if you’re querying by type – you can’t query on <br />typeof( Room ), for example.</p> <p>There are some specially designed filters to compensate for this – like RoomFilter, AreaFilter, SpaceFilter, etc… These would be called as follows:</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">coll.WherePasses( new RoomFilter() );</td> </tr> </tbody></table> <p></p> <p>The WherePasses method is another mechanism for specifying filters – you can use any filter with it.</p> <h3>Final Requirements of the Filter</h3> <p>Ok, ok – we’re almost to the payoff… But one thing I should note before we go on… If you’re used to being able to just query the whole model (for whatever reason) – you’ll find that a little bit tricky with this mechanism… Why? Because the rule is that after you construct the collector – you MUST apply at least one filter before you attempt to retrieve from it. You can’t (easily) just retrieve everything.</p> <p>The closest I’ve come to it is:</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">// get EVERYTHING – like in the bad-old-days… <br />// get all the ElementTypes + all the non-ElementTypes <br />coll.WhereElementIsElementType().UnionWith( new <br />         ElementIsElementTypeFilter( false ) );</td> </tr> </tbody></table> <h3> <br />Finally – Retrieving from the Filter</h3> <p>Sorry to make you go through all this to get to the good part! Once you have constructed your collector and applied filter(s), then it’s time to request the contents of the collector and see what you get. Autodesk has really done a nice job of implementing some .NET 3.5 goodies here, so there are a variety of options.</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="225">coll.ToElements();</td> <td valign="top" width="225">Return an IList<Element> of the contents.</td> </tr> <tr> <td valign="top" width="225">coll.ToElementIds();</td> <td valign="top" width="225">Return an ICollection<ElementId> of the contents.</td> </tr> <tr> <td valign="top" width="225">coll.FirstElement()</td> <td valign="top" width="225">Return the first Element found that matches.</td> </tr> </tbody></table> <p>But that’s only the first part – the other thing I love is that the .NET 3.5 tricks that get around another annoyance – that these query routines return pointers to “Element” – which you immediately have to convert/cast down into, say “Room” to be able to easily access the properties and methods of that class.</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450">// get all the wall types as wall type objects: <br />coll.OfClass (typeof(WallType)); <br />IEnumerable<WallType> types = coll.Cast<WallType>(); <br /> <br />foreach (WallType wt in types ) <br />{ <br />    // do something with the wall type <br />}</td> </tr> </tbody></table> <h3> </h3> <h3>Using with LINQ</h3> <p>Because the FilteredElementCollector supports the IEnumerable interface – it easily  can make the jump to LINQ – being able to write full-fledged queries directly in code.</p> <p>This looks something like:</p> <table border="1" cellspacing="0" cellpadding="2" width="450"><tbody> <tr> <td valign="top" width="450"> <p>FilteredElementCollector coll = new FilteredElementCollector(doc); <br />coll.OfClass(typeof(WallType)); </p> <p>var bigEnoughWallTypes = <br />from element in coll <br />where element.get_Parameter(BuiltInParameter.WALL_ATTR_WIDTH_PARAM).AsDouble() > 0.5 && <br />   element.get_Parameter(BuiltInParameter.FUNCTION_PARAM).AsInteger() == 1 <br />                         select element; </p> <p>IEnumerable<WallType> types = bigEnoughWallTypes.Cast<WallType>();</p> </td> </tr> </tbody></table> <p>ok, so the thin screen doesn’t lend itself to this… In any case – it’s not magic, it’s nothing you couldn’t have done before – but it DOES make your code a bit tighter and arguably easier to maintain because it’s clear what you’re doing (as opposed to doing the same thing in a query then loops with if statements).</p> <h3>The Final Analysis</h3> <p>In the final analysis – the new FilteredElementCollector is a fantastic new way of accessing data within Revit. It does take a little bit of adjustment, but once you’re there, I’d say it’s nicer than what existed before – and it has nice room to grow.</p> <p>I still need to run the new things through a performance test (my impression is that they run faster than their 2010 equivalents – but I haven’t put a stopwatch to it yet). This post is already too long – so I’ll save that for another post…</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com2tag:blogger.com,1999:blog-23382408.post-79353339068361212782010-03-26T16:20:00.001-04:002010-03-27T17:02:56.649-04:00Revit API 2011: Upgrading Existing Add-Ins<p>(Part of our <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">Revit API 2011 Series</a>) <br />If there is a dark side to all of the positive changes in the 2011 API – it is that the amount of re-work required for existing add-ins is <strong><em>FAR</em></strong> more than previous upgrades. I’m tired just writing this post…</p> <p>While previous upgrades have been fairly painless, in 2011 you’re up against:</p> <ul> <li>Massive namespace renaming/restructuring. </li> <li>Deprecation and replacement of many of the fundamental element search and iteration APIs. </li> <li>Fundamentally new transaction and regeneration mechanisms </li> <li>Non-trivial changes to the fundamental XYZ, UV and ElementId class </li> <li>Changes to the Element.ObjectType structure. </li> <li>Replacement of the Analytical Model classes </li> <li>New Event Model </li> <li>New Selection Mechanisms </li> <li>Ribbon API changes </li> <li>Print API changes </li> <li>Re-work of the gbXML class </li> <li>Installer changes (if you want to take advantage of new capabilities) </li> </ul> <h3>Massive Namespace Restructuring</h3> <p>The factory has taken this opportunity to completely re-work the namespace hierarchy into something which more closely matches Revit’s internals – as well as to clean house, straighten up, and simplify some things.</p> <p>While I would argues that this is probably a good thing in the long term, it will require a bit of work to recompile your code.</p> <p>While I won’t cover the namespaces in detail here, to give you an idea of what you’re looking at:</p> <ul> <li>Autodesk <ul> <li>Autodesk.Revit <ul> <ul> <ul> <li>Autodesk.Revit.UI (where all the User Interface and command/application integration classes landed) </li> <li>Autodesk.Revit.DB   (this is the container for most core elements, geometry, parameters, and other concepts) <ul> <ul> <li>Autodesk.Revit.DB.Architecture ( contains architecture-specific elements like Rooms, RoomTags, Gutter, Fascia, etc) </li> <li>Autodesk.Revit.DB.Electrical (contains electrical-related elements and concepts, from CableTray to DemandFactor) </li> <li>Autodesk.Revit.DB.Events (contains the event arguments for all the different kinds of events) </li> <li>Autodesk.Revit.DB.Mechanical (Spaces, Zones, SpaceTags, Ductwork, etc) </li> <li>Autodesk.Revit.DB.Plumbing ( Piping, PipingSystems, etc) </li> <li>Autodesk.Revit.DB.Structure ( Analytical Model, Loads, Rebar, Trusses, etc) </li> </ul> </ul> </li> </ul> </ul> </ul> </li> </ul> </li> </ul> <p>Other key re-naming issues:</p> <ul> <li>the Symbol class has been re-named to “ElementType” </li> <li>the old Geometry.Element class has been renamed to GeometryElement </li> <li>the old Geometry.Instance class has been renamed to GeometryInstance </li> <li>These are further described in the “What’s New” section of the API Help File </li> </ul> <p>Autodesk is also providing in the SDK a spreadsheet of all of the class renames, and their corresponding new names. It is a long list :).</p> <h3>Where Did My ElementIterator Go?</h3> <p>Autodesk has taken somewhat of an unusual step in 2011 – that of ripping and replacing all of the three different element search and iteration schemes from before 2011 and replacing them with the new FilteredElementCollector. The Document.Elements collection, the Document.get_Elements( type ) and the filter mechanism have all been removed.</p> <p>See our separate post on the new mechanism (which is quite superior) – but it may take a minute or two to re-work any of your code which iterates through elements in the document (which almost every command does at least once).</p> <p>Also note – the View.Elements collection has also been re-worked to the new scheme.</p> <h3>The New Transaction Mechanisms</h3> <p>There are fundamentally new transaction mechanisms that you will likely need to deal with (unless your application was very straightforward). Commands are now attributed with one of two Transaction modes:</p> <ul> <li>Automatic – like what has existed historically. </li> <li>Manual – the developer must control their own transactions explicitly. </li> </ul> <p>For upgrading an existing application, you’ll probably want to stay with Automatic because it most closely matches the prior release behavior. However, if you had been using transactions within your code in the past (i.e. Document.BeginTransaction) you must replace these with the new “SubTransaction” classes.</p> <table border="1" cellspacing="0" cellpadding="2" width="400"><tbody> <tr> <td valign="top" width="398">//New SubTransaction approach <br /> <br />SubTransaction subTr = new SubTransaction( myDoc ); <br />try <br />{ <br />    subTr.Start(); <br />   // do something <br />    subTr.Commit() <br />} <br />catch (Exception ex) <br />{ <br />    TaskDialog.Show(“Error”, “An unexpected error was encountered: “ + ex.GetType().Name + “: “ + ex.Message); <br />    if (subTr.HasStarted()) subTr.Rollback(); <br />} <br /></td> </tr> </tbody></table> <p><strong>Developer TechTip:</strong> <br />If you go the manual transaction approach, don’t forget to name your transaction. This name shows up in the “Undo” box, but because there is a constructor which does not require a name, it’s easy to forget. And Revit throws a nasty exception at you if you forget to name it.</p> <h3>The New Regeneration Mechanism</h3> <p>All commands in Revit are now attributed with another attribute: RegenerationMode:</p> <ul> <li>Automatic – same way Revit has worked traditionally – after every action in Revit, the model is regenerated (unless you’re using SuspendUpdate). Solid, but slow on occasion. Also – Autodesk has indicated that <em>this mode is going away in the future.</em> </li> <li>Manual – you are in complete control of your own regeneration (powerful and fast but occasionally painful). </li> </ul> <p>With manual regeneration, you issue a Document.Regenerate any time that you want the project to regenerate. Seems easy enough, right? Well… First you have to understand when you NEED to regenerate. There are a variety of cases, particularly when you are creating or modifying geometry, that the changes will not be propagated until you do the regenerate. For example, if you create a line, you are unable to query for the reference to that line until the document has been regenerated.</p> <p>Why it can be challenging: If you’ve got library code that you re-use in multiple commands. Are you currently in Manual Regeneration mode or not? it depends on how you entered the current command. If you call Document.Regenerate and you’re already in Automatic mode, Revit will throw an exception (seems like a harmless problem – factory guys, chill out!). To further complicate things, if your code is being called as part of an event callback, I believe that it is ALWAYS going to be in Automatic Transaction mode (even if the whole thing is in the context of a manual transaction command). So there’s some potential trickiness to deal with.</p> <h3>XYZ, UV and ElementId - All Change to be Unchangeable!</h3> <p>OK – this is just cruel… I’d swear that this is the third change to the XYZ class in three releases! And it’s worse than previous issues. In 2011, you can no longer do the following code:</p> <table border="1" cellspacing="0" cellpadding="2" width="400"><tbody> <tr> <td valign="top" width="400">myPoint.X = 10;</td> </tr> </tbody></table> <p>What?? why not? Well, Autodesk has made the XYZ, UV, and ElementId classes immutable – they cannot be changed once they are created. There’s a reasonable reason behind this from a framework design perspective – because it implies that you could do something that you really couldn’t. For example, if you did:</p> <table border="1" cellspacing="0" cellpadding="2" width="400"><tbody> <tr> <td valign="top" width="400">myWall.Location.Point.X = myWall.Location.Point.X + 1;</td> </tr> </tbody></table> <p>What would this do? You would think that it might move the wall 1 foot in the X direction. In fact, it does not. The Point here was a COPY of the actual data – so changing the X value did nothing.</p> <p>To do what you wanted to do above, you had to:</p> <table border="1" cellspacing="0" cellpadding="2" width="400"><tbody> <tr> <td valign="top" width="400">XYZ newPt = new XYZ( myWall.Location.Point.X + 1, <br />                               myWall.Location.Point.Y,  <br />                               myWall.Location.Point.Z); <br />myWall.Location.Point = newPt;</td> </tr> </tbody></table> <p>In the case of the new immutable XYZ class, the only way to modify an XYZ, or UV, or ElementId is to construct a new version. So to modify an XYZ point, you must:</p> <table border="1" cellspacing="0" cellpadding="2" width="400"><tbody> <tr> <td valign="top" width="400">myPoint = new XYZ( myPoint.X +1, myPoint.Y, myPoint.Z);</td> </tr> </tbody></table> <p>If you did much with XYZ coordinates in the past, this likely means a bunch of grumbling, painful code re-writing and re-testing.</p> <p>Oh – and ElementId? they changed the name of the actual Id property to “IntegerValue”. They’re not as bad as the Autodesk Vault team with the seemingly meaningless renames, but I definitely have had cause to grumble here.</p> <h3>Changes to the Element.ObjectType mechanism</h3> <p>Prior to 2011, if you wanted to interrogate the type of a given element, you navigated via the Element.ObjectType mechanism and voila, you were at the type element.</p> <p>In 2011, this mechanism has been deprecated. In its place, you actually have to call a couple of methods to do the same thing:</p> <p>Element.GetTypeId()   - which returns an ElementId, not an element. You’ll still have to call Document.get_Element() to get the element object.</p> <p>Correspondingly – whereas you could previously just modify the element type through the property, you now much do Element.ChangeTypeId().</p> <p>Further, if you used to use “Element.SimilarObjectTypes” to browse the corresponding other types that could be swapped to – you’ll now have to call Element.GetValidTypes().</p> <h3>Replacement of the Analytical Model classes </h3> <p>I have to say I’m relatively unfamiliar with AnalyticalModels – but suffice it to say it’s all been ripped out and replaced with something better! Unfortunately, you’ll have to re-work any existing usages.</p> <h3>Deprecated Events</h3> <p>If you were lazy last time – and didn’t remove your 2009-era events like Application.OnDocumentSaved, OnDocumentSavedAs, OnDocumentOpened, OnDocumentClosed, OnDocumentNewed, OnDialogBox, Document.OnSaveAs, OnSave, OnClose…</p> <p>Then you’ve got some work to do – because they’ve all been removed now. They’ve all been replaced with newer and better events, though.</p> <h3>New Selection Mechanisms </h3> <p>The existing selection mechanisms (PickOne/Window Select). Find out all about the new mechanisms <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-ooh-ooh-pick-me.html">here.</a></p> <h3>Ribbon API changes </h3> <p>The ribbon API has had some non-trivial changes… if you’ve done a ribbon panel, it will require updates. See more <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-user-interface.html">here</a>.</p> <h3>Print API changes </h3> <p>The PrintSetup.CurrentPrintSetting has been changed to a new interface: IPrintSetting. This should make things better going forward, but again – it will make for a little bit of cleanup time.</p> <h3>Re-work of the gbXML class </h3> <p>If you were previously getting at the gbXMLelement class, there’s some work required to get at its replacement – the EnergyDataSettings class. While it does inherit from Element, it’s been my experience so far that it is not retrievable in the same ways as in the past – it is not a parameter within the ProjectInformation class. Also, it is not queryable in the same ways as before.</p> <p>To retrieve it in 2011, you need to actually call a static methods:</p> <p>EnergyDataSettings.GetFromDocument(myDoc) <br /> <br />Also note the other static method: EnergyDataSettings.IsDocumentUsingEnergyDataAnalyticalModel(myDoc) – which tells you if there is an analytical model as well.</p> <p> </p> <h3>Installer Changes</h3> <p>While only a minimal installer change is necessary for 2011 (if you still like the bad-old-way of looking through registry uninstall keys to find which versions of Revit are installed and where) – you should probably think about going further. <br /> <br />While the Revit.INI file approach still works – the AddIn file mechanism is better, and the redistributable AddInUtility.dll can really help make this an easier process.</p> <h3>Whew!</h3> <p>While there’s a lot in this document, don’t despair… Chances are your application doesn’t use ALL of these features – does it? There are a variety of common, painful ones – but it’s mostly just mindless grinding through errors. </p> <p>Just go into it with the right expectations – it will take you at least 3-5x as long as it used to take you with previous upgrade projects! It will be worth it to get to Revit 2011!</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-79093457418647191202010-03-25T08:58:00.001-04:002010-03-25T08:58:26.181-04:00Revit 2011 API: Exceptional Stuff…<p>(Part of our <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">Revit API 2011 Series</a>) <br />Forgive the bad pun of a title…</p> <p>One of the new capabilities in the Revit 2011 API that I haven’t covered yet is some re-working of the way that Revit throws exceptions when you do something it doesn’t like… Whereas in the past, you would have gotten something pretty generic (in terms of the type of exception thrown), in 2011 Autodesk has introduced a variety of very specific Revit exceptions which are thrown. All of these inherit from Autodesk.Revit.Exceptions.ApplicationException:</p> <ul> <li>ApplicationException <ul> <li>ArgumentException <ul> <ul> <li>ArgumentNullException </li> <li>ArgumentOutOfRangeException </li> <li>ArgumentsInconsistentException </li> <li>FileArgumentNotFoundException </li> <li>InvalidPathArgumentException </li> </ul> </ul> </li> <li>InternalException </li> <li>InvalidOperationException <ul> <ul> <li>AutoJoinFailedException </li> <li>FamilyContextException </li> <li>ForbiddenForDynamicUpdateException </li> <li>InapplicableDataException </li> <li>IncorrectProductException </li> <li>InvalidLicenseException </li> <li>InvalidObjectException </li> <li>ModificationForbiddenException </li> <li>ModificationOutsideTransactionException </li> <li>ObjectAccessException </li> <li>RegenerationFailedException </li> </ul> </ul> </li> <li>IOException <ul> <ul> <li>DirectoryNotFoundException </li> <li>FileAccessException </li> <li>FileNotFoundException </li> <li>InvalidDataStreamException </li> </ul> </ul> </li> </ul> </li> </ul> <p>So what, you say? An exception is an exception, you say? I disagree – historically it has been painful to try to figure out why something didn’t work in Revit – the exceptions and error messages were not always helpful. And if you wanted to trap specific exceptions, it was pretty weak.</p> <p>I see this as a great investment on Autodesk’s part in making the Revit API “grow up” to a level of maturity that you can develop strong applications with it. Applications that are easier to control and to diagnose when something goes wrong.</p> <p>And speaking of diagnosis, there’s one other hidden gem in all these exceptions: the FunctionId. A property on these exceptions which gives you:</p> <ul> <li>The Revit source code file </li> <li>The Revit source code function </li> <li>The Revit source code line number </li> </ul> <p>where this particular exception occurred. This strikes me as a great help when I’m sending something in to Autodesk Developer Network… Telling them EXACTLY where in their code something is going bad (and to help me figure out why).</p> <p>All in all, I appreciate that they took some time to implement this in 2011.</p> <p><strong>Obscure Developer TechNote:</strong></p> <p>One thing that I had not been expecting… If you use the “Debug + Exceptions + Thrown Exceptions” in Visual Studio… When a Revit Exception is <em>first</em> thrown, it shows up as an “SEHException” which I believe means an unmanaged C++ exception that is bubbling up. That said, when it actually arrives – it is one of the new types shown above. So you actually have to let it bubble all the way up before you get the benefit of the knowledge of what it is.</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-90480264061516578272010-03-25T08:09:00.003-04:002010-03-25T08:13:24.306-04:00Revit API 2011: Ooh Ooh! Pick Me!<p>(Part of our <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">Revit API 2011 Series</a>) <br />The Revit 2011 API adds some new ways to interact with elements in the project – through picking. These are all available through the UIDocument.Selection class:</p> <ul> <li>PickObject (replaces PickOne – pick something in the active view – get back a reference) </li> <li>PickObjects – pick multiple objects, click “Finish” when done. </li> <li>PickElementsByRectangle – a replacement for “WindowSelect” </li> <li>PickPoint – return an XYZ coordinate based on picking on the active workplane </li> </ul> <h3>What’s Even Better?</h3> <p>All of the above except for PickPoint support a number of options that go deeper than what we had in Revit 2010 and prior (where you could only support picking full elements):</p> <ul> <li>Element (as before a whole element) </li> <li>Face (a specific face of an element) </li> <li>Edge (any model edge) </li> <li>PointOnElement (any point on any face or curve) </li> </ul> <p>Further, the methods mentioned above also support a new concept as well – a Selection Filter interface: ISelectionFilter. You can implement ISelectionFilter on any class – it will get callbacks from the pick method to help you control what is allowed to be selected or not:</p> <ul> <li>a Pre-filter method at the element-level </li> <li>a Post-filter method at the reference-level </li> </ul> <p>This lets you easily limit your selections to, for example, “walls” or “exterior walls” or “an inside horizontal top edge of an exterior wall” – the mind boggles.</p> <h3>But Wait, There’s More!</h3> <p>While PickPoint() does not support the options described above – it DOES support a different set of options – Object Snaps!</p> <ul> <li>Points - Snaps to site points. </li> <li>Quadrants - Snaps to quadrant points. For arcs, jump snaps are enabled. </li> <li>Tangents - Snaps tangent to an arc. </li> <li>Perpendicular - Snaps to perpendicular elements or components. </li> <li>Centers - Snaps to the center of an arc. </li> <li>Intersections - Snaps to intersections. </li> <li>WorkPlaneGrid - Snaps to a work plane grid. </li> <li>Nearest - Snaps to the nearest element or component. </li> <li>Midpoints - Snaps to the midpoint of an element or component. </li> <li>Endpoints - Snaps to the endpoint of an element or component. </li> </ul> <h3>Conclusion</h3> <p>The Pick mechanism in Revit has gone from paltry to an embarrassment of riches… I’m not aware of a better Pick API in any CAD system. While there are still a few usability oddities, it’s a vast improvement over 2010.</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com4tag:blogger.com,1999:blog-23382408.post-28174812884455930122010-03-25T08:09:00.001-04:002010-03-25T08:13:38.314-04:00Revit API 2011: User Interface Changes/Improvements<p>(Part of our <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">Revit API 2011 Series</a>) <br />The 2011 API has a variety of interesting enhancements in the ribbon user interface – making it possible to build applications which more closely match the look, feel and capability of native Revit commands (aside from being relegated to the Add-Ins tab).</p> <p>In 2010, the first Ribbon release, the API already had access to controls such as:</p> <ul> <li>RibbonPanel </li> <li>Pushbutton </li> <li>Stacked Pushbutton </li> <li>Pulldown Button </li> </ul> <p>What is new in 2011 are a wide variety of new controls and constructs in the ribbon:</p> <ul> <li>Combo Box </li> <li>SplitButton (like a Pulldown button, but it has a default action) </li> <li>TextBox </li> <li>SlideOut </li> </ul> <p>I created the following sample ExternalApplication which illustrates the different controls now possible:</p> <p><a href="http://lh4.ggpht.com/_dHu6uapG2Tg/S6tSaaBXaHI/AAAAAAAAAI0/2uoi7BfX9l0/s1600-h/image3.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Figure 1" border="0" alt="Figure 1" src="http://lh4.ggpht.com/_dHu6uapG2Tg/S6tSa9K9Z1I/AAAAAAAAAI4/of8XimLwn8w/image_thumb1.png?imgmax=800" width="456" height="146" /></a> <br /><strong>Figure 1</strong></p> <p>If the user has added a SlideOut to the RibbonPanel, any additional controls will be only available on the SlideOut panel – available when you click the down-arrow to the right of the Ribbon Panel name.</p> <p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_dHu6uapG2Tg/S6tSbKTG5vI/AAAAAAAAAI8/d4Acjt-lJt8/image_thumb3.png?imgmax=800" width="475" height="230" /> <br /><strong>Figure 2</strong></p> <p>Note that the slide out is “pinnable” to keep it open. That, combined with the ability to “tear off” the panel (also available in 2010) – makes for some interesting capabilities.</p> <h3></h3> <h3>Going Deeper</h3> <p>Beyond the new controls, there are some new capabilities a level deeper:</p> <ul> <li>Images on Pulldown buttons </li> <li>Tooltips and Long Descriptions – to provide more detail on how to run your command. </li> <li>Tooltip Images – to provide a graphic for your command – a picture is worth a thousand words </li> </ul> <p><a href="http://lh5.ggpht.com/_dHu6uapG2Tg/S6tSbd0UUnI/AAAAAAAAAJA/bFx2jLGTZ3A/s1600-h/image11.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_dHu6uapG2Tg/S6tSbiCdyCI/AAAAAAAAAJE/naROt9tprUI/image_thumb5.png?imgmax=800" width="423" height="521" /></a> </p> <h3>General Availability</h3> <p>Another new feature in 2011 is the ability to have an interface (IExternalCommandAvailability) which implements a check for whether your command should be enabled or disabled.</p> <p>This is useful if your command should only be available in a 3D View, or only if the user has filled out the setup/preferences dialog, or only if they user has pre-selected a certain category of elements. The command will be automatically enabled/disabled as appropriate.</p> <h3>The TaskDialog</h3> <p>One of the new core capabilities of Windows (starting in Vista) is an upgrade for the venerable MessageBox – called the TaskDialog. Revit now provides the TaskDialog on a platform-independent basis. The TaskDialog has all of the capabilities of the old MessageBox, but also has new and interesting capabilities like:</p> <ul> <li>Expanded Content (visible when the user expands it) </li> <li>As many or few buttons as you’d like (Yes/No/Close/Retry/About/etc). </li> <li>Up to 4 Command Link buttons with supporting text. </li> <li>Checkbox with verification text </li> <li>Footer text </li> </ul> <p>Here’s an example showing a bit of everything:</p> <p><a href="http://lh6.ggpht.com/_dHu6uapG2Tg/S6tScAOKsAI/AAAAAAAAAJI/4Uoti-r2ZtM/s1600-h/image15.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_dHu6uapG2Tg/S6tScVDg_jI/AAAAAAAAAJM/_YicMxFTp9Q/image_thumb7.png?imgmax=800" width="463" height="354" /></a></p> <p></p> <p>The code required to do a TaskDialog is pretty straightforward:</p> <table border="0" cellspacing="0" cellpadding="2" width="400"><tbody> <tr> <td valign="top" width="400"> <p>TaskDialog td = new TaskDialog("Hello World"); <br />td.MainContent = "This is main content"; <br />td.ExtendedContent = “This is shown on demand”; <br />td.Show();</p> <p>// or, alternatively – you can use a static method, if you only need the basics: <br />TaskDialog.Show("The Title", "The Main Instruction");</p> <p></p> </td> </tr> </tbody></table> <h3>Conclusion</h3> <p>Revit 2011 provides a good number of new controls and capabilities – it’s nice to be able to make applications that have the feel of native Revit commands.</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-49587780596333992862010-03-25T08:05:00.001-04:002010-03-25T08:13:55.584-04:00Revit API 2011: The New UI vs. Database Split<p>(Part of our <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">Revit API 2011 Series</a>) <br />One interesting development in the Revit 2011 API is the splitting of the single Revit API into two – a Revit User-Interface DLL and a core Revit database DLL.</p> <p>The “RevitAPI.dll” continues to cover the core database, while the new “RevitAPIUI.dll” covers the user-interface integration. This split extends to the core of the object model as well – while in the past the two primary classes in the API were <font face="Courier New">Application</font> and <font face="Courier New">Document</font>. Now, these classes have been split into:</p> <ul> <li><font face="Courier New">UIApplication</font> and Application </li> <li><font face="Courier New">UIDocument</font> and Document </li> </ul> <p><font face="Courier New">UIApplication</font> has picked up the classes and methods defining the RibbonPanels, the loaded applications, and some UI-oriented events like view changes and dialog boxes. The Application class retains the rest of the core application capability.</p> <p><font face="Courier New">UIDocument</font> picks up some of the UI-oriented aspects of the document, like selection, showing elements, and refreshing the active view.</p> <p>The IExternalCommand and IExternalApplication interfaces live in the RevitAPIUI.dll, so all Add-In DLLs will have to reference the new DLL.</p> <h3>What does it all mean?</h3> <p>I don’t know this for certain, but I’m hopeful that this signals a shift towards an ability to access the Revit model outside of the user interface (similar to ObjectDBX/RealDWG on the AutoCAD side). I’m sure this is a hard feature for the factory to pursue – but here’s hoping that we might see it in a release or two.</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-38845405058661500802010-03-25T08:04:00.001-04:002010-03-25T08:14:16.233-04:00What’s New in the Revit 2011 API: New Deployment Methods<p>(Part of our <a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-edition-whats-new.html">Revit API 2011 Series</a>) <br />Deploying commands and applications in Revit up until now has required a mental visit back to the 90’s… You had to create or edit sections within the Revit.INI file – keywords and values (and ugly ones at that). And developing installers which would programmatically add and remove things? Ugh!</p> <p>Autodesk has heard and finally answered the call on this issue – new in 2011 are XML-based “add-in” files. These new files (typically one for each program) also address some of the issues with permissions – particularly in Vista and Windows 7:</p> <p>The locations are:</p> <ul> <li>For “All Users”: <ul> <li>Windows XP: C:\Documents and Settings\All Users\Application Data\Autodesk\Revit\Addins\2011\ </li> <li>Windows Vista/Windows 7: C:\ProgramData\Autodesk\Revit\Addins\2011\ </li> </ul> </li> <li>For “User-Specific”: <ul> <li>Windows XP: C:\Documents and Settings\<user>\Application Data\Autodesk\Revit\Addins\2011\ </li> <li>Windows Vista/Windows 7: C:\Users\<user>\AppData\Roaming\Autodesk\Revit\Addins\2011\ </li> </ul> </li> </ul> <p>For .NET programmers, I would recommend using the Environment.GetFolder() method, where you can specify:</p> <ul> <li>All Users: Environment.SpecialFolder.CommonApplicationData </li> <li>Current User: Environment.SpecialFolder.ApplicationData </li> </ul> <p>A basic Command sample might look like:</p> <p><?xml version="1.0" encoding="utf-16" standalone="no"?> <br /><RevitAddIn> <br /><AddIn Type="Command"> <br /><Assembly>C:\MyDirectory\MyCommand.DLL</Assembly> <br /><ClientId>64end01a-5d66-4243-b4544-31429ecae9ed</ClientId> <br /><FullClassName>Avatech.RoomRenumber</FullClassName> <br /><Text>Room Renumber</Text> <br /><VisibilityMode>NotVisibleInFamily</VisibilityMode> <br /><VisibilityMode>NotVisibleInMEP</VisibilityMode> <br /><AccessibilityClassName></AccessibilityClassName> <br /></AddIn> <br /></RevitAddIn></p> <p>I’ll write more about some of the capabilities implied here – but as you can see it represents a big step forward versus the REVIT.INI file (which still works).</p> <h4>More Deployment Help Still… For Installers.</h4> <p>As mentioned above – writing installers for Revit in the olden-days was no picnic. While it’s no picnic in 2011, beyond the new file format, Autodesk has also provided an all-new redistributable DLL – specifically to help developers do installations in .NET.</p> <p>The “RevitAddInUtility.DLL” can:</p> <ol> <li>Provide you information about which versions of Revit 2011 are installed (no much reverse engineering 6+ uninstall registry keys!). </li> <li>Get all existing addins, and manifest. </li> </ol> <p>All in all, there are a variety of new features, capabilities and tools which bring more power and professionalism to Revit AddIn deployment in 2011.</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-36020925965238822092010-03-25T07:45:00.001-04:002010-04-24T20:09:10.963-04:00The Revit API – 2011 Edition – What’s New?<p>For the past few years, I’ve done a series of posts describing what’s new and possible in the latest version of Revit and it’s Application Programming Interface (API). For the uninitiated, the API is the series of mechanisms that Autodesk provides to be able to drive or analyze Revit through programming.</p> <p>2011 represents a watershed year in the ongoing development of the Revit API. Autodesk has taken the opportunity to re-work the API to better match how Revit works internally – and at the same time to do some amazing new things.</p> <p>Over the following series of posts, I hope to cover topics such as:</p> <ol> <li><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-upgrading-existing-add.html">Upgrading Existing Revit API commands/applications</a> </li> <li><a href="http://cadappdev.blogspot.com/2010/03/whats-new-in-revit-2011-api-new.html">New Deployment Methods</a> </li> <li><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-new-ui-vs-database-split.html">The New UI vs. Database split</a>. </li> <li><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-user-interface.html">New Ribbon Capabilities</a> </li> <li><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-new-way-to-find-elements.html">Element Iteration Changes</a> </li> <li><a href="http://cadappdev.blogspot.com/2010/03/revit-api-2011-ooh-ooh-pick-me.html">Ooh-ooh Pick Me! New Selection Methods</a> </li> <li>Dynamic Model Update </li> <li>Event Model Changes </li> <li><a href="http://cadappdev.blogspot.com/2010/04/revit-2011-api-series-revitlookup-new.html">RevitLookup: The New RevitMgdDbg</a> </li> <li><a href="http://cadappdev.blogspot.com/2010/04/revit-api-2011-revit-addin-manager.html">Revit AddIn Manager: Almost Edit & Continue</a></li> <li><a href="http://cadappdev.blogspot.com/2010/04/revit-2011-api-whats-new-in-element.html">What’s New in Element Creation?</a> </li> <li><a href="http://cadappdev.blogspot.com/2010/03/revit-2011-api-exceptional-stuff.html">Exceptional Stuff</a></li> <li>What Kinds of Applications are Possible Now? </li> <li>And More… </li> </ol> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com2tag:blogger.com,1999:blog-23382408.post-13680655464450451372009-10-11T16:56:00.003-04:002009-10-11T17:08:01.107-04:00What Type of Element is this? It depends...<a href="http://2.bp.blogspot.com/_dHu6uapG2Tg/StJHfP5ZZBI/AAAAAAAAAIk/bBP_K5-gn3M/s1600-h/RevitTypes.jpg"><img style="MARGIN: 0px 10px 10px 0px; WIDTH: 400px; FLOAT: left; HEIGHT: 291px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5391450306084693010" border="0" alt="" src="http://2.bp.blogspot.com/_dHu6uapG2Tg/StJHfP5ZZBI/AAAAAAAAAIk/bBP_K5-gn3M/s400/RevitTypes.jpg" /></a><br /><br />(Sorry for the long interruption in blogging - project work was just too heavy to devote time to blogging).<br /><br /><br /><br /><br /><br />I ran into something interesting yesterday that I had not seen before, and I figured it was worthy of a quick blog post. When doing Revit-oriented development, there are a lot of times when you check the type of an element, and have logic in place to handle that element based on the type.<br /><br /><br /><br /><br /><br />I was running an application that I had tested before in the past - but it was no longer working - why? And then I stumbled upon an interesting quirk about Revit Architecture versus Revit MEP - something that I had never encountered before:<br /><br /><br /><br />For certain types such as Pipe, when you ask Revit what type it is - the answer depends on which flavor of Revit you are using. In the sample above, I was interrogating a pipe element. In Revit MEP, it tells you it is a Pipe. BUT - with the same model in Revit Architecture - it tells you that it is an "Element" (Revit's code word for generic elements that don't have any special definition).<br /><br />The element's category is consistently reported as "Pipes" - but this is just the first time I've ever noticed the type of object being different based on which flavor of Revit you're in. It makes sense that Revit behaves this way - if it did not, you would be exposing a variety of properties and methods for this type of object which should only be available in MEP.<br /><br />In any case - just be aware - the code that you have that works perfectly one way in MEP could work completely differently in Revit Architecture (and I'm sure this is not the only scenario).<div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-78694296170011167552009-07-20T09:03:00.002-04:002009-07-20T09:14:52.500-04:00Avatech Utilities for Revit<a href="http://www.avatech.com/images/solutions/boxshots/revit_utilities_boxshot.jpg"><img style="MARGIN: 0px 0px 10px 10px; WIDTH: 98px; FLOAT: right; HEIGHT: 117px; CURSOR: hand" border="0" alt="" src="http://www.avatech.com/images/solutions/boxshots/revit_utilities_boxshot.jpg" /></a><br /><br />We finally got our <a href="http://www.avatech.com/web/revitutilities">Avatech Utilities for Revit </a>launched a month or so ago. We've added to the list of utilities as well:<br /><ul><li>Room Renumber</li><li>Change Case</li><li>Space Update (New)</li><li>Grid Select (New)</li><li>Door Mark Update</li><li>RevitCity Content Browser</li><li>Earth Connector</li><li>Room Phase Copy (New)</li></ul><p>Unfortunately - we came to a hard decision... because of the amount of effort it takes to produce, support and update these utilities on an ongoing basis - we have to start charging money for them.</p><p>Because we didn't really give any warning on this - we wanted to make this as fair as possible for the 2010 release.</p><p>As such, we did the following:</p><ul><li>Avatech Utilities for Revit LITE - this will continue to be free (it's made up of the top four utilities above).</li><li>Avatech Utilities for Revit - will be offered for $395 USD / seat </li></ul><p>To take care of all of the people who had previously downloaded the software- we've put in a one-time program to give previous downloaders 5 standalone seats of the software (this was sent via e-mail to the address which was registered during the download). You should have received the second and final notice of this program today (so if you're thinking "where was that?" you might want to check your junk mail folder or something like that).</p><p>Finally, there will be other special offers for customers who purchase their Revit software through Avatech (which I realize is only a fraction of the total audience - sorry!).</p><p>While this has been a bit tough for us to work through - I'm looking forward to what this means - we should be able to do a better job growing and releasing more utilities in the future.</p><p>-Matt</p><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com4tag:blogger.com,1999:blog-23382408.post-32043852739917334702009-07-20T09:01:00.003-04:002009-07-20T09:03:11.726-04:00Getting back into the swing of thingsI apologize! I've committed the cardinal sin of blogging - not doing it once you got started.<br /><br />But you know how it is - work gets busy, yadda, yadda, yadda.<br /><br />In any case - I think it's back to a level where I can blog occasionally... and I'm looking forward to it. Now if I can just remember all the ideas I had while I've been "away".<div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0tag:blogger.com,1999:blog-23382408.post-91887027946035161982009-05-08T08:29:00.003-04:002009-05-08T08:36:30.041-04:00Autodesk University 2009 VotingHi there, readers...<br /><br />Today is the last day of public voting for the Autodesk University 2009 conference...<br /><br />I've submitted three classes and I'd REALLY appreciate your vote:<br /><br /><ul><li>Deep Dive on the Revit API: Advanced Topics</li><li>The Power of Creation in the Revit API</li><li>Check It! Building Check Plugins for BIMreview</li></ul><p>You can vote at:</p><p><a href="http://au.autodesk.com/?tagent=em30&nd=au_voting_login" target="_NEW">AU Session Selection</a></p><p>Thanks!</p><div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com2tag:blogger.com,1999:blog-23382408.post-62756727152326467682009-03-14T13:58:00.001-04:002009-03-14T13:58:58.006-04:00What’s New in the Revit 2010 API: Geometry<p>(Part of the <a href="http://cadappdev.blogspot.com/2009/02/whats-new-in-revit-2010-api.html">What’s New in the Revit 2010 API</a> series)</p> <p>The Geometry area of the Revit API has a few interesting and helpful enhancements in the 2010 version.</p> <p><a href="http://lh4.ggpht.com/_dHu6uapG2Tg/SbvwXRfvaRI/AAAAAAAAAIc/zPY0b7Rv3EE/s1600-h/image%5B3%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/_dHu6uapG2Tg/SbvwYD2J-xI/AAAAAAAAAIg/TS3Wj2kmnVA/image_thumb%5B1%5D.png?imgmax=800" width="244" height="202" /></a> Probably the most obvious of the enhancements were made to support Revit’s new conceptual massing capabilities.</p> <h3>HermiteSpline</h3> <p>While there was previously a HermiteFace class to represent the surface – we now have a HermiteSpline element for the splines that can be created (which will probably result in many more HermiteFaces as well – since it only takes one button to go from spline to face).</p> <p>The HermiteSpline exposes its control points and tangent vectors (nice touch). <strong>WARNING</strong>: <em>For those of you who have been using Tessellation – like we have on our Earth Connector application – be prepared for an explosion of points as Revit Users start using splines. The 5-point spline shown above tessellated into 287 points… (I probably have to start investing some mental energy in a “reduce” function – because that’s pretty heavy!).</em></p> <h3>Point</h3> <p>As I joked about in one of the previous posts – Autodesk has finally broken down and added the Point concept to Revit (yes, yes – the XYZ class was there before – but Points are now first class geometric objects).</p> <p>The reference points in the picture above are part of the spline, but it is possible to create standalone ReferencePoint elements – and the geometry extracted for the reference point is a Geometry point. </p> <p>I have not yet figured out why it’s important to have a point in the geometry class (since you can get the location directly from the element) – but I’m sure that there is a good reason (consistency, if nothing else, I suppose).</p> <h3>Making Life a Little Easier for You</h3> <p>Historically if you dealt with geometry in the Revit API, you had to brush up on your linear algebra in order to deal with Transformation matrices… For example, a chair might be modeled within a family centered on the 0,0,0 point – but then it gets placed 100 times into a project way out in space. Every instance has a transformation matrix that gets you from the “internal” geometry locations – also known as the “SymbolGeometry” – out to the actual geometry location in the project.</p> <p>It was even worse when items are nested a few levels deep… I know that, for example, stairs have railings and railings have balusters – and balusters gave me fits for quite some time, being a good number of levels deep.</p> <p>Autodesk started making this better a couple of releases ago – making it easier to get the transformed version of things – and they’ve taken it another step now.</p> <ul> <li>Instance.GetInstanceGeometry()</li> <li>Instance.GetSymbolGeometry()</li> </ul> <p>(Instance is the Geometry class which represents things like FamilyInstances, and other elements where you need to dig into the definition of things). Both of these methods can optionally take a transform matrix to transform – or just give you the easy answer.</p> <h3>The Hit Reference</h3> <p>I mentioned in “<a href="http://cadappdev.blogspot.com/2009/02/whats-new-in-revit-2010-api-very.html">Very Spatial APIs</a>” that the Reference class has been upgraded, mainly to provide the additional information retrieved when shooting rays through elements. The new properties:</p> <ul> <li>ProximityParameter (how close the hit is to the origin)</li> <li>Element (the element that was hit)</li> <li>ElementReferenceType:</li> <ul> <ul> <li>MESH</li> <li>CUT_EDGE</li> <li>INSTANCE</li> <li>FOREIGN (from the docs: “The reference is to geometry or elements in linked Revit file.”)</li> <li>SURFACE</li> <li>LINEAR (curve or edge)</li> </ul> </ul> <li>GeometryObject (the geometry intersected)</li> <li>Transform (of an instance, if that’s what was hit)</li> <li>UVPoint (U,V parameters of the face, if that’s what was hit)</li> </ul> <h3>Summary</h3> <p>This is yet another area with modest but solid improvement in the API in 2010.</p> <div class="blogger-post-footer">Copyright (C) 2006-2010, Matt Mason
Content provided here does not necessarily reflect the views of Rand Worldwide, Inc.</div>Matt Masonhttp://www.blogger.com/profile/13505746985622750229noreply@blogger.com0