从模型中选面绘线

在3D建模中,为实现从模型表面选取面进行造型的功能,经历三次尝试。首次尝试直接选取面绘线出现部分线条不在面上的问题。通过阅读网上前辈的文章进行优化,但问题依旧。最终采取折中方案,结合选取元素上的点判断是否在面上来绘制线条,达到满意效果。
摘要由CSDN通过智能技术生成

有个功能需要从模型中选面,做一些造型。
第一次:起初觉得很简单,使用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();

                        }
                    }
                }
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值