二次开发之梁随板

概述

梁随板是较为实用的工具,下面是能直接找到的找到的代码:
早先梁随板案例
这个代码实现的功能会发现与橄榄山插件做到的不一样,上述插件是利用坐标转换的方式得到原有梁到既定平面的投影。
这种投影法会出现梁水平方向的偏移

橄榄山插件做法

基本还原橄榄山插件做法,保留缺陷

方法代码

运用坐标转换的方法进行点到面的投影

查阅软件研发教材关于坐标转换章节的内容,理解坐标转换。

微调后的方法

微调内容是根据定位点分别做竖直点,再根据线与面的交点得到需求点,根据两个需求点将定位线做一个变更
下面的代码依旧保留了坐标转换以及投影线部分的内容,而没有用线与面的交点的方法,主要是为了保留一些投影线的案例,实际使用本代码时注意选择最优解。

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlignedBeamWPF
{
    /// <summary>
    /// 梁随斜板
    /// </summary>
    [Transaction(TransactionMode.Manual)]
    class Class1 : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            FloorISelection floorISelection = new FloorISelection();
            MainWindow wpf = new MainWindow();//实例化主窗口
            wpf.ShowDialog();//展示界面
            if (!wpf.IsClickClose)
            {
                return Result.Cancelled;
            }
            //【1】拾取楼板和梁
            Reference reference;
            try
            {
                reference = uidoc.Selection.PickObject(ObjectType.Element, floorISelection, "选择楼板");
            }
            catch
            {

                return Result.Succeeded;
            }
            BeamISelection beamISelection = new BeamISelection();
         IList<Reference> beamReferences =new List<Reference> ();
            try
            {
                beamReferences = uidoc.Selection.PickObjects(ObjectType.Element, beamISelection, "框选所需操作的梁");
            }
            catch
            {

                return Result.Succeeded;
            }
            List<ElementId> ids = new List<ElementId>();
            foreach (var item in beamReferences)
            {
                ElementId id = doc.GetElement(item).Id;
                ids.Add(id);
            }
            //【2】获得元素表面,根据交互选择确定是获取楼板底面,还是楼板顶面并偏移梁后距离的面
            //这里补充说明一下, 梁默认的定位线位置在梁顶部,如果单纯按照梁顶面求交点的方式,梁会埋没在板中间,与橄榄山插件的效果类似
            //按照实际工程需要这里对相对平面进行一个梁厚的偏移

          
            foreach (var id in ids)//注意修改数据需要将楼板参数放入循环内容里面,要不然会持续报错
            {

                Floor floor = doc.GetElement(reference) as Floor;
                double floorH = floor.LookupParameter("厚度").AsDouble();
                //获取几何表面
                Reference bottomFaceRef = HostObjectUtils.GetBottomFaces(floor).First();
                Reference GetTopFaceRef = HostObjectUtils.GetTopFaces(floor).First();
                Face GetTopFace = floor.GetGeometryObjectFromReference(GetTopFaceRef) as Face;
                Face bottomFace = floor.GetGeometryObjectFromReference(bottomFaceRef) as Face;
                FamilyInstance beam = doc.GetElement(id) as FamilyInstance;
                //梁高度
                //获取梁定位线
                LocationCurve beamLocation = beam.Location as LocationCurve;
                Line bLine = beamLocation.Curve as Line;
                //获取梁的两个端点
                XYZ pStart = bLine.GetEndPoint(0);
                XYZ pEnd = bLine.GetEndPoint(1);
                //通过两个端点做z方向直线,然后利用直线与面的交点求出对应位置的梁端点
                Line lStart = Line.CreateUnbound(pStart, XYZ.BasisZ);
                Line lEnd = Line.CreateUnbound(pEnd, XYZ.BasisZ);
                //与目标面相交的两个端点
                XYZ startPoint = null;
                XYZ endPoint = null;

                if (wpf.btnselect == false)  //交互界面选择为对齐底面时
                {
                    startPoint = IntersectPointOfFaceAndCurve(bottomFace, lStart);
                   
                  endPoint = IntersectPointOfFaceAndCurve(bottomFace, lEnd);
                }
                if (wpf.btnselect == true)//交互界面选择为对齐顶面时
                {
                    double h = beam.Symbol.LookupParameter("h").AsDouble();
                    startPoint = IntersectPointOfFaceAndCurve(bottomFace, lStart);
                    endPoint = IntersectPointOfFaceAndCurve(bottomFace, lEnd);
                    //获取顶面交点
                    XYZ startPoint2 = IntersectPointOfFaceAndCurve(GetTopFace, lStart);
                    XYZ endPoint2 = IntersectPointOfFaceAndCurve(GetTopFace, lEnd);
                    //相似三角形计算得出,这里就不用坐标转化了,坐标转化结果显示有问题,可能斜梁显示逻辑理解不对
                    startPoint = new XYZ(startPoint2.X, startPoint2.Y, (startPoint2.Z - startPoint.Z) * h / floorH + startPoint2.Z);
                    endPoint = new XYZ(endPoint2.X, endPoint2.Y, (endPoint2.Z - endPoint.Z) * h / floorH + endPoint2.Z);
                    进行坐标系转化,实现交点往平面法向方向顺延h的目的;
                    //PlanarFace planeFace = GetTopFace as PlanarFace;
                    顶面定位线坐标
                    //Transform tf = Transform.Identity;
                    //tf.BasisX = planeFace.XVector;
                    //tf.BasisY = planeFace.YVector;
                    //tf.BasisZ = planeFace.FaceNormal;
                    //tf.Origin = planeFace.Origin;
                    //XYZ p = tf.Inverse.OfPoint(startPoint);
                    //p = new XYZ(p.X, p.Y, h);
                    //startPoint = tf.OfPoint(p);

                    //XYZ p2 = tf.Inverse.OfPoint(endPoint);
                    //p2 = new XYZ(p2.X, p2.Y, h);
                    //endPoint = tf.OfPoint(p2);
                }

                if (startPoint == null || endPoint == null)
                {
                    TaskDialog.Show("提示信息", "梁超出附板范围,需手动调整");
                    return Result.Succeeded;
                }
                else
                {
                    Transaction transaction = new Transaction(doc, "梁随板");
                    transaction.Start();
                    beamLocation.Curve = Line.CreateBound(startPoint, endPoint);
                    transaction.Commit();
                }

            }
            return Result.Succeeded;
        }
        class FloorISelection : ISelectionFilter
        {
            public bool AllowElement(Element elem)
            {
                Categories categories = elem.Document.Settings.Categories;
                if ((elem is Floor && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_Floors).Id) || (elem is Floor && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_StructuralFoundation).Id))
                {
                    return true;
                }
                else
                {
                    return false;
                }
                ;//返回true时内容可被鼠标选定
            }
            public bool AllowReference(Reference reference, XYZ position)
            {
                return true;//返回true时表示内容可以被边、点、面选中
            }
        }
        class BeamISelection : ISelectionFilter
        {
            public bool AllowElement(Element elem)
            {
                Categories categories = elem.Document.Settings.Categories;
                if (elem is FamilyInstance && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_StructuralFraming).Id)
                {
                    return true;
                }
                else
                {
                    return false;
                }
                ;//返回true时内容可被鼠标选定
            }
            public bool AllowReference(Reference reference, XYZ position)
            {
                return true;//返回true时表示内容可以被边、点、面选中
            }
        }
        #region IntersectPointOfFaceAndCurve:求面与线的交点
        public XYZ IntersectPointOfFaceAndCurve(Face face, Curve curve)
        {
            //交点数组
            IntersectionResultArray result = null;
            //枚举,用于判断相交类型
            SetComparisonResult setResult = face.Intersect(curve, out result);
            XYZ interResult = null;
            //Disjoint为不相交
            if (SetComparisonResult.Disjoint != setResult)
            {
                //isEmpty判断是否为空
                if (!result.IsEmpty)

                    interResult = result.get_Item(0).XYZPoint;

            }
            return interResult;
        }
        #endregion
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值