Thursday 11 August 2011

Quality

We want quality models. A basic rule for quality processes is to determine the root causes of defects. Once you’ve found the root cause, you can change things to (try and) prevent the problem happening again (the oft-misunderstood preventative action)

So when we find a problem in the Revit model, I’d like to know how it happened. But Revit’s infuriatingly opaque. It won’t reveal its sources.

Revit knows who changed the elements. It knows when the changes were committed to the file. We’re not short of disk space (well we are, but that’s another story), so I can allow Revit to keep the full file history. But I just would like to be able to call up the version of the file from a date in the past, and then ask ‘what happened to this element between then and now?’

Then I could find out why the change was made, and change things to try and avoid the problem in the future.

Wednesday 10 August 2011

Exploded Views

So in Revit 2020, I’ve modelled a complex construction with all its sub-components. How do I convey that to my construction teams?

I can let them pick my model apart, of course. But I’d really like to be able to generate live exploded views. Something like Revit 2012’s locked 3D views, except that I can move the components apart to show how it all fits together.

Memo to self: Is there anything like this in Inventor, for example?

Tuesday 9 August 2011

Stone jointing

So I’m modelling a stone facade. I need to define the individual stones (my stone supplier needs dimensioned drawings). They’re not in a continuous pattern, but there’s some pattern-like quality.

I could define a complex .pat file and align it onto a basic wall. But that doesn’t show up in plan, so I can’t create setting-out plans for the different courses (my walls are curved, so they can’t be set out on elevation).

I’d really like a cross between a .pat file (to set the pattern), and curtain wall gridlines (real 3D cutting planes), to generate individual stones in a definable, patterned way.

Monday 8 August 2011

Finding gaps in room boundaries

When a Room isn’t bounded where it should be, it can be tricky to find the gap. You have to spend time putting in Room Boundary lines to narrow down the search.

How would it be if you could just pour (virtual) liquid into the Room, at the room’s origin, and watch while it flowed out to fill the room. You’d instantly see where Revit was finding gaps in the boundary, because that would be where the ‘liquid’ flowed out.

Sunday 7 August 2011

Room Floors

Joe Stott recently posted about using Ceilings to model floor finishes in Revit, because the Automatic Ceiling tool finds the ceiling boundaries, er, automatically.

But it would be better BIM if the floor finishes were modelled as Floors. And I’ve always though there should be some way of connecting a Room’s Floor Finish property with the modelled floor finish.

So, as a proof of concept, here is a VSTA macro for R2012: MakeFloorsForSelectedRooms.

For each Room you’ve selected, it makes a new floor the same shape as the Room. The floor type is taken from the Room’s Floor Finish property:

  • If there’s a Floor Type with a matching name, the new floor will be of that type.
  • If there isn’t a matching Floor Type, a new Type is created.
  • If the Floor Finish property is blank, the new Floor will be a new default type.

As a proof of concept, it’s still a bit rough around the edges. And there are lots of ways in which it could be extended. As usual, the code comes with no warranties: Experiment at your own risk.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Autodesk.Revit.DB;
using DBArch = Autodesk.Revit.DB.Architecture;

namespace RoomFloors
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
[Autodesk.Revit.VSTA.AddInId("039bfb1c-5582-4afc-ab85-491abcf2484a")]
public partial class ThisApplication
{
#region Fields

public int MakeOpeningExceptionCount { get; set; }
public int MakeFloorExceptionCount { get; set; }

private FloorType defaultFloorType;

#endregion

#region Startup and Shutdown

private void Module_Startup(object sender, EventArgs e)
{

}

private void Module_Shutdown(object sender, EventArgs e)
{

}

#endregion

#region VSTA generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(Module_Startup);
this.Shutdown += new System.EventHandler(Module_Shutdown);
}
#endregion

