Browse Source

mxg:添加立管对齐功能

mengxiangge 6 years ago
parent
commit
ed26cd64e9

BIN
MBI/MBIResource/DataCheck/模型检查结果输出格式-模版.xlsx


+ 8 - 0
MBI/SAGA.MBI/SAGA.MBI.csproj

@@ -354,6 +354,10 @@
     <Compile Include="ToolsData\IToolCommand.cs" />
     <Compile Include="ToolsData\ExportAllDuty.cs" />
     <Compile Include="ToolsData\UpdateRelationEquipinSpace.cs" />
+    <Compile Include="ToolsData\VerticalPipeAlign.cs" />
+    <Compile Include="ToolsData\WinSelectCheckFloors.xaml.cs">
+      <DependentUpon>WinSelectCheckFloors.xaml</DependentUpon>
+    </Compile>
     <Compile Include="WinView\BeModingDutyList\MEquipNoMode.cs" />
     <Compile Include="WinView\BeModingDutyList\VMBeModeDutyList.cs" />
     <Compile Include="Extend\MRevitEquipBaseExtend.cs" />
@@ -710,6 +714,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="ToolsData\WinSelectCheckFloors.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="WinView\BeModingDutyList\WinBeModeDutyList.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 33 - 0
MBI/SAGA.MBI/ToolCommand.cs

@@ -34,6 +34,39 @@ namespace SAGA.MBI
 
     #region 工具
     /// <summary>
+    /// 立管对齐
+    /// </summary>
+    [Transaction(TransactionMode.Manual)]
+    [Regeneration(RegenerationOption.Manual)]
+    public class VerticalPipeAlginCommand : ExternalCommand
+    {
+        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+        {
+            try
+            {
+                int count = 0;
+                WinSelectCheckFloors win =new WinSelectCheckFloors();
+                if (win.ShowDialog() == true)
+                {
+                    VerticalPipeAlign.Instance.Execute();
+                    VerticalPipeAlign.Instance.ShowResult();
+                }
+
+            }
+            catch (Exception e)
+            {
+                MessageShow.Show(e);
+                return Result.Cancelled;
+            }
+            return Result.Succeeded;
+        }
+
+        public override bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
+        {
+            return true;
+        }
+    }
+    /// <summary>
     /// 批量删除无用的空间
     /// </summary>
     [Transaction(TransactionMode.Manual)]

+ 317 - 0
MBI/SAGA.MBI/ToolsData/VerticalPipeAlign.cs

