/// <summary> /// 根据选择的一个平面或者曲线来绘制一个面层对象 /// </summary> /// <param name="uiDoc"></param> /// <param name="options"></param> /// <returns></returns> private Result DrawFromOneFace(UIDocument uiDoc, FaceOptions options) { Result res = Result.Failed; // 在Revit界面中选择表面 Reference faceRef = SelectSurface(uiDoc, options); if (faceRef != null) { // 1. 选择的单元 Element struElement = _doc.GetElement(faceRef); // 2. 选择的表面 GeometryObject obj = struElement.GetGeometryObjectFromReference(faceRef); if (!(obj is Face)) { MessageBox.Show("未检测到选择的面!", "提示"); return(Result.Failed); } Face face = (Face)obj; // 3. 族实例对象的 变换 Transform transform = GetElementTransform(struElement); // ---------------------------------------------------------------------------------------------------- // 对不同的选择情况进行分类处理 using (Transaction tran = new Transaction(_doc, "在选择的面上生成面层")) { try { tran.Start(); // 根据不同的选择类型进行分类处理 if (face is PlanarFace) { PlanarFace pFace = (PlanarFace)face; // 对单元中所有同方向的面均进行绘制进行特殊处理 if (options.IncludeSameNormal) { IList <DirectShape> surfaces = ExtendToFacesWithSameNormal(tran, struElement, pFace, options, transform); // 设置面层对象的位置 ElementId[] ids = surfaces.Select(r => r.Id).ToArray(); uiDoc.Selection.SetElementIds(ids); } else // 对于一般的单元进行操作 { DirectShape ds = ConstructSurfaceFromPlanarFace(tran, pFace, options, transform); if (ds != null) { // 设置面层对象的位置 uiDoc.Selection.SetElementIds(new ElementId[] { ds.Id }); } } } else { // 将一个曲面转化为多个网格平面 SurfaceTriangulator st = new SurfaceTriangulator(face, transform); List <PlanarFace> planarFaces = st.GetMeshedFaces(); List <FaceTransform> faceTransforms = planarFaces.Select(r => new FaceTransform(r, Transform.Identity)).ToList(); // DirectShape ds = ConstructSurfaceFromPlanarFaces(tran, faceTransforms, options); // throw new InvalidOperationException("无法在不是平面的表面生成面层。"); } tran.Commit(); return(Result.Succeeded); } catch (Exception ex) { // Utils.ShowDebugCatch(ex, "生成面层出错。"); tran.RollBack(); throw new InvalidOperationException("生成面层出错。", ex); return(Result.Failed); } } } return(res); }
// 根据指定的类别与类型来进行面层对象的过滤 /// <summary> /// 从整个文档中的指定集合中 按指定的过滤选项 搜索面层对象 /// </summary> /// <param name="doc"></param> /// <param name="elementIds"> 如果其值为null,则表示过滤集合为整个文档中的所有单元 </param> /// <returns></returns> private IList <ElementId> Filterfaces(Document doc, ICollection <ElementId> elementIds, FaceOptions opt) { List <ElementId> faces = new List <ElementId>(); FilteredElementCollector coll; coll = (elementIds == null) ? new FilteredElementCollector(doc) : new FilteredElementCollector(doc, elementIds); // 首先判断类型 与 过滤指定的类别 coll.OfClass(typeof(DirectShape)).OfCategoryId(opt.CategoryId); // 跟据参数值进行过滤 string tag; foreach (Element ele in coll) { WallFace wallface; if (!WallFace.IsWallFace(ele as DirectShape, out wallface)) { continue; } // 2. 过滤面层类型,如“防水” bool hasType = wallface.GetFaceType(out tag); if (!hasType || tag == null || !tag.Equals(opt.FaceType, StringComparison.OrdinalIgnoreCase)) { continue; } // 满足所有过滤条件 faces.Add(ele.Id); } return(faces); }
/// <summary> /// 为面层实体设置颜色、类型等参数 /// </summary> /// <param name="tran"></param> /// <param name="ds"></param> /// <param name="volumn"></param> /// <param name="area"></param> /// <param name="faceOptions"></param> private void SetParameters(Transaction tran, DirectShape ds, double volumn, double area, FaceOptions faceOptions) { // 设置实体对象在指定视力中的填充颜色 OverrideGraphicSettings gs = _view.GetElementOverrides(ds.Id); // 填充颜色 gs.SetProjectionFillColor(faceOptions.Color); // 填充模式 string fillPatternName = "实体填充"; FillPatternElement fpe = FillPatternElement.GetFillPatternElementByName(_doc, FillPatternTarget.Drafting, fillPatternName); if (fpe == null) { fpe = FillPatternElement.Create(_doc, new FillPattern(fillPatternName, FillPatternTarget.Drafting, FillPatternHostOrientation.ToHost)); } gs.SetProjectionFillPatternId(fpe.Id); gs.SetProjectionFillPatternVisible(true); _view.SetElementOverrides(ds.Id, gs); // 设置参数 Parameter p; // 面层对象标识 p = ds.get_Parameter(FaceWallParameters.sp_FaceIdTag_guid); if (p != null) { p.Set(FaceWallParameters.FaceIdentificaion); } // 面积 p = ds.get_Parameter(FaceWallParameters.sp_Area_guid); if (p != null) { p.Set(area); } // 体积 p = ds.get_Parameter(FaceWallParameters.sp_Volumn_guid); if (p != null) { p.Set(volumn); } // 类型 p = ds.get_Parameter(FaceWallParameters.sp_FaceType_guid); if (p != null) { p.Set(faceOptions.FaceType); } }
/// <summary> /// 将多个平面生成为一个面层对象 /// </summary> /// <param name="docTran"> </param> /// <param name="faceTransforms"> 键表示用来生成面层的多个面,对应的值表示将 face 对象 转换到模型空间中所需要进行的变换 </param> /// <param name="faceOp"> 生成面层的选项 </param> /// <returns> 如果新生成的面层实体或者进行剪切后的实体体积太小,则认为不会生成此实体(在施工中也不可能考虑如此精细的施工),此时返回 null</returns> private DirectShape ConstructSurfaceFromPlanarFaces(Transaction docTran, List <FaceTransform> faceTransforms, FaceOptions faceOp) { IList <Solid> solids = new List <Solid>(); foreach (FaceTransform face_Transform in faceTransforms) { PlanarFace face = face_Transform.planarFace; Transform transform = face_Transform.transform; Solid solid = ExtrudeSolid(face, transform, faceOp.SurfaceThickness); solids.Add(solid); } docTran.SetName("通过多个平面来生成一个面层对象"); // create direct shape and assign the sphere shape DirectShape ds = DirectShape.CreateElement(_doc, faceOp.CategoryId, "Application id", "Geometry object id"); ds.SetShape(solids.Select(r => r as GeometryObject).ToList()); _doc.Regenerate(); bool reSetFace = false; // 是否要将当前的面层对象删除后再重新生成 bool hasIntersect; // 将初步生成的面层对象与周围的环境相剪切,并返回剪切后的实体集合。 // 集合中的Solid的体积可能为零,说明它已经被剪切掉了,但是其定义还在。 IList <Solid> extrudedSolids = ExcludeIntersect(ds, solids, out hasIntersect); // 在将此面层对象中的多个Solid进行组合之前,先获取到面层对象的面积 double area = 0; int index = 0; foreach (var faceTransform in faceTransforms) { PlanarFace f = faceTransform.planarFace; Transform transform = faceTransform.transform; // Solid solid = extrudedSolids[index]; if (solid.Volume > 0) { Face face = CorrespondFace(solid, f, transform); // area += face.Area; } // index += 1; } IList <Solid> finnalSolids; if (faceOp.UnionInnerSolids) { // 将此面层对象中的多个Solid进行组合,最后集合中就只包含一个用来Union的Solid,以及不能成功被Union的Solids。 finnalSolids = UnionSolid(extrudedSolids); } else { finnalSolids = extrudedSolids; } // 计算组合之后的最终面层的真实体积。 double volumn = finnalSolids.Sum(s => s.Volume); // 不管原来生成的面层对象与周围环境是否有相交,都删除原来的实体,并根据剪切后的实体重新创建 _doc.Delete(ds.Id); // create direct shape and assign the sphere shape ds = DirectShape.CreateElement(_doc, faceOp.CategoryId, "Application id", "Geometry object id"); ds.SetShape(finnalSolids.Select(r => r as GeometryObject).ToList()); // ds.SetShape(new GeometryObject[] { unionedSolid }); // 设置面层单元的各种参数 SetParameters(docTran, ds, volumn: volumn, area: area, faceOptions: faceOp); return(ds); }
/// <summary> /// 从单一平面来生成面层对象 /// </summary> /// <param name="face"> 用来生成面层的那个面 </param> /// <param name="faceOp"> 生成面层的选项 </param> /// <returns> 如果新生成的面层实体或者进行剪切后的实体体积太小,则认为不会生成此实体(在施工中也不可能考虑如此精细的施工),此时返回 null</returns> /// <param name="transform"> 从族几何到实例对象的变换 </param> private DirectShape ConstructSurfaceFromPlanarFace(Transaction docTran, PlanarFace face, FaceOptions faceOp, Transform transform) { Solid solid = ExtrudeSolid(face, transform, faceOp.SurfaceThickness); if (solid.Volume < 0.00001) { // 如果新生成的面层实体体积太小,则认为不会生成此实体(在施工中也不可能考虑如此精细的施工) return(null); } docTran.SetName("生成面层"); // create direct shape and assign the sphere shape DirectShape ds = DirectShape.CreateElement(_doc, faceOp.CategoryId, "Application id", "Geometry object id"); ds.SetShape(new GeometryObject[] { solid }); _doc.Regenerate(); // 判断生成的实体与周围的结构的相交关系 bool hasIntersect; IList <Solid> solids = ExcludeIntersect(ds, new Solid[] { solid }, out hasIntersect); if (hasIntersect) { if (!solids.Any()) { // 如果新生成的面层实体体积太小,则认为不会生成此实体(在施工中也不可能考虑如此精细的施工) _doc.Delete(ds.Id); return(null); } solid = solids.First(); // 删除原来的实体,并根据剪切后的实体重新创建 _doc.Delete(ds.Id); if (solid.Volume < 0.000001) { // 如果新生成的面层实体被剪切之后体积太小,则认为不会生成此实体(在施工中也不可能考虑如此精细的施工) return(null); } else { // create direct shape and assign the sphere shape ds = DirectShape.CreateElement(_doc, faceOp.CategoryId, "Application id", "Geometry object id"); ds.SetShape(new GeometryObject[] { solid }); } } PlanarFace pFace = CorrespondFace(solid, face, transform); // 设置面层单元的各种参数 SetParameters(docTran, ds, volumn: solid.Volume, area: pFace.Area, faceOptions: faceOp); return(ds); }
/// <summary> /// 将楼梯中所有与选择的表面相同方向的面上都生成面层 /// </summary> /// <param name="docTran"> </param> /// <param name="elem"> 用来生成面层的单元。此函数会搜索此单元中所有与 baseFace 同法向的面,并进行面层的绘制 </param> /// <param name="pickedFace"> 楼梯中用来生成面层的那个面</param> /// <param name="faceOp"> 生成面层的选项</param> /// <param name="transf"> </param> /// <returns></returns> private IList <DirectShape> ExtendToFacesWithSameNormal(Transaction docTran, Element elem, PlanarFace pickedFace, FaceOptions faceOp, Transform transf) { IList <DirectShape> directShapes = new List <DirectShape>(); // 值中的false 表示solid 是 Family中的solid,后期还要再进行一次transform才能变换 Familyinstance 所对应的位置 Dictionary <Solid, bool> solids = GeoHelper.GetSolidsInModel(elem, GeoHelper.SolidVolumnConstraint.Positive); foreach (Solid solid in solids.Keys) { foreach (Face face in solid.Faces) { if ((face is PlanarFace)) { PlanarFace planarFace = (PlanarFace)face; if (GeoHelper.IsSameDirection(planarFace.FaceNormal, transf.OfVector(pickedFace.FaceNormal))) { DirectShape ds = ConstructSurfaceFromPlanarFace(docTran, planarFace, faceOp, Transform.Identity); if (ds != null) { directShapes.Add(ds); } } } } } return(directShapes); }
/// <summary> /// 选择多个面,并将对应的多个面层绘制到一个DirectShape中 /// </summary> /// <param name="uiDoc"></param> /// <param name="options"></param> /// <returns></returns> private Result DrawOneElemWithFaces(UIDocument uiDoc, FaceOptions options) { Result res = Result.Failed; // 在Revit界面中选择表面 var faceRefs = SelectSurfaces(uiDoc, options); if (faceRefs != null && faceRefs.Count > 0) { // 提取每一个选择的表面,以及对应的单元的 Transform 对象 List <FaceTransform> faceTransforms = new List <FaceTransform>(); foreach (Reference faceRef in faceRefs) { // 1. 选择的单元 Element struElement = _doc.GetElement(faceRef); // 2. 选择的表面 GeometryObject obj = struElement.GetGeometryObjectFromReference(faceRef); // 3. 族实例对象的 变换 Transform transform = GetElementTransform(struElement); if (!(obj is PlanarFace)) { Face face = (Face)obj; // 将一个曲面转化为多个网格平面 SurfaceTriangulator st = new SurfaceTriangulator(face, transform); List <PlanarFace> planarFaces = st.GetMeshedFaces(); // 一个曲面所对应的所有平面网格 List <FaceTransform> ft = planarFaces.Select(r => new FaceTransform(r, Transform.Identity)).ToList(); // 将这一个曲面所对应的三角形平面集合添加到总的集合中 faceTransforms.AddRange(ft); } else { PlanarFace pFace = (PlanarFace)obj; faceTransforms.Add(new FaceTransform(pFace, transform)); } } // ---------------------------------------------------------------------------------------------------- // 对不同的选择情况进行分类处理 using (Transaction tran = new Transaction(_doc, "通过多个平面来生成一个面层对象")) { try { tran.Start(); DirectShape ds = ConstructSurfaceFromPlanarFaces(tran, faceTransforms, options); if (ds != null) { // 设置面层对象的位置 uiDoc.Selection.SetElementIds(new ElementId[] { ds.Id }); } tran.Commit(); return(Result.Succeeded); } catch (Exception ex) { // Utils.ShowDebugCatch(ex, "生成面层出错。"); tran.RollBack(); throw new InvalidOperationException("生成面层出错。", ex); // return Result.Failed; } } } return(res); }