public void MakeFloorsForSelectedRooms()
{
Transaction transaction = new Transaction(ActiveUIDocument.Document);
if (transaction.Start("Create new floors") == TransactionStatus.Started)
{

defaultFloorType = GetDefaultFloorType();
Autodesk.Revit.UI.Selection.SelElementSet collection = ActiveUIDocument.Selection.Elements;
foreach (Autodesk.Revit.DB.Element element in collection)
{
if (element is DBArch.Room)
{
MakeFloorForRoom(element as DBArch.Room);
}
}
transaction.Commit();
}

}

#region Floor Making

private void MakeFloorForRoom(DBArch.Room room)
{
SpatialElementBoundaryOptions options = new SpatialElementBoundaryOptions();
IList<IList<BoundarySegment>> bounds = room.GetBoundarySegments(options);
CurveArrArray boundsArray = new CurveArrArray();
Floor floor = null;
bool outerLoop = true;
foreach (IList<BoundarySegment> loop in bounds)
{
CurveArray profile = new CurveArray();
foreach (BoundarySegment segment in loop)
{
Curve curve = segment.Curve;
profile.Append(curve);
}
if (outerLoop)
{
FloorType newFloorType;
string newFloorTypeName = GetFloorTypeName(room);
if ("" == newFloorTypeName)
{ newFloorType = defaultFloorType; }
else { newFloorType = GetOrMakeFloorType(newFloorTypeName); }

floor = MakeAFloor(profile, room.Level, room.BaseOffset, newFloorType);
outerLoop = false;
}
else
{
if (null != floor) { MakeAnOpening(floor, profile); }
}
}
}

private string GetFloorTypeName(DBArch.Room room)
{
string newFloorTypeName = GetProperty(room, BuiltInParameter.ROOM_FINISH_FLOOR);
if (null == newFloorTypeName) { newFloorTypeName = ""; }
return newFloorTypeName;
}

private Floor MakeAFloor(CurveArray loop, Level level, double offset, FloorType newFloorType)
{
Floor newFloor = null;

try
{
newFloor = ActiveUIDocument.Document.Create.NewFloor(loop, newFloorType, level, false);

}
catch (Exception ex)
{
MakeFloorExceptionCount++;
Debug.WriteLine("Exception: " + ex.Message);
//throw;
}

if (null != newFloor)
{
BuiltInParameter paraIndex = BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM;
Parameter parameter = newFloor.get_Parameter(paraIndex);
parameter.Set(offset + GetFloorThickness(defaultFloorType));
}
return newFloor;
}

private void MakeAnOpening(Floor floor, CurveArray loop)
{
try
{
Opening newOpening = ActiveUIDocument.Document.Create.NewOpening(floor, loop, true);
}
catch (Exception ex)
{
MakeOpeningExceptionCount++;
Debug.WriteLine("Exception: " + ex.Message);
//throw;
}

}

#endregion

#region Floor Types


private FloorType GetDefaultFloorType()
{
string newFloorTypeName = GetUniqueFloorTypeName();
return MakeNewFloorType(newFloorTypeName);
}

private FloorType MakeNewFloorType(string newFloorTypeName)
{
FloorType newFloortype = (FloorType)GetFloorType().Duplicate(newFloorTypeName);
return newFloortype;
}

private string GetUniqueFloorTypeName()
{
int index = 0;
string proposedFloorTypeName;
do
{
index++;
proposedFloorTypeName = "DefaultFloorType" + index.ToString();
} while (!IsUniqueName(proposedFloorTypeName));
return proposedFloorTypeName;
}

private bool IsUniqueName(string proposedFloorTypeName)
{
FloorTypeSet floorTypes = ActiveUIDocument.Document.FloorTypes;
bool isUniqueName = true;
foreach (FloorType floorType in floorTypes)
{
if (floorType.Name == proposedFloorTypeName) { isUniqueName = false; }
}
return isUniqueName;
}

private FloorType GetFloorType()
{
FloorType myFloorType = null;
FloorTypeSet floorTypes = ActiveUIDocument.Document.FloorTypes;
foreach (FloorType floorType in floorTypes)
{
myFloorType = floorType;
}
if (null == myFloorType)
{ throw new Exception("No FloorTypes in Document"); }
return myFloorType;
}