@@ -0,0 +1,317 @@
+/* ==============================================================================
+ * 功能描述:立管对齐
+ * 创 建 者:Garrett
+ * 创建日期:2019/1/21 16:22:40
+ * ==============================================================================*/
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.DB.Plumbing;
+using SAGA.DotNetUtils.Data;
+using SAGA.DotNetUtils.Extend;
+using SAGA.DotNetUtils.Others;
+using SAGA.MBI.DataArrange;
+using SAGA.MBI.Model;
+using SAGA.MBI.Tools;
+using SAGA.RevitUtils.Extends;
+using SAGA.RevitUtils.MEP;
+
+namespace SAGA.MBI.ToolsData
+{
+    /// <summary>
+    /// VerticalPipeAlign
+    /// </summary>
+    public class VerticalPipeAlign : SingleInstance<VerticalPipeAlign>
+    {
+        public void Execute()
+        {
+            m_ErrorLogs = new List<string>();
+            List<MFloor> floors = DalProjectTree.GetSelectedFloors();
+            //两层两层对齐,从上到下依次对齐
+            for (int i = 1; i < floors.Count; i++)
+            {
+                MFloor m0 = floors[i - 1];
+                MFloor m1 = floors[i];
+                if (BeginAlign(m0, m1))
+                    break;
+            }
+
+        }
+        /// <summary>
+        /// Doc0和Doc1对齐
+        /// </summary>
+        /// <param name="doc0"></param>
+        /// <param name="doc1"></param>
+        private bool BeginAlign(MFloor m0, MFloor m1)
+        {
+            string m0Name = m0.ToString();
+            string m1Name = m1.ToString();
+
+            Document doc0 = ExternalDataWrapper.Current.App.OpenDocumentFile(m0.FullPath);
+            Document doc1 = ExternalDataWrapper.Current.App.OpenDocumentFile(m1.FullPath);
+            string path0 = doc0.PathName;
+            string path1 = doc1.PathName;
+
+            var verticalPipes = GetAllVerticalPipe(doc0);
+            verticalPipes.AddRange(GetAllVerticalPipe(doc1));
+
+            double z = GetBaseLevel(doc0);
+            var groupByNote = verticalPipes.GroupBy(t => t.Note);
+            foreach (IGrouping<string, VPipe> grouping in groupByNote)
+            {
+                //不是成对的,不处理
+                if (grouping.Count() < 2) continue;
+                var basePipe = grouping.FirstOrDefault(t => t.FloorName == path0);
+                var referPipe = grouping.FirstOrDefault(t => t.FloorName == path1);
+                if (basePipe != null && referPipe != null)
+                {
+                    using (Transaction trans = new Transaction(doc1, "立管对齐"))
+                    {
+                        trans.Start();
+                        try
+                        {
+                            FailureHandlingOptions options = trans.GetFailureHandlingOptions();
+                            VerticalPipeAlignFailuresPreProcessor failureProcessor = new VerticalPipeAlignFailuresPreProcessor();
+                            options.SetFailuresPreprocessor(failureProcessor);
+                            trans.SetFailureHandlingOptions(options);
+
+                            MoveReferPipe(basePipe.Pipe, referPipe.Pipe);
+                            //ExtendPipe(grouping.Where(t => t.FloorName == path0).Select(t => t.Pipe).ToList(), z, true);
+                            ExtendPipe(grouping.Where(t => t.FloorName == path1).Select(t => t.Pipe).ToList(), z, false);
+                            trans.Commit();
+                            if (failureProcessor.HasError)
+                            {
+                                string msg =
+                                    $"对齐时发生异常:{failureProcessor.FailureMessage}\r\n楼层:{m1Name} Id:{referPipe.Pipe.Id};参考楼层:{m0Name} Id:{basePipe.Pipe.Id}";
+                                AppendErrorLogs(msg);
+                            }
+                        }
+                        catch (Exception e)
+                        {
+                            trans.RollBack();
+                            string msg =
+                                $"楼层:{m1Name} Id:{referPipe.Pipe.Id} 对齐时发生异常,请检查!参考楼层:{m0Name} Id:{basePipe.Pipe.Id}";
+                            AppendErrorLogs(msg);
+                        }
+                    }
+                    using (Transaction trans = new Transaction(doc0, "延长立管"))
+                    {
+                        trans.Start();
+                        try
+                        {
+                            ExtendPipe(grouping.Where(t => t.FloorName == path0).Select(t => t.Pipe).ToList(), z, true);
+                            trans.Commit();
+                        }
+                        catch (Exception e)
+                        {
+                            trans.RollBack();
+                            string msg =
+                                $"楼层:{m0Name} Id:{basePipe.Pipe.Id} 延长立管时发生异常,请检查!";
+                            AppendErrorLogs(msg);
+                        }
+                    }
+                }
+            }
+
+            doc0.CloseDoc();
+            doc1.CloseDoc();
+
+            return ErrorLogs.Count > 0;
+        }
+        private List<string> m_ErrorLogs = new List<string>();
+
+        private List<string> ErrorLogs
+        {
+            get { return m_ErrorLogs; }
+        }
+
+        private void AppendErrorLogs(string msg)
+        {
+            ErrorLogs.Add(msg);
+        }
+
+        public void ShowResult()
+        {
+            if (ErrorLogs.Count == 0)
+                ErrorLogs.Add("对齐操作成功");
+            MessageShowBase.Infomation(ErrorLogs);
+        }
+        /// <summary>
+        /// 延长立管
+        /// </summary>
+        /// <param name="pipes"></param>
+        /// <param name="z"></param>
+        /// <param name="isTop"></param>
+        private void ExtendPipe(List<Pipe> pipes, double z, bool isTop = true)
+        {
+            foreach (Pipe pipe in pipes)
+            {
+                var connectors = pipe.GetConnectors();
+                var connectort = connectors.FirstOrDefault(t => t.CoordinateSystem.BasisZ.IsEqual(XYZ.BasisZ));
+                var connectorb = connectors.FirstOrDefault(t => t.CoordinateSystem.BasisZ.IsEqual(-XYZ.BasisZ));
+                if (connectort == null || connectorb == null) continue;
+                var xyzt = connectort?.Origin;
+                var xyzb = connectorb?.Origin;
+                if (xyzb == null || xyzt == null) continue;
+                if (isTop)
+                {
+                    //底部连接的不延长
+                    if (connectorb.IsConnected)
+                        continue;
+                    xyzb = xyzb.NewZ(z);
+                }
+                else
+                {
+                    if (connectort.IsConnected)
+                        continue;
+                    xyzt = xyzt.NewZ(z);
+                }
+                pipe.UpdateLocation(xyzb, xyzt);
+            }
+        }
+
+        /// <summary>
+        /// 对齐
+        /// </summary>
+        /// <param name="pipe0"></param>
+        /// <param name="pipe1"></param>
+        private void MoveReferPipe(Pipe pipe0, Pipe pipe1)
+        {
+
+            var baseOrigin = (pipe0.GetCurve() as Line)?.Origin;
+            if (baseOrigin == null) return;
+            var referOrigin = (pipe1.GetCurve() as Line)?.Origin;
+            if (referOrigin == null) return;
+            pipe1.MoveWithSub((baseOrigin - referOrigin).NewZ());
+        }
+
+        /// <summary>
+        /// 获取所有的立管
+        /// </summary>
+        /// <param name="doc"></param>
+        /// <returns></returns>
+        private List<VPipe> GetAllVerticalPipe(Document doc)
+        {
+            var pipes = doc.GetElements<Pipe>();
+
+            var verticalPipes = pipes.Where(t => t.GetParameterString("注释") != null && Regex.IsMatch(t.GetParameterString("注释"), @"start-.*")).Select(tt => new VPipe() { Pipe = tt, FloorName = doc.PathName, Note = tt.GetParameterString("注释") }).ToList();
+
+            return verticalPipes;
+        }
+
+        #region 延长立管
+
+        private double GetBaseLevel(Document doc)
+        {
+            var sagaPlans = doc.GetElements<ViewPlan>()
+                .Where(t => t.ViewType == ViewType.FloorPlan && t.Name.Contains("-saga"));
+            //只有一个saga标记
+            var sagaPlan = sagaPlans.FirstOrDefault();
+            double hb = sagaPlan.GenLevel.Elevation;
+            return hb;
+        }
+        private Tuple<double, double> GetCurFloorLevel(Document doc)
+        {
+            var sagaPlans = doc.GetElements<ViewPlan>()
+                .Where(t => t.ViewType == ViewType.FloorPlan && t.Name.Contains("-saga"));
+            //只有一个saga标记
+            var sagaPlan = sagaPlans.FirstOrDefault();
+            double hb = sagaPlan.GenLevel.Elevation;
+            double ht = 0;
+            double hj = 0;
+            //设置楼层底部高度
+            var curLevelName = sagaPlan.GenLevel.Name;
+            //设置楼层顶部高度
+            if (curLevelName == "RF" || curLevelName == "RFM")
+            {
+                ht = double.MaxValue;
+                hj = double.MaxValue;
+            }
+            else
+            {
+                var levels = doc.GetLevels();
+                var mbiLevels = levels.Where(t => Regex.IsMatch(t.Name, @"([BF][1-9]\d*M?|RFM?)"));
+                var topLevel = mbiLevels.FirstOrDefault(t => t.Elevation.IsThan(hb));
+                if (topLevel == null)
+                {
+                    throw new Exception($"标高编码不合法:{curLevelName}不应该是顶层,缺少标高RF或标高RF标注的位置不正确");
+                }
+
+                double nextL = topLevel.Elevation;
+                string tempTopLevelName = topLevel.Name;
+                //如果是夹层,获取夹层的上一层
+                if (Regex.IsMatch(tempTopLevelName, @"([BF][1-9]\d*M|RFM)"))
+                {
+                    hj = nextL;
+                    topLevel = mbiLevels.FirstOrDefault(t => t.Elevation.IsThan(nextL));
+                    if (topLevel == null)
+                    {
+                        throw new Exception($"标高编码不合法:{tempTopLevelName}不应该是顶层,缺少标高RF或标高RF标注的位置不正确");
+                    }
+                    else
+                    {
+                        ht = topLevel.Elevation;
+                    }
+                }
+                else
+                {
+                    hj = nextL;
+                    ht = nextL;
+                }
+
+            }
+            return null;
+        }
+        #endregion
+
+    }
+    public class VPipe
+    {
+        public Pipe Pipe { get; set; }
+
+        public string FloorName { get; set; }
+
+        public string Note { get; set; }
+    }
+    public class VerticalPipeAlignFailuresPreProcessor : IFailuresPreprocessor
+    {
+        private string _failureMessage;
+        private bool _hasError;
+        public string FailureMessage
+        {
+            get { return _failureMessage; }
+            set { _failureMessage = value; }
+        }
+        public bool HasError
+        {
+            get { return _hasError; }
+            set { _hasError = value; }
+        }
+        public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
+        {
+            var failures = failuresAccessor.GetFailureMessages();
+            if (failures.Count == 0)
+                return FailureProcessingResult.Continue;
+
+            foreach (var failure in failures)
+            {
+                if (failure.GetSeverity() == FailureSeverity.Error)
+                {
+                    _failureMessage = failure.GetDescriptionText(); // get the failure description
+                    _hasError = true;
+                    return FailureProcessingResult.ProceedWithRollBack;
+                }
+                if (failure.GetSeverity() == FailureSeverity.Warning)
+                {
+                    failuresAccessor.DeleteWarning(failure);
+                }
+            }
+
+            return FailureProcessingResult.Continue;
+        }
+    }
+}

