译者注:我旁听了上海中心的负责人在去年的北京AU大师会上做的关于 Autodesk BIM 在上海中心设计和建造中应用的主题演讲。会后我向他问了些 Revit 具体的使用情况。上海中心前期的设计多数还是用AutoCAD和犀牛等传统工具完成的。Revit 更多得是在整体方案设计阶段体现出它的数据一致性优势。估计他们那时候使用的是 Revit 2010。相信如果使用 Revit 2013 的话,更多的工作将会被直接拿到 Revit 中完成了。今年的AU大师会在上海,希望能听到更多关于 Revit 实际应用的介绍。另外我也会和东南大学的一位教授共同做“基于BIM技术的工业化住宅产业联盟数字设计与管理平台开发”的报告。
译者注:剖视图中坐标系和 Revit 模型坐标系是不一样的。以与墙体平行的剖视图为例:X方向是墙体的水平方向;Y方向是墙体的垂直方向(即Revit模型坐标系中的Z轴方向);Z方向是与墙面垂直的方向。
[Transaction( TransactionMode.Manual )]
public class Command : IExternalCommand
{
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements )
{
UIApplication uiapp = commandData.Application;
UIDocument uidoc = uiapp.ActiveUIDocument;
Document doc = uidoc.Document;
// 获取选中墙体
Selection sel = uidoc.Selection;
SelElementSet set = sel.Elements;
Wall wall = null;
if( 1 == set.Size )
{
foreach( Element e in set )
{
wall = e as Wall;
}
}
if( null == wall )
{
message = "Please select exactly one wall element.";
return Result.Failed;
}
// 确认是直线墙
LocationCurve lc = wall.Location as LocationCurve;
Line line = lc.Curve as Line;
if( null == line )
{
message = "Unable to retrieve wall location line.";
return Result.Failed;
}
// 获取视图类型对象
ViewFamilyType vft = new FilteredElementCollector( doc )
.OfClass( typeof( ViewFamilyType ) )
.Cast<ViewFamilyType>()
.FirstOrDefault<ViewFamilyType>( x => ViewFamily.Section == x.ViewFamily );
// 计算视图区域
XYZ p = line.get_EndPoint( 0 );
XYZ q = line.get_EndPoint( 1 );
XYZ v = q - p;
BoundingBoxXYZ bb = wall.get_BoundingBox( null );
double minZ = bb.Min.Z;
double maxZ = bb.Max.Z;
double w = v.GetLength();
double h = maxZ - minZ;
double d = wall.WallType.Width;
double offset = 0.1 * w;
XYZ min = new XYZ( -w, minZ - offset, -offset );
XYZ max = new XYZ( w, maxZ + offset, 0 );
XYZ midpoint = p + 0.5 * v;
XYZ walldir = v.Normalize();
XYZ up = XYZ.BasisZ;
XYZ viewdir = walldir.CrossProduct( up );
Transform t = Transform.Identity;
t.Origin = midpoint;
t.BasisX = walldir;
t.BasisY = up;
t.BasisZ = viewdir;
BoundingBoxXYZ sectionBox = new BoundingBoxXYZ();
sectionBox.Transform = t;
sectionBox.Min = min;
sectionBox.Max = max;
// 创建墙体剖视图
using( Transaction tx = new Transaction( doc ) )
{
tx.Start( "Create Wall Section View" );
ViewSection.CreateSection( doc, vft.Id, sectionBox );
tx.Commit();
}
return Result.Succeeded;
}
}
问题
上面的代码创建的虚线部分与墙体位置线重合了。我希望剖视图区域边界对称地位于墙体两侧。
Jeremy
XYZ min = new XYZ( -w, minZ - offset, -offset ); XYZ max = new XYZ( w, maxZ + offset, 0 );
XYZ min = new XYZ( -w, minZ - offset, -offset );
XYZ max = new XYZ( w, maxZ + offset, offset );
BoundingBoxXYZ GetSectionViewPerpendiculatToWall( Wall wall ) { LocationCurve lc = wall.Location as LocationCurve; // 使用 0.5 和 "true" 保证 Transform 的原点在墙体中心点且向量是规范化的。 Transform curveTransform = lc.Curve.ComputeDerivatives( 0.5, true ); // Transform 包含了位置线的中心点和正切线,这样我们就能获取其位于 XY 平面的法线了。 XYZ origin = curveTransform.Origin; XYZ viewdir = curveTransform.BasisX.Normalize(); XYZ up = XYZ.BasisZ; XYZ right = up.CrossProduct( viewdir ); // 设置视图 Transform,假设墙体是垂直方向的。对于非垂直方向墙体(例如:有斜坡的地板),我们需要其表面的法线 Transform transform = Transform.Identity; transform.Origin = origin; transform.BasisX = right; transform.BasisY = up; transform.BasisZ = viewdir; BoundingBoxXYZ sectionBox = new BoundingBoxXYZ(); sectionBox.Transform = transform; // Min & Max X 值定义位于墙体两侧的剖线长度; // Max Y 是剖视区域的高度; // Max Z (5) 是远端剪裁偏移 double d = wall.WallType.Width; BoundingBoxXYZ bb = wall.get_BoundingBox( null ); double minZ = bb.Min.Z; double maxZ = bb.Max.Z; double h = maxZ - minZ; sectionBox.Min = new XYZ( -2 * d, -1, 0 ); sectionBox.Max = new XYZ( 2 * d, h + 1, 5 ); return sectionBox; }