private FloorType GetOrMakeFloorType(string floorTypeName)
{
FloorType myFloorType = null;
FloorTypeSet floorTypes = ActiveUIDocument.Document.FloorTypes;
foreach (FloorType floorType in floorTypes)
{
if (floorTypeName == floorType.Name)
{ myFloorType = floorType; }
}
if (null == myFloorType)
{ myFloorType = MakeNewFloorType(floorTypeName); }
return myFloorType;
}



private double GetFloorThickness(FloorType floorType)
{
//return 1; //in feet;
double floorThickness = 0;
CompoundStructure comStruct = floorType.GetCompoundStructure();
foreach (CompoundStructureLayer structLayer in comStruct.GetLayers())
{ floorThickness += structLayer.Width; }

return floorThickness;
}


#endregion

#region Utility

public String GetProperty(DBArch.Room room, BuiltInParameter paramEnum)
{
String propertyValue = null; //the value of parameter

//get the parameter via the parameterId
Parameter param = room.get_Parameter(paramEnum);
//get the parameter's storage type
StorageType storageType = param.StorageType;
switch (storageType)
{
case StorageType.Integer:
int iVal = param.AsInteger();
propertyValue = iVal.ToString();
break;
case StorageType.String:
String stringVal = param.AsString();
propertyValue = stringVal;
break;
case StorageType.Double:
Double dVal = param.AsDouble();
dVal = Math.Round(dVal, 2);
propertyValue = dVal.ToString();
break;
default:
break;
}
return propertyValue;
}

#endregion
}
}

Tuesday 14 June 2011

X Y Z

It’s curious that Revit hides its coordinate system. When you look at the properties of a line in AutoCAD, the X,Y,Z coordinates of its endpoints are right there.

But in Revit, objects don’t know their own coordinates. So you can’t tag or schedule them. And you can’t use coordinates to drive object properties (other than via the API).

Sunday 12 June 2011

Windposts

So we have some windposts in the masonry wall. They’re just RHS sections.

But do we model them as structural framing, or as some kind of custom-made generic model?

Logic says they’re a length of RHS with structural properties, so they’re structural framing. But logic also says they’re wall-based.

How would it be if you could embed a piece of RHS structural framing inside a wall-based family? Just like you can embed a shared window or door. Then the family could be both structural framing and wall-based at the same time: The structural framing element would give you all the structural properties, and the wall-based wrapper would give you the sticks-to-the-wall feature.

Saturday 11 June 2011

Parametric view names

So your plan of Level 1 is called Level 1, but the two values aren’t parametrically connected.

And there’s no way to have the views of Phase 2 named ‘Phase2’ automatically.

How would it be if the names of views were like labels, so they could be driven by the view’s own parameters?

Friday 10 June 2011

Quick Select

AutoCAD has Quick Select, which lets you select objects by their properties.

It would be useful to have similar functionality in Revit:

“Select all the walls of <this type> in <this workset> created in <this phase>, where the base of the wall is below 56.060m and the top is Unconnected.”

Something for the API? A generalised SQL-for-Revit implementation? Perhaps.

Wednesday 8 June 2011

Worksets

Worksets were a wonderful idea back in the day. You could partition the project up into chunks (‘worksets’), and several people could work in the same file at the same time (‘worksharing’) as long as they all worked in different chunks. Great feature.

Now that Revit has element borrowing, worksets are hardly ever needed for worksharing.

But that hasn’t stopped us press-ganging them into use for all sorts of other purposes:

  • Locking up grids and levels (lock out the workset as ‘admin’)
  • Partial loading (close the worksets you’re not using)
  • Partial loading of linked files (close worksets in a linked model)
  • Controlling visibility (hide a workset in a view)

Such a wide range of misuses, showing such ingenuity. But all would be better served by purpose-designed features rather than by the poor abused workset.

Tuesday 7 June 2011

Linked families

You can link Revit projects and CAD files, but you can’t link families.

We break our larger projects into separate files to keep them fast.

But that makes it tedious to maintain a common set of families. Every time you edit a family, you have to open each of the projects and load in the changed family.

