zhangyuekai
2024-08-08 1e66b4cc1183f30ff6add72750f3e9e155ff7f9a
HStation.RevitDev/RevitDataExport/Utility/DocumentUtil.cs
@@ -1,195 +1,371 @@
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using HStation.RevitDev.Model.ModelEnum;
using HStation.RevitDev.RevitDataExport.Common;
using System;
using System.Collections.Generic;
namespace HStation.RevitDev.RevitDataExport.Utility
{
    public class DocumentUtil
    {
        public static void RegistDocumentEvent(Application app)
        {
            app.DocumentChanged -= App_DocumentChanged;
            app.DocumentChanged += App_DocumentChanged;
        }
        private static void App_DocumentChanged(object sender, DocumentChangedEventArgs e)
        {
            var doc = e.GetDocument();
            var addedIds = e.GetAddedElementIds();
            var removeIds = e.GetDeletedElementIds();
            var modifiedIds = e.GetModifiedElementIds();
            bool instancePlacing = GlobalResource.InstancePlacing;
            bool pipePlacing = GlobalResource.PipePlacing;
            if (pipePlacing)
            {
                foreach (var id in addedIds)
                {
                    var elem = doc.GetElement(id);
                    if (elem is FamilyInstance fi)
                    {
                        AddAutoCreated(fi);
                    }
                    if (elem is Pipe)
                    {
                        GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                        AddManualCreated(elem);
                    }
                }
            }
            else if (instancePlacing)
            {
                foreach (var id in addedIds)
                {
                    var elem = doc.GetElement(id);
                    if (elem is FamilyInstance)
                    {
                        GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                        AddManualCreated(elem);
                    }
                }
            }
            else
            {
                bool isPumpSystemElement = false;
                foreach (var id in addedIds)
                {
                    if (IsConnectedWithPumpSystem(doc, id))
                    {
                        isPumpSystemElement = true;
                    }
                }
                if (isPumpSystemElement)
                {
                    foreach (var id in addedIds)
                    {
                        AddToPumpSystem(doc, id);
                    }
                }
            }
            foreach (var id in removeIds)
            {
                if (GlobalResource.ElementIds.Contains(id.IntegerValue.ToString()))
                {
                    GlobalResource.ElementIds.Remove(id.IntegerValue.ToString());
                    TaskDialog.Show("提示", "删除元素:" + id.IntegerValue.ToString());
                }
            }
            foreach (var id in modifiedIds)
            {
                if (GlobalResource.ElementIds.Contains(id.IntegerValue.ToString()))
                {
                }
            }
        }
        private static bool IsConnectedWithPumpSystem(Document doc, ElementId id)
        {
            var elem = doc.GetElement(id);
            if (elem is Pipe pipe) //直接点击水泵的连接件创建管道
            {
                if (pipe.ConnectWithPumpSystem())
                {
                    //GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                    //TaskDialog.Show("提示", "增加管道:" + id.IntegerValue.ToString());
                    //AddManualCreated(elem);
                    return true;
                }
            }
            else if (elem is FamilyInstance fi)
            {
                if (fi.ConnectWithPumpSystem()) //直接点击管道连接点创建管道时,Revit会自动创建弯头,都需要加入到缓存
                {
                    //GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                    //TaskDialog.Show("提示", "增加族实例:" + id.IntegerValue.ToString());
                    //AddManualCreated(elem);
                    return true;
                }
            }
            return false;
        }
        private static void AddToPumpSystem(Document doc, ElementId id)
        {
            var elem = doc.GetElement(id);
            if (elem is Pipe)
            {
                GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                AddToMap(elem, RevitType.RFT_Pipe);
            }
            else if (elem is FamilyInstance fi)
            {
                GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                AddAutoCreated(fi);
            }
            return;
        }
        private static void AddAutoCreated(FamilyInstance fi)
        {
            var id = fi.Id;
            GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
            if (fi.IsWanTou())
            {
                AddToMap(fi, RevitType.RFT_Elbow);
            }
            else if (fi.IsSanTong())
            {
                AddToMap(fi, RevitType.RFT_ThreeJoint);
            }
            else if (fi.IsSiTong())
            {
                AddToMap(fi, RevitType.RFT_FourJoint);
            }
            else
            {
                TaskDialog.Show("警告", $"未知类型被添加!id:{fi.Id.IntegerValue}");
                //报错
            }
        }
        private static void AddManualCreated(Element elem)
        {
            var id = elem.Id.IntegerValue.ToString();
            if (!GlobalResource.RevitModels.ContainsKey(GlobalResource.RevitFamilyType))
            {
                GlobalResource.RevitModels.Add(GlobalResource.RevitFamilyType, new List<string>());
                GlobalResource.RevitModels[GlobalResource.RevitFamilyType].Add(id);
                TaskDialog.Show("提示", "增加族实例:" + id);
            }
            else if(!GlobalResource.RevitModels[GlobalResource.RevitFamilyType].Contains(id))
            {
                GlobalResource.RevitModels[GlobalResource.RevitFamilyType].Add(id);
                TaskDialog.Show("提示", "增加族实例:" + id);
            }
        }
        private static void AddToMap(Element elem, RevitType revitType)
        {
            var id = elem.Id.IntegerValue.ToString();
            if (!GlobalResource.RevitModels.ContainsKey(revitType))
            {
                GlobalResource.RevitModels.Add(revitType, new List<string>());
                GlobalResource.RevitModels[revitType].Add(id);
                TaskDialog.Show("提示", "增加族实例:" + id);
            }
            else if (!GlobalResource.RevitModels[revitType].Contains(id))
            {
                GlobalResource.RevitModels[revitType].Add(id);
                TaskDialog.Show("提示", "增加族实例:" + id);
            }
        }
    }
}
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
using DevExpress.Utils.Extensions;
using HStation.RevitDev.Model.ModelEnum;
using HStation.RevitDev.RevitDataExport.Common;
using HStation.RevitDev.RevitDataExport.Entity;
using HStation.RevitDev.RevitDataExport.Service;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using static DevExpress.Data.Mask.Internal.RegExMaskMath.CloudOfInts;
namespace HStation.RevitDev.RevitDataExport.Utility
{
    public static class DocumentUtil
    {
        public static void RegistDocumentEvent(ExternalCommandData commandData)
        {
            commandData.Application.Application.DocumentChanged -= App_DocumentChanged;
            commandData.Application.Application.DocumentChanged += App_DocumentChanged;
            GlobalResource.CurrentUIDocument = commandData.Application.ActiveUIDocument;
            RegistViewEvent(commandData);
        }
        private static void App_DocumentChanged(object sender, DocumentChangedEventArgs e)
        {
            var doc = e.GetDocument();
            try
            {
                var addedIds = e.GetAddedElementIds();
                var removeIds = e.GetDeletedElementIds();
                var modifiedIds = e.GetModifiedElementIds();
                AddElements(doc,  addedIds);
                RemoveElements(removeIds);
                ModifyElements(modifiedIds);
                UpdateLinkerInfo(doc);
                GlobalResource.InstancePanel.UpdateForm();
            }
            catch (Exception ex)
            {
                TaskDialog.Show("错误", ex.Message);
            }
        }
        private static void UpdateLinkerInfo(Document doc)
        {
            foreach (var pair in GlobalResource.RevitModels)
            {
                foreach (var model in pair.Value)
                {
                    var id = model.Id;
                    var element = doc.GetElement(new ElementId(int.Parse(id)));
                    var linkedElems = element.GetConnectElements();
                    var linkedIds = linkedElems.Select(x => x.Id.IntegerValue.ToString());
                    model.LinkIds = string.Join(",", linkedIds);
                }
            }
        }
        private static void ModifyElements(ICollection<ElementId> modifiedIds)
        {
            foreach (var id in modifiedIds)
            {
                if (GlobalResource.ElementIds.Contains(id.IntegerValue.ToString()))
                {
                }
            }
        }
        private static void RemoveElements(ICollection<ElementId> removeIds)
        {
            foreach (var id in removeIds)
            {
                var strId = id.IntegerValue.ToString();
                if (GlobalResource.ElementIds.Contains(strId))
                {
                    GlobalResource.ElementIds.Remove(id.IntegerValue.ToString());
                    foreach (var pair in GlobalResource.RevitModels)
                    {
                        var values = pair.Value;
                        var model = values.Where(x => x.Id == strId)?.ToList();
                        if (model == null || model.Count() == 0)
                        {
                            continue;
                        }
                        else
                        {
                            values.Remove(model[0]);
                        }
                    }
                }
            }
            return;
        }
        private static void AddElements(Document doc, ICollection<ElementId> addedIds)
        {
            bool instancePlacing = GlobalResource.InstancePlacing;
            bool pipePlacing = GlobalResource.PipePlacing;
            if (pipePlacing)
            {
                foreach (var id in addedIds)
                {
                    var elem = doc.GetElement(id);
                    if (elem is FamilyInstance fi)
                    {
                        AddAutoCreated(fi);
                    }
                    if (elem is Pipe)
                    {
                        GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                        AddManualCreated(elem);
                    }
                }
            }
            else if (instancePlacing)
            {
                foreach (var id in addedIds)
                {
                    var elem = doc.GetElement(id);
                    if (elem is FamilyInstance)
                    {
                        GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                        AddManualCreated(elem);
                    }
                }
            }
            else
            {
                bool isPumpSystemElement = false;
                foreach (var id in addedIds)
                {
                    if (IsConnectedWithPumpSystem(doc, id))
                    {
                        isPumpSystemElement = true;
                        break;
                    }
                }
                if (isPumpSystemElement)
                {
                    foreach (var id in addedIds)
                    {
                        AddToPumpSystem(doc, id);
                    }
                }
            }
            return;
        }
        private static bool IsConnectedWithPumpSystem(Document doc, ElementId id)
        {
            var elem = doc.GetElement(id);
            if (elem is Pipe pipe) //直接点击水泵的连接件创建管道
            {
                if (pipe.ConnectWithPumpSystem())
                {
                    //GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                    //TaskDialog.Show("提示", "增加管道:" + id.IntegerValue.ToString());
                    //AddManualCreated(elem);
                    return true;
                }
            }
            else if (elem is FamilyInstance fi)
            {
                if (fi.ConnectWithPumpSystem()) //直接点击管道连接点创建管道时,Revit会自动创建弯头,都需要加入到缓存
                {
                    //GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                    //TaskDialog.Show("提示", "增加族实例:" + id.IntegerValue.ToString());
                    //AddManualCreated(elem);
                    return true;
                }
            }
            return false;
        }
        private static void AddToPumpSystem(Document doc, ElementId id)
        {
            var elem = doc.GetElement(id);
            if (elem is Pipe)
            {
                GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                AddToMap(elem, RevitType.RFT_Pipe);
            }
            else if (elem is FamilyInstance fi)
            {
                GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
                AddAutoCreated(fi);
            }
            return;
        }
        private static void AddAutoCreated(FamilyInstance fi)
        {
            var id = fi.Id;
            GlobalResource.ElementIds.Add(id.IntegerValue.ToString());
            if (fi.IsWanTou())
            {
                AddToMap(fi, RevitType.RFT_Elbow);
            }
            else if (fi.IsConverter())
            {
                AddToMap(fi, RevitType.RFT_Converter);
            }
            else if (fi.IsSanTong())
            {
                AddToMap(fi, RevitType.RFT_ThreeJoint);
            }
            else if (fi.IsSiTong())
            {
                AddToMap(fi, RevitType.RFT_FourJoint);
            }
            else
            {
                TaskDialog.Show("警告", $"未知类型被添加!id:{fi.Id.IntegerValue}");
                //报错
            }
        }
        private static void AddManualCreated(Element elem)
        {
            var id = elem.Id.IntegerValue.ToString();
            //更新已加入到缓存中的构件数据
            List<string> linkedIds = elem.GetConnectElements().Select(x => x.Id.IntegerValue.ToString()).ToList();
            //foreach (var linkId in linkedIds)
            //{
            //    var model = GlobalResource.GetElementModel(linkId);
            //    if (!model.LinkIds.Contains(id))
            //    {
            //        model.LinkIds += "," + id;
            //    }
            //}
            //把新增构件加入到缓存中
            if (!GlobalResource.RevitModels.ContainsKey(GlobalResource.RevitFamilyType))
            {
                GlobalResource.RevitModels.Add(GlobalResource.RevitFamilyType, new ObservableCollection<ElementModel>());
                GlobalResource.RevitModels[GlobalResource.RevitFamilyType].Add(new ElementModel
                {
                    Name = elem.Name,
                    Id = id,
                    LinkIds = /*string.Join(",", linkedIds)*/string.Empty
                });
            }
            else if(!GlobalResource.RevitModels[GlobalResource.RevitFamilyType].Any(x=>x.Id == id))
            {
                GlobalResource.RevitModels[GlobalResource.RevitFamilyType].Add(new ElementModel
                {
                    Name = elem.Name,
                    Id = id,
                    LinkIds = /* string.Join(",", linkedIds)*/string.Empty
                });
            }
        }
        private static void AddToMap(Element elem, RevitType revitType)
        {
            var id = elem.Id.IntegerValue.ToString();
            //更新已加入到缓存中的构件数据
            //List<string> linkedIds = elem.GetConnectElements().Select(x => x.Id.IntegerValue.ToString()).ToList();
            //foreach (var linkId in linkedIds)
            //{
            //    var model = GlobalResource.GetElementModel(linkId);
            //    if (!model.LinkIds.Contains(id))
            //    {
            //        model.LinkIds += "," + id;
            //    }
            //}
            if (!GlobalResource.RevitModels.ContainsKey(revitType))
            {
                GlobalResource.RevitModels.Add(revitType, new ObservableCollection<ElementModel>());
                GlobalResource.RevitModels[revitType].Add(new ElementModel
                {
                    Name = elem.Name,
                    Id = id,
                    LinkIds = /*string.Join(",", linkedIds)*/string.Empty
                });
            }
            else if (!GlobalResource.RevitModels[revitType].Any(x => x.Id == id))
            {
                GlobalResource.RevitModels[revitType].Add(new ElementModel
                {
                    Name = elem.Name,
                    Id = id,
                    LinkIds = /*string.Join(",", linkedIds)*/string.Empty
                });
            }
        }
        public static void RegistViewEvent(ExternalCommandData commandData)
        {
            commandData.Application.ViewActivated -= Application_ViewActivated;
            commandData.Application.ViewActivated += Application_ViewActivated;
        }
        private static void Application_ViewActivated(object sender, ViewActivatedEventArgs e)
        {
            GlobalResource.CurrentDocument = e.CurrentActiveView.Document;
        }
        public static List<Element> GetModelElements(this Document doc)
        {
            //FilteredElementCollector collector = null;
            //foreach (Category cate in doc.Settings.Categories)
            //{
            //    if (cate.CategoryType != CategoryType.Model)
            //    {
            //        continue;
            //    }
            //    var subCollector = new FilteredElementCollector(doc);
            //    subCollector.OfCategory((BuiltInCategory)(cate.Id.IntegerValue));
            //    subCollector.WhereElementIsNotElementType();
            //    if (collector == null)
            //    {
            //        collector = subCollector;
            //    }
            //    else
            //    {
            //        collector.UnionWith(subCollector);
            //    }
            //}
            //
            var collector1 = new FilteredElementCollector(doc).
                OfCategory(BuiltInCategory.OST_PipeCurves).
                WhereElementIsNotElementType();
            var collector2 = new FilteredElementCollector(doc).
                OfClass(typeof(FamilyInstance)).
                WhereElementIsNotElementType();
            var elements1 = collector1.ToElements()?.ToList();
            var elements2 = collector2.ToElements()?.ToList();
            elements1.AddRange(elements2);
            elements1 = elements1.Where(x => x.Category.CategoryType == CategoryType.Model).ToList();
            elements1 = elements1.Where(x => x.get_BoundingBox(null) != null).ToList();
            return elements1;
        }
        public static void AddUnhandledElementsToCache()
        {
            var elements = GlobalResource.CurrentDocument.GetModelElements();
            foreach (var element in elements)
            {
                var id = element.Id.IntegerValue.ToString();
                if (GlobalResource.ElementIds.Contains(id))
                {
                    continue;
                }
                RevitMepCategoryService.MatchElement(element);
            }
            UpdateLinkerInfo(GlobalResource.CurrentDocument);
        }
    }
}