+ 91 - 0
MBI/SAGA.MBI/ToolsData/WinSelectCheckFloors.xaml

@@ -0,0 +1,91 @@
+<Window x:Class="SAGA.MBI.ToolsData.ModeCheck.WinSelectCheckFloors"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:SAGA.MBI.ToolsData.ModeCheck"
+             xmlns:common="clr-namespace:SAGA.MBI.Common"
+             xmlns:converter="clr-namespace:SAGA.DotNetUtils.WPF.Converter;assembly=SAGA.DotNetUtils"
+             xmlns:userControl="clr-namespace:SAGA.DotNetUtils.WPF.UserControl;assembly=SAGA.DotNetUtils"
+             xmlns:checkBase="clr-namespace:SAGA.MBI.ToolsData.CheckBase"
+             xmlns:dataCheck="clr-namespace:SAGA.MBI.ToolsData.DataCheck"
+             mc:Ignorable="d"  Title="选择楼层" WindowStartupLocation="CenterScreen"
+             Height="587" Width="400">
+    <Window.Resources>
+        <converter:BoolToInverserConverter x:Key="BoolInverseConverter"></converter:BoolToInverserConverter>
+        <converter:StringToImageConverter x:Key="StringToImageConverter"></converter:StringToImageConverter>
+    </Window.Resources>
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="40"></RowDefinition>
+            <RowDefinition Height="*"></RowDefinition>
+            <RowDefinition Height="40"></RowDefinition>
+        </Grid.RowDefinitions>
+        <Grid Grid.Row="0">
+            <WrapPanel VerticalAlignment="Center">
+                <Label Margin="5,0,0,0" Content="当前项目:" FontSize="15"></Label>
+                <Label Content="{x:Static common:MBIControl.ProjectCur}" FontSize="15"></Label>
+            </WrapPanel>
+        </Grid>
+        <Grid Grid.Row="1">
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="*"></ColumnDefinition>
+            </Grid.ColumnDefinitions>
+            <Grid Grid.Column="0">
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="*"></RowDefinition>
+                </Grid.RowDefinitions>
+                <GroupBox Grid.Row="0" Header="请选择需要检查的建筑">
+                    <TreeView ItemsSource="{Binding Path=ProjectList}">
+                        <TreeView.ItemTemplate>
+                            <HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
+                                <WrapPanel>
+                                    <CheckBox IsChecked="{Binding Path=IsSelected,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
+                                              Width="Auto" VerticalContentAlignment="Center" 
+                                              Click="TreeItem_Click">
+                                    </CheckBox>
+                                    <Label Content="{Binding Path=Item.TvItemName}"></Label>
+                                </WrapPanel>
+                            </HierarchicalDataTemplate>
+                        </TreeView.ItemTemplate>
+                        <TreeView.ItemContainerStyle>
+                            <Style TargetType="{x:Type TreeViewItem}">
+                                <Setter Property="IsExpanded" Value="True" />
+                            </Style>
+                        </TreeView.ItemContainerStyle>
+                    </TreeView>
+                </GroupBox>
+            </Grid>
+        </Grid>
+        <Grid Grid.Row="2">
+            <Grid.RowDefinitions>
+                <RowDefinition></RowDefinition>
+            </Grid.RowDefinitions>
+            <Grid Grid.Row="0">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition></ColumnDefinition>
+                    <ColumnDefinition></ColumnDefinition>
+                </Grid.ColumnDefinitions>
+                <Button Grid.Column="0" Width="100" Height="25" Content="确定" HorizontalAlignment="Right" Margin="0,0,20,0" VerticalAlignment="Center" Click="ButtonNext_OnClick" IsDefault="True"></Button>
+                <Button Grid.Column="1" Width="100" Height="25" Content="取消" HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" IsCancel="True"  Background="White"></Button>
+
+            </Grid>
+        </Grid>
+
+    </Grid>
+</Window>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 146 - 0
MBI/SAGA.MBI/ToolsData/WinSelectCheckFloors.xaml.cs