Wouldn’t it be better if you could link the families from a project library and update them in just one place?

Monday 6 June 2011

Gates

Railings (fences) need gates, just like curtain walls need doors.

If railings had the same default + overrides behaviour as curtain walls, gates would be easy.

Wednesday 25 May 2011

BIM MSc at Salford

The University of Salford are offering an MSc in BIM and Integrated Design. There’s a launch party at the Old Fire Station in Salford, Tuesday 7th June at 4:00:

MSc BIM and Integrated Design launch event

Native DWG handling

DWG format is going to be used for years. Many of our partners don’t use Revit and never will: It’s just not appropriate for many specialist sub-contractors for example.

But we need to bring their DWGs into Revit. So Revit needs to handle DWGs seamlessly.

It shouldn’t be hard. AutoCAD handles DWG data pretty well. Autodesk own the AutoCAD code. Those of us with Revit Suites already have the AutoCAD code installed. Revit’s code ‘just’ needs to talk nicely to AutoCAD’s.

Oh, and how about seamless in-place editing of DWGs in a Revit session? For an example, just look at how you can embed an Excel spreadsheet into a Word document (Insert/Object/Excel). Double-click the Excel sheet to edit it in-place, and the toolbars and ribbons all change to Excel ones.

Imagine taking the same approach with AutoCAD, Revit, Inventor, Max, etc: Use the most appropriate set of tools for the job in hand, within one fluid interface.

Tuesday 24 May 2011

In-place edit

How about in-place editing of linked Revit files?

It’s been a wishlist item for a while, here and here for example. There are workarounds, but none achieve the simplicity and flow of being able to edit in place.

Monday 23 May 2011

Automatic annotation

So I’d like to define a view (a plan view) in which all the rooms are always tagged. If I add a new room, this view creates a tag for it automatically. So I don’t have to go round to all of my fifty plan views tagging all the untagged rooms before every issue.

Oh, and the room tags adjust themselves to fit, of course. Didn’t I mention that? If you move their room, they move with it. If they’re too big to fit in their room, they move into a clear space nearby and generate their own leader line. They place themselves nicely in odd-shaped rooms.

Is that too much to ask?

Just extend the principle to enable self-documenting building models. You model the building. Revit generates the documents.

Sunday 22 May 2011

(Sub)components 2

So I’m designing a brick cavity wall. The brick face has a stretcher-bond surface pattern, which I’ve aligned accurately. But when I come to draw the details, I have to position repeating details to show the bricks and mortar joints.

Wait a minute, I’ve told Revit I’m using brickwork. I’ve told it how the joints are aligned. Why can’t Revit work out where the bricks are in the detail?

How would it be if, following on from Friday’s post, you could define the brick bond in terms of sub-components and not just as a simple surface pattern?

Then the brickwork could come alive. Walls could snap to brick dimensions. Openings could clip into place. All the cavity wall hardware (weep holes, wall ties, cavity trays, lintels, etc.) could auto-generate.You could project or contrast-colour individual bricks to create daiper patterns.

Yes, perhaps not on today’s hardware. But by 2020, why not?

Friday 20 May 2011

(Sub)components

A stud wall is made of components – studs, board, nails and so on. How would Revit change if it could easily model all the components?

You wouldn’t want to lose the simplicity of placing a wall. You’d just need to be able to define the way the wall generated its studs and board, both in the field and at junctions and openings. You might need a calculation- or code-based solver for stud sizing and spacing. For a full bill-of-materials, you’d need rules for itemising nails and fixings. You might even have manufacturer-specific plug-ins for proprietary framing systems and fabrication machines. And all parametric, so that the components flex with the wall.

None of this needs to impact on the simplicity of placing a wall. It just allows us to move closer to a fully-designed BIM.

Some designers won’t need so much detail, but those who need to check that the power sockets don’t clash with the studs, and those who are designing for manufacture/prefabrication, could really make use of sub-components.

And just to be clear, I’m not really asking for a stud framing solution within Revit, because there are third-party solutions for stud framing. I’m just using stud walls as an illustration of the need for a general-purpose sub-component solution.

