从模型中选面绘线

it2026-04-18  0

有个功能需要从模型中选面,做一些造型。 第一次:起初觉得很简单,使用sel.PickObject(ObjectType.Face)后发现存在问题:绘制的线有的在面上,有的不在面上,从face的属性看不出来任何规律。 第二次:上网搜到了一篇前辈的文章:https://blog.csdn.net/qq_34968766/article/details/82934915。觉得很有道理,抄过去之后,仍然存在同样问题。 第三次:折腾了半天,暂时找个折中的办法。采用 sel.PickObject(ObjectType.PointOnElement),判断点是不是在面上,若在就直接画线,若不在就采用上面那位前辈的方法。结果还可以。

using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using System; namespace IECOMMAND.Task { /// <summary> /// 从网上抄的选面画线,结果也不理想,会出现跑偏现象 /// </summary> [Transaction(TransactionMode.Manual)] class FaceToLine : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIDocument uidoc = commandData.Application.ActiveUIDocument; Document doc = uidoc.Document;//获取活动文档 Selection sel = uidoc.Selection; sel.PickObject(ObjectType.Face); Reference oneRR = sel.PickObject(ObjectType.PointOnElement); if (oneRR == null) return Result.Cancelled; Element e = doc.GetElement(oneRR); XYZ onePt = oneRR.GlobalPoint; PlanarFace face = doc.GetElement(oneRR).GetGeometryObjectFromReference(oneRR) as PlanarFace; IntersectionResult oneIR = face.Project(onePt); if (oneIR != null && oneIR.Distance == 0) { TaskDialog.Show("dd", "点在面上"); PtOnFace(doc, face); } else { TaskDialog.Show("dd", "点不在面上"); FamilyInstance fi = (FamilyInstance)e; Transaction trans = new Transaction(doc); FaceNewModelLine(doc, face, fi.GetTotalTransform()); } return Result.Succeeded; } /// <summary> /// 点在面上 /// </summary> /// <param name="doc"></param> /// <param name="face"></param> private static void PtOnFace(Document doc, PlanarFace face) { try { BRepBuilder breBuild = new BRepBuilder(BRepType.OpenShell); //先创建一个假面(不能直接用,每个面都需要添加至少一个循环边,带洞的面需要多个循环边) bool faceReverse = face.OrientationMatchesSurfaceOrientation ? false : true; BRepBuilderGeometryId faceId = breBuild.AddFace(BRepBuilderSurfaceGeometry.Create(face.GetSurface(), null), faceReverse); EdgeArrayArrayIterator edgeAAIter = face.OrientationMatchesSurfaceOrientation ? face.EdgeLoops.ForwardIterator() : face.EdgeLoops.ReverseIterator(); while (edgeAAIter.MoveNext()) { BRepBuilderGeometryId loopId = breBuild.AddLoop(faceId); EdgeArray edgeArr = (EdgeArray)edgeAAIter.Current; EdgeArrayIterator edgeIter = edgeArr.ForwardIterator(); while (edgeIter.MoveNext()) { Edge gg = (Edge)edgeIter.Current; BRepBuilderEdgeGeometry breEdge = BRepBuilderEdgeGeometry.Create(gg.AsCurveFollowingFace(face)); BRepBuilderGeometryId bEdgeId = breBuild.AddEdge(breEdge); breBuild.AddCoEdge(loopId, bEdgeId, false); } breBuild.FinishLoop(loopId); } breBuild.FinishFace(faceId); breBuild.Finish(); using (var ts = new Transaction(doc, "创建")) { ts.Start(); //使用体量的话,只能用面表示模板面积。好处是使用brepbuilder创建面对象比较简单。 var ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_Mass)); try { ds.SetShape(breBuild); ts.Commit(); } catch (Exception sdd) { TaskDialog.Show("dd", "set wrong\n" + sdd.Message); ts.Dispose(); } } } catch { TaskDialog.Show("dd", "build wrong"); } } //根据PlanarFace创建平面模型线 //考虑了trans变换,但是效果不理想 private void FaceNewModelLine(Document RevitDoc, PlanarFace face, Transform trans) { foreach (EdgeArray e in face.EdgeLoops) { foreach (Edge e2 in e) { if (e2.AsCurve() is Line) { Line line = (e2.AsCurve()) as Line;//因为怕存在Arc曲线无法转换 Plane plane = null; if (trans != null)//转换坐标 { plane = Plane.CreateByNormalAndOrigin(trans.OfVector(face.FaceNormal), trans.OfPoint(face.Origin)); XYZ xyz1 = line.GetEndPoint(0); XYZ xyz2 = line.GetEndPoint(1); line = Line.CreateBound(trans.OfPoint(xyz1), trans.OfPoint(xyz2)); } else { plane = Plane.CreateByNormalAndOrigin(face.FaceNormal, face.Origin); } using (Transaction transaction = new Transaction(RevitDoc)) { transaction.Start("Create Model Line"); //创建sketchPlane SketchPlane modelSketch = SketchPlane.Create(RevitDoc, plane); //创建模型线 RevitDoc.Create.NewModelCurve(line, modelSketch); transaction.Commit(); } } } } } } }

 

最新回复(0)