@@ -0,0 +1,146 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Input;
+using SAGA.DotNetUtils.Extend;
+using SAGA.MBI.Common;
+using SAGA.MBI.DataArrange;
+using SAGA.MBI.Model;
+using SAGA.MBI.ToolsData.CheckBase;
+
+namespace SAGA.MBI.ToolsData.ModeCheck
+{
+    /// <summary>
+    /// WinModeCheckSetting.xaml 的交互逻辑
+    /// </summary>
+    public partial class WinSelectCheckFloors : INotifyPropertyChanged
+    {
+        private CheckType m_CheckType;
+        public WinSelectCheckFloors()
+        {
+            InitializeComponent();
+            Init();
+            this.DataContext = this;
+
+        }
+
+        private void Init()
+        {
+            ProjectList = MBIControl.ProjectTree.Children;
+            if (ProjectList.FirstOrDefault() != null)
+                SetTreeItemState(ProjectList.FirstOrDefault(), false);
+        }
+
+
+        #region BindingProperty
+
+        private ObservableCollection<TreeNodeItem> m_ProjectList;
+
+        public ObservableCollection<TreeNodeItem> ProjectList
+        {
+            get { return m_ProjectList; }
+            set { m_ProjectList = value; }
+        }
+        
+        public event PropertyChangedEventHandler PropertyChanged;
+        #endregion
+
+
+        #region Action
+
+        
+        private void ButtonNext_OnClick(object sender, RoutedEventArgs e)
+        {
+            if (CanExecute())
+            {
+                this.DialogResult = true;
+            }
+        }
+
+        private bool CanExecute()
+        {
+            bool result = DalProjectTree.GetSelectedBuilding()?.Id != null; ;
+            if (!result)
+            {
+                MessageBox.Show("请选择需要检查的建筑");
+                if (ProjectList.FirstOrDefault() != null)
+                    SetTreeItemState(ProjectList.FirstOrDefault(), true);
+            }
+
+
+            return result;
+        }
+        #endregion
+       
+
+        private void TreeItem_Click(object sender, RoutedEventArgs e)
+        {
+            if (sender is CheckBox chk)
+            {
+                bool state = chk.IsChecked == true;
+                if (chk.DataContext is TreeNodeItem node)
+                {
+                    SetTreeItemState(node, state);
+                }
+            }
+        }
+        /// <summary>
+        /// 设置节点状态
+        /// </summary>
+        /// <param name="node"></param>
+        /// <param name="state"></param>
+        private void SetTreeItemState(TreeNodeItem node, bool state)
+        {
+            node.IsSelected = state;
+            SetChildrenState(node, state);
+            SetParentState(node, state);
+        }
+        /// <summary>
+        /// 设置子节点状态
+        /// </summary>
+        /// <param name="node"></param>
+        /// <param name="state"></param>
+        private void SetChildrenState(TreeNodeItem node, bool state)
+        {
+            foreach (TreeNodeItem child in node.Children)
+            {
+                child.IsSelected = state;
+            }
+        }
+        /// <summary>
+        /// 设置父节点状态
+        /// </summary>
+        /// <param name="node"></param>
+        /// <param name="state"></param>
+        private void SetParentState(TreeNodeItem node, bool state)
+        {
+            if (node.Parent != null)
+            {
+                if (node.Parent.Item is MProject)
+                {
+                    if (state)
+                    {
+                        foreach (var child in node.Parent.Children)
+                        {
+                            if (child != node)
+                            {
+                                child.IsSelected = false;
+                                SetChildrenState(child, false);
+                            }
+                        }
+                    }
+                }
+                node.Parent.IsSelected = node.Parent.Children.Any(t => t.IsSelected);
+                SetParentState(node.Parent, state);
+            }
+
+        }
+    }
+}
+

+ 0 - 1
MBI/SAGA.RevitUtils/Extends/ExternalApplication.cs

@@ -55,7 +55,6 @@ namespace SAGA.RevitUtils.Extends
                 //´«µÝDocumentChangedʼþ
                 TszDocChanged(sender, e);
             }
-          System.Diagnostics.Debug.WriteLine($"{DateTime.Now}±»ÐÞ¸ÄÁË£¡");
         }
 
         /// <summary>

+ 4 - 0
MBI/SAGA.RevitUtils/MEP/PipeExtend.cs

@@ -242,7 +242,11 @@ namespace SAGA.RevitUtils.MEP
             if (!start.IsEqual(end, 0.0))
             {
                 LocationCurve location = pipe.Location as LocationCurve;
+                if (location == null) return;
                 Line axis = start.NewLine(end);
+                //如果与之前线方向不同,那么反向。
+                if (!location.Curve.SameDirection(axis))
+                    axis = axis.Reverse();
                 location.Curve = axis;
                 pipe.Document.RotateElement((Element) pipe, axis, Math.PI*2);
             }