revit二次开发一键给梁,墙和楼板开洞添加套管

初步代码和思路还需要完善与X轴有夹角的情况,套管尺寸和洞的尺寸参照套管图集02S404,已完善旋转问题
效果
namespace OpeningHole
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
[Journaling(JournalingMode.NoCommandData)]
public class Class1 : IExternalCommand
{
string path = @“C:\Users\Administrator\source\repos\OpeningHole\Resources\刚性套管A-DN50-DN2000.rfa”;
string holePath = @“C:\Users\Administrator\source\repos\OpeningHole\Resources\墙圆形洞口.rfa”;
string holePathTable = @“C:\Users\Administrator\source\repos\OpeningHole\Resources\洞口尺寸对照表.csv”;
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{

        UIDocument uIDocument = commandData.Application.ActiveUIDocument;
        Document document = uIDocument.Document;
        Reference element = uIDocument.Selection.PickObject(ObjectType.Element, "选择要开洞的管线");
        Pipe pipe = document.GetElement(element) as Pipe;
        if (pipe == null)
        {
            return Result.Cancelled;
        }

        Dictionary<Element, XYZ> pointXYZ = GetCenterPoint(document, pipe);

        using (Transaction tr = new Transaction(document, "载入套管族"))
        {
            tr.Start();
            Bushing(document, pointXYZ, pipe);
            tr.Commit();
        }

        return Result.Succeeded;
    }
    /// <summary>
    /// 放置墙洞口,并设置参数
    /// </summary>
    /// <param name="doc"></param>
    /// <param name="filePath"></param>
    /// <param name="pipeDiameter"></param>
    /// <param name="pipeHeight"></param>
    /// <param name="pipeDiameterD"></param>
    /// <param name="level"></param>
    /// <param name="pointXYZ"></param>
    private void WallOpeningHole(Document doc, string filePath, string pipeDiameter, double pipeHeight, double pipeDiameterD, Level level, Element element, XYZ point)
    {
        Family holeFamily = LoadFamily(doc, holePath);
        FamilySymbol holeFamilySymbol = GetFamilySymbol(doc, holeFamily);
        holeFamilySymbol.Activate();
        try
        {
            FamilyInstance holeFamilyInstance = doc.Create.NewFamilyInstance(point, holeFamilySymbol, element, level, StructuralType.NonStructural);
            Parameter holeParameter = holeFamilyInstance.LookupParameter("R");
            double RValue = CsvReader(holePathTable, pipeDiameter) / 2 / 304.8;
            holeParameter.Set(RValue);
            Parameter holeHeight = holeFamilyInstance.LookupParameter("相对标高的偏移");
            double t = pipeHeight - RValue;
            holeHeight.Set(t);
        }
        catch (Exception ex)
        {
            TaskDialog.Show("Revit", $"{ex.Message}");
        }
    }
    /// <summary>
    /// 查找套管开洞尺寸对照表
    /// </summary>
    /// <param name="path"></param>
    /// <param name="searchValue">150mm</param>
    /// <returns></returns>
    private double CsvReader(string path, string searchValue)
    {
        string str = searchValue.Substring(0, searchValue.Length - 2).Trim();
        try
        {
            using (StreamReader reader = new StreamReader(path))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] values = line.Split(",");
                    if (values[0] == str)
                    {
                        return Convert.ToDouble(values[1]);
                    }
                }
            }
        }
        catch (Exception e)
        {
            TaskDialog.Show("Error", $"读取CSV文件时出错: {e.Message}");
        }
        return -1.0;
    }
    /// <summary>
    /// 放置套管和开洞
    /// </summary>
    /// <param name="document"></param>
    /// <param name="pointXYZ"></param>
    /// <param name="pipe"></param>
    private void Bushing(Document document, Dictionary<Element, XYZ> pointXYZ, Pipe pipe)
    {
        Family family = LoadFamily(document, path);//载入套管族
        FamilySymbol familySymbol = GetFamilySymbol(document, family);//套管的族类型
        familySymbol.Activate();
        double pipeDiameter = pipe.Diameter;//获取管道直径
        ElementId levelID = pipe.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId();
        Level level = document.GetElement(levelID) as Level;
        string pipeDiameterStr = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsValueString();
        double pipeHeight = pipe.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).AsDouble();
        try
        {
            foreach (var item in pointXYZ)
            {
                familySymbol.Activate();
                FamilyInstance familyInstance = document.Create.NewFamilyInstance(item.Value, familySymbol, StructuralType.NonStructural);//放置套管

                Parameter parameter = familyInstance.LookupParameter("公称尺寸");
                parameter.Set(pipeDiameter);//设置套管尺寸

                Element instance = item.Key;//与管道碰撞的墙或者梁实例
                if (instance.Category.Name == "墙")
                {
                    double wallThickness = (instance as Wall).Width;
                    Parameter length = familyInstance.LookupParameter("套管长度");
                    //length.Set(UnitUtils.ConvertFromInternalUnits(wallThickness, UnitTypeId.Millimeters));
                    length.Set(wallThickness);//设置套管长度
                    Line axis = Line.CreateBound(item.Value, new XYZ(item.Value.X, item.Value.Y, item.Value.Z + 1));
                    double angle = PipeToXAngle(pipe);
                    ElementTransformUtils.RotateElement(document, familyInstance.Id, axis, angle);//设置套管旋转角度
                    WallOpeningHole(document, holePath, pipeDiameterStr, pipeHeight, pipeDiameter, level, item.Key, item.Value);
                }
                else if (instance.Category.Name == "楼板")
                {
                    double RValue = CsvReader(holePathTable, pipeDiameterStr) / 2 / 304.8;
                    Arc arc = Arc.Create(item.Value, RValue, 0, 2 * Math.PI, XYZ.BasisX, XYZ.BasisY);
                    CurveArray curveArray = new CurveArray();
                    curveArray.Append(arc);
                    document.Create.NewOpening(instance, curveArray, true);
                    Line axis = Line.CreateBound(item.Value, new XYZ(item.Value.X, item.Value.Y + 1, item.Value.Z));
                    ElementTransformUtils.RotateElement(document, familyInstance.Id, axis, Math.PI / 2);
                    Parameter length = familyInstance.LookupParameter("套管长度");
                    double floorHeight = instance.get_Parameter(BuiltInParameter.FLOOR_ATTR_THICKNESS_PARAM).AsDouble();
                    length.Set(floorHeight);//获取楼板的厚度
                }
                else if (instance.Category.Name == "结构框架")
                {
                    double RValue = CsvReader(holePathTable, pipeDiameterStr) / 2 / 304.8;
                    Arc arc = Arc.Create(item.Value, RValue, 0, 2 * Math.PI, XYZ.BasisX, XYZ.BasisZ);
                    CurveArray curveArray = new CurveArray();
                    curveArray.Append(arc);
                    FamilyInstance beamInstance = instance as FamilyInstance;
                    Parameter length = familyInstance.LookupParameter("套管长度");
                    double b = beamInstance.Symbol.LookupParameter("b").AsDouble();
                    TaskDialog.Show("Revit", $"{b}");
                    //document.Create.NewOpening(instance, curveArray, Autodesk.Revit.Creation.eRefFace.CenterY);
                    length.Set(b);
                    double angle = PipeToXAngle(pipe);
                    Line axis = Line.CreateBound(item.Value, new XYZ(item.Value.X, item.Value.Y, item.Value.Z + 1));
                    ElementTransformUtils.RotateElement(document, familyInstance.Id, axis, angle);//设置套管旋转角度
                    document.Create.NewOpening(instance, curveArray, Autodesk.Revit.Creation.eRefFace.CenterY);
                    TaskDialog.Show("Revit", "{梁}");
                }
            }
        }
        catch (Exception e)
        {
            TaskDialog.Show("Revit", $"放置族失败{e.Message}");
        }
    }
    /// <summary>
    /// 获取套管的族实例
    /// </summary>
    /// <param name="document"></param>
    /// <param name="family"></param>
    /// <returns></returns>
    private FamilySymbol GetFamilySymbol(Document document, Family family)
    {
        FilteredElementCollector col = new FilteredElementCollector(document);
        FamilySymbol familySymbol = col.OfClass(typeof(FamilySymbol)).Cast<FamilySymbol>().FirstOrDefault(fs => fs.Name == family.Name);
        return familySymbol;
    }
    /// <summary>
    /// 获取与管道碰撞的墙
    /// </summary>
    /// <param name="document"></param>
    /// <param name="pipe"></param>
    /// <returns></returns>
    private List<Element> GetIntersectsWall(Document document, Pipe pipe)
    {
        FilteredElementCollector cols = new FilteredElementCollector(document);
        ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(pipe);
        ElementCategoryFilter Cfilter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);
        LogicalAndFilter logicalAndFilter = new LogicalAndFilter(elementIntersectsElementFilter, Cfilter);
        return cols.WherePasses(logicalAndFilter).ToList();
    }
    /// <summary>
    /// 获取与管道碰撞的楼板
    /// </summary>
    /// <param name="document"></param>
    /// <param name="pipe"></param>
    /// <returns></returns>
    private List<Element> GetIntersectFloor(Document document, Pipe pipe)
    {
        FilteredElementCollector cols = new FilteredElementCollector(document);
        ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(pipe);
        ElementCategoryFilter Cfilter = new ElementCategoryFilter(BuiltInCategory.OST_Floors);
        LogicalAndFilter logicalAndFilter = new LogicalAndFilter(elementIntersectsElementFilter, Cfilter);
        return cols.WherePasses(logicalAndFilter).ToList();
    }
    /// <summary>
    /// 获取与管道碰撞的梁
    /// </summary>
    /// <param name="document"></param>
    /// <param name="pipe"></param>
    /// <returns></returns>
    private List<Element> GetIntersectBeam(Document document, Pipe pipe)
    {
        FilteredElementCollector cols = new FilteredElementCollector(document);
        ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(pipe);
        ElementCategoryFilter Cfilter = new ElementCategoryFilter(BuiltInCategory.OST_StructuralFraming);
        LogicalAndFilter logicalAndFilter = new LogicalAndFilter(elementIntersectsElementFilter, Cfilter);
        return cols.WherePasses(logicalAndFilter).ToList<Element>();
    }
    /// <summary>
    /// 获取与管线碰撞的元素和中心点
    /// </summary>
    /// <param name="doc"></param>
    /// <param name="pipe"></param>
    /// <returns></returns>
    private Dictionary<Element, XYZ> GetCenterPoint(Document doc, Pipe pipe)
    {
        List<Element> element1 = GetIntersectsWall(doc, pipe);
        List<Element> element2 = GetIntersectFloor(doc, pipe);
        List<Element> element3 = GetIntersectBeam(doc, pipe);
        List<Element> elements = new List<Element>();
        elements.AddRange(element1);
        elements.AddRange(element2);
        elements.AddRange(element3);

        //List<XYZ> centerPoint = new List<XYZ>();
        List<XYZ> point = new List<XYZ>();
        Dictionary<Element, XYZ> intersectElementAndPoint = new Dictionary<Element, XYZ>();

        try
        {
            foreach (Element item in elements)
            {
                point.Clear();
                point = Get_Intersection(GetCurve(pipe), GetFace(item));
                XYZ centerPoint = new XYZ((point[0].X + point[1].X) / 2,
                    (point[0].Y + point[1].Y) / 2, (point[0].Z + point[1].Z) / 2);
                intersectElementAndPoint.Add(item, centerPoint);
            }
        }
        catch (Exception)
        {
            TaskDialog.Show("Revit", "未找到与选择管线碰撞的墙,梁和楼板");
        }
        return intersectElementAndPoint;
    }
    private Curve GetCurve(Pipe pipe)
    {
        Curve curve = null;
        LocationCurve locationCurve = pipe.Location as LocationCurve;
        if (locationCurve != null)
        {
            curve = locationCurve.Curve;
        }
        return curve;
    }

    /// <summary>
    /// 获取梁或者墙的表面
    /// </summary>
    /// <param name="element"></param>
    /// <returns></returns>
    private List<Face> GetFace(Element element)
    {
        Options opt = new Options { ComputeReferences = true, DetailLevel = ViewDetailLevel.Fine };
        GeometryElement geometryElement = element.get_Geometry(opt);
        List<Face> faces = new List<Face>();

        foreach (GeometryObject item in geometryElement)
        {
            if (item is Solid)
            {
                Solid solid = item as Solid;
                if (solid != null && solid.Faces.Size > 0)
                {
                    foreach (Face soliFace in solid.Faces)
                    {
                        PlanarFace planarFace = soliFace as PlanarFace;
                        if (planarFace != null)
                        {
                            faces.Add(planarFace);
                        }

                    }
                }
            }
            else if (item is GeometryInstance)
            {
                GeometryInstance instance = item as GeometryInstance;
                if (instance != null)
                {
                    GeometryElement ge = instance.GetInstanceGeometry();
                    foreach (GeometryObject go in ge)
                    {
                        Solid solid = go as Solid;
                        if (solid != null && solid.Faces.Size > 0)
                        {
                            foreach (Face face in solid.Faces)
                            {
                                PlanarFace planarFace = face as PlanarFace;
                                if (planarFace != null)
                                {
                                    faces.Add(planarFace);
                                }
                            }
                        }
                    }
                }
            }
        }
        return faces;
    }
    /// <summary>
    /// 获取管道与面的交点
    /// </summary>
    /// <param name="pipeLine"></param>
    /// <param name="listFace"></param>
    /// <returns></returns>
    public List<XYZ> Get_Intersection(Curve pipeLine, List<Face> listFace)
    {
        List<XYZ> lstIntersection = new List<XYZ>();
        foreach (Face item in listFace)
        {
            XYZ ptJd = CaculateIntersection(item, pipeLine);
            if (ptJd != null)
            {
                lstIntersection.Add(ptJd);
            }
        }
        return lstIntersection;
    }
    /// <summary>
    /// 计算线与面的交点
    /// </summary>
    /// <param name="face"></param>
    /// <param name="curve"></param>
    /// <returns></returns>
    private XYZ CaculateIntersection(Face face, Curve curve)
    {
        XYZ intersection = null;
        try
        {
            IntersectionResultArray resultArray = new IntersectionResultArray();
            SetComparisonResult setComparisonResult = face.Intersect(curve, out resultArray);
            if (SetComparisonResult.Disjoint != setComparisonResult && resultArray != null)
            {
                if (!resultArray.IsEmpty)
                {
                    intersection = resultArray.get_Item(0).XYZPoint;
                }
            }
        }
        catch (Exception ex)
        { }
        return intersection;
    }
    private double PipeToXAngle(Pipe pipe)
    {
        Curve curve = GetCurve(pipe);

Line line = curve as Line;
XYZ direction = line.Direction;
// 获取管道方向向量与X轴的夹角
double angleToXAxis = XYZ.BasisX.AngleTo(direction);
if (direction.Y<0)
{
return 2 * Math.PI - angleToXAxis;
}
return angleToXAxis;
}
#region 载入族
private Family LoadFamily(Document doc, string path)
{
Family family = IsFamilyInFile(doc, path);
if (family == null)
{
bool loadResult = doc.LoadFamily(path, out family);
if (loadResult)
{
return family;
}
else
{
TaskDialog.Show(“载入族”, $“族 ‘{family.Name}’ 载入失败。”);
}
}
return family;
}
private Family IsFamilyInFile(Document doc, string path)
{
Family family = null;
string name = Path.GetFileNameWithoutExtension(path);//不带文件后缀
FilteredElementCollector elements = new FilteredElementCollector(doc);
List familys = elements.OfClass(typeof(Family)).Cast().ToList();
foreach (Family item in familys)
{
if (item.Name == name)
{
family = item;
break;
}
}
return family;
}
#endregion

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值