Building Coder(Revit 二次开发) - 真实世界中的角坐标
2012-10-05 15:06
387 查看
原文链接: Real-World Concrete Corner Coordinates
我之前和人合作了一个很实用的程序:自动创建施工现场的位置点和结构元素。为了实现功能,我们必须首先解决如下几个 Revit 二次开发的问题:
1. 获取结构混凝土元素(Structural Concrete Elements);
2. 获取结构混凝土元素的角(通过它们的几何特征获取顶点);
3. 将 Revit 模型坐标转换为真实世界坐标
获取结构混凝土元素
我们已经在 retrieving structural elements (http://thebuildingcoder.typepad.com/blog/2010/07/retrieve-structural-elements.html) 中讨论了如何获取结构元素。这里我们需要的是结构混凝土元素,所以我们还必须添加两个结构材质类型过滤器:混凝土和预制混凝土。
访问几何数据获取顶点
得到了指定的元素之后,我们就可以通过分析它们的几何特征来获取所有的(即几何顶点)。为了保证得到的顶点没有重复,我们首先需要为顶点(Autodesk.Revit.DB.XYZ)定义一个比较器。
接下来就可以从元素的几何实体 (Autodesk.Revit.DB.Solid) 中获取所有的顶点了。
遍历元素的几何数据,并且将第一个非空的几何数据作为 Solid 对象。
族实例需要特殊的处理,因为它们有一个额外的转换。族定义了一个其自身的坐标系统,我们需要将 Solid 对象从族坐标系统转换到 Revit 模型坐标系统。以下代码能够处理所有的情况:
得到了相对 Revit 模型坐标系的所有顶点之后,我们还需要通过项目位置(Project Location)将它们转换成真实世界坐标。代码如下:
最后,使用转换就变得很简单了:
我之前和人合作了一个很实用的程序:自动创建施工现场的位置点和结构元素。为了实现功能,我们必须首先解决如下几个 Revit 二次开发的问题:
1. 获取结构混凝土元素(Structural Concrete Elements);
2. 获取结构混凝土元素的角(通过它们的几何特征获取顶点);
3. 将 Revit 模型坐标转换为真实世界坐标
获取结构混凝土元素
我们已经在 retrieving structural elements (http://thebuildingcoder.typepad.com/blog/2010/07/retrieve-structural-elements.html) 中讨论了如何获取结构元素。这里我们需要的是结构混凝土元素,所以我们还必须添加两个结构材质类型过滤器:混凝土和预制混凝土。
/// <summary> /// Retrieve all structural elements that we are /// interested in using to define setout points. /// We are looking at concrete for the moment. /// This includes: columns, framing, floors, /// foundations, ramps, walls. /// </summary> FilteredElementCollector GetStructuralElements( Document doc ) { BuiltInCategory[] bics = new BuiltInCategory[] { BuiltInCategory.OST_StructuralColumns, BuiltInCategory.OST_StructuralFraming, BuiltInCategory.OST_StructuralFoundation, BuiltInCategory.OST_Floors, BuiltInCategory.OST_Ramps }; IList<ElementFilter> a = new List<ElementFilter>( bics.Length ); foreach( BuiltInCategory bic in bics ) { a.Add( new ElementCategoryFilter( bic ) ); } LogicalOrFilter categoryFilter = new LogicalOrFilter( a ); // 使用材质过滤器添加混凝土或者预制混凝土的条件 List<ElementFilter> b = new List<ElementFilter>( 2 ); b.Add( new StructuralMaterialTypeFilter( StructuralMaterialType.Concrete ) ); b.Add( new StructuralMaterialTypeFilter( StructuralMaterialType.PrecastConcrete ) ); LogicalOrFilter structuralMaterialFilter = new LogicalOrFilter( b ); List<ElementFilter> c = new List<ElementFilter>( 3 ); c.Add( new ElementClassFilter( typeof( FamilyInstance ) ) ); c.Add( structuralMaterialFilter ); c.Add( categoryFilter ); LogicalAndFilter familyInstanceFilter = new LogicalAndFilter( c ); IList<ElementFilter> d = new List<ElementFilter>( 6 ); d.Add( new ElementClassFilter( typeof( Wall ) ) ); d.Add( new ElementClassFilter( typeof( Floor ) ) ); #if NEED_LOADS d.Add( new ElementClassFilter(typeof( PointLoad ) ) ); d.Add( new ElementClassFilter(typeof( LineLoad ) ) ); d.Add( new ElementClassFilter(typeof( AreaLoad ) ) ); #endif d.Add( familyInstanceFilter ); LogicalOrFilter classFilter = new LogicalOrFilter( d ); FilteredElementCollector col = new FilteredElementCollector( doc ) .WhereElementIsNotElementType() .WherePasses( classFilter ); return col; }
访问几何数据获取顶点
得到了指定的元素之后,我们就可以通过分析它们的几何特征来获取所有的(即几何顶点)。为了保证得到的顶点没有重复,我们首先需要为顶点(Autodesk.Revit.DB.XYZ)定义一个比较器。
class XyzEqualityComparer : IEqualityComparer<XYZ> { const double _sixteenthInchInFeet = 1.0 / ( 16.0 * 12.0 ); public bool Equals( XYZ p, XYZ q ) { return p.IsAlmostEqualTo( q, _sixteenthInchInFeet ); } public int GetHashCode( XYZ p ) { return PointString( p ).GetHashCode(); } }
接下来就可以从元素的几何实体 (Autodesk.Revit.DB.Solid) 中获取所有的顶点了。
/// <summary> /// 在 Revit 中,一个圆由两段弧组成,每段弧的两个顶点中只会返回一个。 /// </summary> Dictionary<XYZ,int> GetCorners( Solid solid ) { Dictionary<XYZ, int> corners = new Dictionary<XYZ, int>( new XyzEqualityComparer() ); foreach( Face f in solid.Faces ) { foreach( EdgeArray ea in f.EdgeLoops ) { foreach( Edge e in ea ) { XYZ p = e.AsCurveFollowingFace( f ).get_EndPoint( 0 ); if( !corners.ContainsKey( p ) ) { corners[p] = 0; } ++corners[p]; } } } return corners; }
遍历元素的几何数据,并且将第一个非空的几何数据作为 Solid 对象。
族实例需要特殊的处理,因为它们有一个额外的转换。族定义了一个其自身的坐标系统,我们需要将 Solid 对象从族坐标系统转换到 Revit 模型坐标系统。以下代码能够处理所有的情况:
Solid GetSolid( Element e, Options opt ) { GeometryElement geo = e.get_Geometry( opt ); Solid solid = null; GeometryInstance inst = null; Transform t = Transform.Identity; // 有些柱子没有几何实体,我们必须从族类型中获取 // 有些有族实例本身有实体,但是没有几何实体 foreach( GeometryObject obj in geo ) { solid = obj as Solid; if( null != solid && 0 < solid.Faces.Size ) { break; } inst = obj as GeometryInstance; } if( null == solid && null != inst ) { geo = inst.GetSymbolGeometry(); t = inst.Transform; foreach( GeometryObject obj in geo ) { solid = obj as Solid; if( null != solid && 0 < solid.Faces.Size ) { break; } } } return solid; }
得到了相对 Revit 模型坐标系的所有顶点之后,我们还需要通过项目位置(Project Location)将它们转换成真实世界坐标。代码如下:
Transform GetProjectLocationTransform( Document doc ) { // 获取项目原点位置 ProjectPosition projectPosition = doc.ActiveProjectLocation.get_ProjectPosition( XYZ.Zero ); // 项目原点对应向量 XYZ translationVector = new XYZ( projectPosition.EastWest, projectPosition.NorthSouth, projectPosition.Elevation ); Transform translationTransform = Transform.get_Translation( translationVector ); // 项目旋转转换 Transform rotationTransform = Transform.get_Rotation( XYZ.Zero, XYZ.BasisZ, projectPosition.Angle ); // 组合项目原点转换和旋转转换 Transform finalTransform = translationTransform.Multiply( rotationTransform ); return finalTransform; }
最后,使用转换就变得很简单了:
Transform projectLocationTransform = GetProjectLocationTransform( doc ); for each concrete corner point XYZ p: { XYZ r2 = projectLocationTransform.OfPoint( p ); }
相关文章推荐
- Building Coder(Revit 二次开发) - 布尔操作和 InstanceVoidCutUtils
- Building Coder(Revit 二次开发) - NewFamilyInstance() 重载版本的选择
- Building Coder(Revit 二次开发) - 临时事务的使用技巧
- Building Coder(Revit 二次开发) - 可扩展存储
- Building Coder(Revit 二次开发) - 改变元素类型
- Building Coder(Revit 二次开发) - 拖放API
- Building Coder(Revit 二次开发) - 为一个共享参数绑定添加一个类别
- Building Coder(Revit 二次开发) - 拓扑表面(Toposurface)内部和边界点
- Building Coder(Revit 二次开发) - 针对视图和阶段进行过滤
- Building Coder(Revit 二次开发) - 改变剖视图的视图类型并且隐藏切割线
- Building Coder(Revit 二次开发)- 在两条线之间创建尺寸
- Building Coder(Revit 二次开发)- 关于楼板边界的重新思考
- Building Coder(Revit 二次开发) - 在一个倾斜的面上创建墙
- Building Coder(Revit 二次开发) - 失败处理API(上)
- Building Coder(Revit 二次开发)- 在新建族中进行镜像操作,并切换当前视图
- Building Coder(Revit 二次开发) - 分解DWG文件
- Building Coder(Revit 二次开发) - 内置参数名称和LabelUtils类
- Building Coder(Revit 二次开发) - 放置族实例
- Building Coder(Revit 二次开发) - 失败回滚(Failure Rollback)
- Building Coder(Revit 二次开发) - 组合使用 Revit 和 Vault