Thursday 19 May 2011

Spot Annotations 2

Following on from yesterday’s post on step annotations, I wonder whether there’s scope to expand the range of similar annotations. Currently, there are three special-purpose spot annotations: Spot Elevation, Spot Coordinate and Spot Slope. I’m always looking for ways to generalise special-purpose tools, to make them more versatile and perhaps more intuitive.

If you imagine how you would design tools like these in the family editor, you’d need to define host points and be able to annotate based on the properties (X,Y,Z) of those host points. That’s all the spot annotation tools do, and it’s what my proposed step annotation tool does.

Thinking about how you’d place these annotation in the project, it would be simplest to just place them with one click, and then drag any extra host points to position them. Alternatively, you could place multi-point annotations with a series of clicks – it just might make for an awkward user interface, each family needing a different number of clicks.

Wednesday 18 May 2011

Step Annotations

It would be nice to have step annotations. Similar to spot elevations, but with two hosts: The annotation value would be the difference in level between the two host points.

Saturday 14 May 2011

Lumpy Levels

Levels are level. But what if they weren’t?

Imagine a building on a sloping site. The ground floor is stepped. Conceptually, everything on the ground floor could be on Level 0, no matter what its actual elevation is. Level 0 could just tell you what the elevation of the ground floor is at any point on the site.

I’m currently dealing with a project which has just ten storeys, but over 100 distinct floor levels.

Another example from a 2006 AUGI post: A mile-long building on a slope of 1/32" per foot.

FOA's Yokohama International Port Terminal, Frank Lloyd Wright’s Guggenheim Museum, there’s a fair number of buildings that would be easier to model with non-level Levels.

Friday 13 May 2011

Favourite Views

You can sort and filter views and sheets in the project browser.

How about being able to select some ‘favourite views’ and have them grouped together at the top of the browser?

Better still, have several sets of favourite views, so you can have different sets for different purposes? One set for editing facades, one for cores, one for rooms, and so on.

The closest you can get to this at the moment is to create print sets (using Selected views/sheets in the Print dialog), and then create a browser organisation for each print set, using the print set as a filter (thanks to this thread for that tip).

But it would be better if the print sets were just listed in the project browser. Add in drag/drop add-a-view-to-a-set and right-click access to the print sets dialog box, and you’d have a winning feature.

Wednesday 11 May 2011

Highlight Lineworked lines

You can use the Linework tool to change the linestyle of individual edges in a view.

It would be useful to be able to highlight which edges have been Lineworked.

Tuesday 10 May 2011

Default + Overrides = Power + Flexibility

Curtain walls are flexible and powerful. Part of that flexibility and power comes from the way you can set up a curtain wall Type with grid setting-out, mullion and panel types, but then override those defaults individually: You can unpin just one panel to change it into a door, for example.

Contrast curtain walls’ flexibility with that of railings. With railings, you can set the spacing of the balusters in the Type, but there’s no way to override an individual baluster in a particular railing instance.

Default + Overrides. It’s a powerful, flexible pattern.

Monday 9 May 2011

Group = Family

If you could make a parametric component from any collection of Revit elements, there’d be no need to distinguish between groups and families.

Groups would have parameters. Exclude Elements From Group would be replaced by visibility parameters on the group elements. Edit Group would be replaced by an uprated Edit Family In-Place .

Families could be created simply by selecting the elements and hitting the ‘Create Family’ button.

You’d need to be able to add relationships and constraints after creating the solid geometry, which is the reverse of the usual family-creation process. That might need some better tools, but I’ll leave them for another post.

Sunday 8 May 2011

Project components and Flexible Buildings

If project files had controllable parameters just like families, you could make a parametric component out of any collection of Revit elements.

And you could flex a whole building model as easily as you can flex a conceptual mass in Revit 2012.

Tuesday 3 May 2011

Project = Family

A simple question: Why do we distinguish between projects and families? What if 'projects' could be flexed with parameters? What if 'families' could contain walls, floors and roofs?