فهرست منبع

Merge branch 'master' of http://dev.dp.sagacloud.cn:8886/r/Revit/SAGA.MBI

mengxiangge 6 سال پیش
والد
کامیت
2304df0666
59فایلهای تغییر یافته به همراه2676 افزوده شده و 544 حذف شده
  1. BIN
      MBI/Dlls/FirmLibDll/FWindSoft.Wpf.dll
  2. BIN
      MBI/Dlls/FirmLibDll/FWindSoft.Wpf.pdb
  3. BIN
      MBI/Dlls/FirmLibDll/FWindSoft.dll
  4. BIN
      MBI/Dlls/FirmLibDll/FWindSoft.pdb
  5. 4 0
      MBI/MBIResource/RevitEvents/RevitEvents.xml
  6. 15 0
      MBI/SAGA.DotNetUtils/SAGA.DotNetUtils.csproj
  7. 22 0
      MBI/SAGA.DotNetUtils/Utilities/IWaitingView.cs
  8. 103 0
      MBI/SAGA.DotNetUtils/WPF/UserControl/WaitingCircle.xaml
  9. 28 0
      MBI/SAGA.DotNetUtils/WPF/UserControl/WaitingCircle.xaml.cs
  10. 33 0
      MBI/SAGA.DotNetUtils/WPF/Windows/WinIndeterminationWaiting.xaml
  11. 35 0
      MBI/SAGA.DotNetUtils/WPF/Windows/WinIndeterminationWaiting.xaml.cs
  12. 49 54
      MBI/SAGA.GplotDrawData/DBView/EquipmentGraphView.cs
  13. 0 1
      MBI/SAGA.GplotDrawData/DBView/SpaceGraphView.cs
  14. 3 2
      MBI/SAGA.GplotDrawData/DBView/VerticalPipeGraphView.cs
  15. 0 172
      MBI/SAGA.GplotDrawData/DBView/VirticalSpaceGraphView.cs
  16. 2 0
      MBI/SAGA.GplotDrawData/WinControlRelation-Web.xaml.cs
  17. 6 31
      MBI/SAGA.GplotDrawData/WinDrawSpace-Web.xaml.cs
  18. 3 3
      MBI/SAGA.GplotManage/GplotCommand.cs
  19. 0 1
      MBI/SAGA.GplotRelationComputerManage/Command.cs
  20. 38 33
      MBI/SAGA.GplotRelationComputerManage/ComputerPipes.cs
  21. 139 37
      MBI/SAGA.GplotRelationComputerManage/ComputerVerticalPipe.cs
  22. 5 2
      MBI/SAGA.GplotRelationComputerManage/PowerDistribution/Common/DataNodeUtil.cs
  23. 1 1
      MBI/SAGA.GplotRelationComputerManage/PumpEnd/DrawEnd.cs
  24. 1 1
      MBI/SAGA.GplotRelationComputerManage/PumpEnd/DuctTerminalBll.cs
  25. 27 15
      MBI/SAGA.GplotRelationComputerManage/ReadSpaceCommand.cs
  26. 5 1
      MBI/SAGA.GplotRelationComputerManage/RevitModelPath.cs
  27. 5 0
      MBI/SAGA.GplotRelationComputerManage/SAGA.GplotRelationComputerManage.csproj
  28. 149 0
      MBI/SAGA.GplotRelationComputerManage/SpaceRelation/ComputerSpaceItem.cs
  29. 364 13
      MBI/SAGA.GplotRelationComputerManage/SpaceRelation/FloorSpaceItems.cs
  30. 80 0
      MBI/SAGA.GplotRelationComputerManage/SpaceRelation/SpaceComputerContext.cs
  31. 49 3
      MBI/SAGA.GplotRelationComputerManage/SpaceRelation/SpaceComputerManager.cs
  32. 37 0
      MBI/SAGA.GplotRelationComputerManage/SystemRelation/Common/SystemCalcUtil.cs
  33. 48 0
      MBI/SAGA.GplotRelationComputerManage/SystemRelation/FloorSystemItems.cs
  34. 55 0
      MBI/SAGA.GplotRelationComputerManage/SystemRelation/SystemComputerContext.cs
  35. 8 5
      MBI/SAGA.MBI/Command.cs
  36. 76 0
      MBI/SAGA.MBI/Common/WaitingView.cs
  37. 5 0
      MBI/SAGA.MBI/DataArrange/DalUploadFloor.cs
  38. 20 0
      MBI/SAGA.MBI/Extend/DocExtend.cs
  39. 76 0
      MBI/SAGA.MBI/Interaction/MBILocalNameTrigger.cs
  40. 7 9
      MBI/SAGA.MBI/Interaction/MBIModelInfoManager.cs
  41. 3 2
      MBI/SAGA.MBI/Model/MRevitEquipBase.cs
  42. 109 1
      MBI/SAGA.MBI/RevitModelHandle/RevitParameterUpdate.cs
  43. 3 0
      MBI/SAGA.MBI/SAGA.MBI.csproj
  44. 139 0
      MBI/SAGA.MBI/TestCommand.cs
  45. 67 0
      MBI/SAGA.MBI/WinView/Space/ExternalEventHandler.cs
  46. 9 4
      MBI/SAGA.MBI/WinView/Space/FloorSpaceContext.cs
  47. 5 1
      MBI/SAGA.MBI/WinView/Space/SpaceManager.cs
  48. 146 120
      MBI/SAGA.MBI/WinView/Space/WinCreateSpace.xaml.cs
  49. 76 9
      MBI/SAGA.MBI/WinView/Space/WinCreateSpaceWeb.xaml
  50. 337 19
      MBI/SAGA.MBI/WinView/Space/WinCreateSpaceWeb.xaml.cs
  51. 3 0
      MBI/SAGA.Models/DrawDataServer.cs
  52. 6 1
      MBI/SAGA.Models/Graphs/GElement.cs
  53. 2 1
      MBI/SAGA.Models/Graphs/GElementConverter.cs
  54. 5 0
      MBI/SAGA.Models/Graphs/VElements/GVElement.cs
  55. 2 0
      MBI/SAGA.Models/VerticalPipe.cs
  56. 33 2
      MBI/SAGA.RevitUtils/ExtendInterface/RevitEventsBingding.cs
  57. 221 0
      MBI/SAGA.RevitUtils/ExtendInterface/RevitTrigger.cs
  58. 11 0
      MBI/SAGA.RevitUtils/MBIExtension/MBIDocExtension.cs
  59. 1 0
      MBI/SAGA.RevitUtils/SAGA.RevitUtils.csproj

BIN
MBI/Dlls/FirmLibDll/FWindSoft.Wpf.dll


BIN
MBI/Dlls/FirmLibDll/FWindSoft.Wpf.pdb


BIN
MBI/Dlls/FirmLibDll/FWindSoft.dll


BIN
MBI/Dlls/FirmLibDll/FWindSoft.pdb


+ 4 - 0
MBI/MBIResource/RevitEvents/RevitEvents.xml

@@ -4,6 +4,10 @@
     <DllName>OutputDll\SAGA.MBI.exe</DllName>
     <ClassName>SAGA.MBI.Interaction.MBIDocumentSaved</ClassName>
 </IDocumentSaved>
+<IUpdaterRegister>
+    <DllName>OutputDll\SAGA.MBI.exe</DllName>
+    <ClassName>SAGA.MBI.Interaction.MBILocalNameTrigger</ClassName>
+</IUpdaterRegister>
 </RevitEvents>
 
 

+ 15 - 0
MBI/SAGA.DotNetUtils/SAGA.DotNetUtils.csproj

@@ -336,6 +336,7 @@
     <Compile Include="Utilities\CompressUtil.cs" />
     <Compile Include="Utilities\FileUp.cs" />
     <Compile Include="Utilities\IniOperator.cs" />
+    <Compile Include="Utilities\IWaitingView.cs" />
     <Compile Include="Utilities\PinyinUtil.cs" />
     <Compile Include="Utilities\SharpZip.cs" />
     <Compile Include="WinForms\EditorItemValueChangedEventArgs.cs" />
@@ -432,7 +433,13 @@
     <Compile Include="WPF\UserControl\UnitTextbox_PlusDouble.xaml.cs">
       <DependentUpon>UnitTextbox_PlusDouble.xaml</DependentUpon>
     </Compile>
+    <Compile Include="WPF\UserControl\WaitingCircle.xaml.cs">
+      <DependentUpon>WaitingCircle.xaml</DependentUpon>
+    </Compile>
     <Compile Include="WPF\VisualTreeExtend.cs" />
+    <Compile Include="WPF\Windows\WinIndeterminationWaiting.xaml.cs">
+      <DependentUpon>WinIndeterminationWaiting.xaml</DependentUpon>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Logger\log4net.config">
@@ -478,6 +485,14 @@
       <SubType>Designer</SubType>
       <Generator>XamlIntelliSenseFileGenerator</Generator>
     </Page>
+    <Page Include="WPF\UserControl\WaitingCircle.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="WPF\Windows\WinIndeterminationWaiting.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
   </ItemGroup>
   <ItemGroup>
     <Resource Include="Image\page_edit.png">

+ 22 - 0
MBI/SAGA.DotNetUtils/Utilities/IWaitingView.cs

@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:IWaitingView
+ * 作者:xulisong
+ * 创建时间: 2018/12/26 17:42:48
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SAGA.DotNetUtils
+{
+    public interface IWaitingView
+    {
+        void Start();
+        void Close();
+        void Update(object args);
+    }
+}

+ 103 - 0
MBI/SAGA.DotNetUtils/WPF/UserControl/WaitingCircle.xaml

@@ -0,0 +1,103 @@
+<UserControl x:Class="SAGA.DotNetUtils.WPF.UserControl.WaitingCircle"
+             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.DotNetUtils.WPF.UserControl"
+             mc:Ignorable="d" 
+             d:DesignHeight="50" d:DesignWidth="50" Height="{Binding Height, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UIElement}}" Width="{Binding Width, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UIElement}}">
+    <Grid>
+        <Grid.Resources>
+            <DrawingBrush x:Key="brush" Stretch="None" AlignmentX="Center" AlignmentY="Top">
+                <DrawingBrush.Drawing>
+                    <GeometryDrawing Brush="Black">
+                        <GeometryDrawing.Geometry>
+                            <EllipseGeometry RadiusX="2" RadiusY="5"/>
+                        </GeometryDrawing.Geometry>
+                    </GeometryDrawing>
+                </DrawingBrush.Drawing>
+            </DrawingBrush>
+        </Grid.Resources>
+
+        <Rectangle x:Name="r01" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="0"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r02" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="30"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r03" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="60"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r04" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="90"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r05" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="120"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r06" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="150"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r07" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="180"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r08" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="210"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r09" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="240"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r10" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="270"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r11" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="300"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Rectangle x:Name="r12" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
+            <Rectangle.RenderTransform>
+                <RotateTransform Angle="330"/>
+            </Rectangle.RenderTransform>
+        </Rectangle>
+        <Grid.Triggers>
+            <EventTrigger RoutedEvent="Grid.Loaded">
+                <BeginStoryboard>
+                    <Storyboard RepeatBehavior="Forever">
+                        <DoubleAnimation Storyboard.TargetName="r01" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.00000" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r02" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.08333" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r03" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.16666" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r04" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.24999" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r05" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.33332" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r06" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.41665" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r07" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.49998" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r08" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.58331" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r09" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.66664" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r10" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.74997" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r11" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.83330" To="0"/>
+                        <DoubleAnimation Storyboard.TargetName="r12" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.91663" To="0"/>
+                    </Storyboard>
+                </BeginStoryboard>
+            </EventTrigger>
+        </Grid.Triggers>
+    </Grid>
+</UserControl>

+ 28 - 0
MBI/SAGA.DotNetUtils/WPF/UserControl/WaitingCircle.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SAGA.DotNetUtils.WPF.UserControl
+{
+    /// <summary>
+    /// WaittingCircle.xaml 的交互逻辑
+    /// </summary>
+    public partial class WaitingCircle : System.Windows.Controls.UserControl
+    {
+        public WaitingCircle()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 33 - 0
MBI/SAGA.DotNetUtils/WPF/Windows/WinIndeterminationWaiting.xaml

@@ -0,0 +1,33 @@
+<Window x:Class="SAGA.DotNetUtils.WPF.Windows.WinIndeterminationWaiting" 
+             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.DotNetUtils.WPF.Windows"
+             xmlns:userControl="clr-namespace:SAGA.DotNetUtils.WPF.UserControl"
+             mc:Ignorable="d" Name="this" Height="200" Width="400"
+             d:DesignHeight="200" d:DesignWidth="400" BorderThickness="0" WindowStyle="None" AllowsTransparency="True"    Background="LightGray"  Opacity="0.7" WindowStartupLocation="CenterOwner">
+
+    <WindowChrome.WindowChrome>
+        <WindowChrome />
+    </WindowChrome.WindowChrome>
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition></RowDefinition>
+            <RowDefinition Height="50"></RowDefinition>
+            <RowDefinition></RowDefinition>
+        </Grid.RowDefinitions>
+        <Grid Grid.Row="1" Margin="10,0">
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="50"></ColumnDefinition>
+                <ColumnDefinition></ColumnDefinition>
+            </Grid.ColumnDefinitions>
+            <userControl:WaitingCircle></userControl:WaitingCircle>
+            <TextBlock FontSize="20" Grid.Column="1" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"  Text="{Binding Message,ElementName=this}" VerticalAlignment="Center" >
+                <TextBlock.ToolTip>
+                    <TextBlock Text="{Binding Message,ElementName=this}"></TextBlock>
+                </TextBlock.ToolTip>
+            </TextBlock>
+        </Grid>
+    </Grid>
+</Window>

+ 35 - 0
MBI/SAGA.DotNetUtils/WPF/Windows/WinIndeterminationWaiting.xaml.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SAGA.DotNetUtils.WPF.Windows
+{
+    /// <summary>
+    /// WinIndeterminationWaiting.xaml 的交互逻辑
+    /// </summary>
+    public partial class WinIndeterminationWaiting : Window
+    {
+        public WinIndeterminationWaiting()
+        {
+            InitializeComponent();
+        }
+        public string Message
+        {
+            get { return (string)GetValue(MessageProperty); }
+            set { SetValue(MessageProperty, value); }
+        }     
+        public static readonly DependencyProperty MessageProperty =
+            DependencyProperty.Register("Message", typeof(string), typeof(WinIndeterminationWaiting), new PropertyMetadata(""));
+    }
+}

+ 49 - 54
MBI/SAGA.GplotDrawData/DBView/EquipmentGraphView.cs

@@ -18,76 +18,71 @@ namespace SAGA.GplotDrawData
     {
         public override GraphDB AppendDb(DataNode dn, GraphDB db)
         {
-            #region 数据解析
-            //var inData = dn.Childrens;
-            //var muData = dn.Childrens.Where(t => t.Type == "母联柜").ToList();
-            //var n = inData.Count;
-            ////数字没什么意义
-            //var perHeight = 1500 / (n + 2d);
-            //var left = 100;
-            //for (int i = 1; i < n + 1; i++)
-            //{
-            //    var node = inData[i - 1];
-            //    //判断是否连接母联柜
-            //    var regex = new Regex($"{node.Sno},|,{node.Sno}");
-            //    var mu = muData.FirstOrDefault(d => regex.IsMatch(d.InLineNo));
-            //    node.Postition = new Point(left, perHeight * i);
-            //    //画当前点            
-            //    db.Elements.Add(CreateVertex(dn));
-            //    if (i == n) break;
-            //    if (mu != null)
-            //    {
-            //        mu.Postition = new Point(left, perHeight * i + perHeight / 2.0d);
-            //        //画母联柜
-            //        db.Elements.Add(CreateVertex(mu));
-            //        //画母联柜上下连线
-            //        var line1 = new GLine(node.Postition.ConvertToPoint3D(), mu.Postition.ConvertToPoint3D()) { ElementColor = Colors.Red };
-            //        var line2 = new GLine(mu.Postition.ConvertToPoint3D(), (new Point(left, perHeight * (i + 1))).ConvertToPoint3D()) { ElementColor = Colors.Red };
-            //        db.Elements.Add(line1);
-            //        db.Elements.Add(line2);
-            //        //移除母联柜
-            //        muData.Remove(mu);
-            //    }
-            //    else
-            //    {
-            //        var line1 = new GLine(node.Postition.ConvertToPoint3D(), (new Point(left, perHeight * (i + 1))).ConvertToPoint3D()) { ElementColor = Colors.Red };
-            //        db.Elements.Add(line1);
-            //    }
-            //} 
-            #endregion
 
             //var gNode = CreateTreeNode(dn);
             //db.Elements.Add(gNode);
             var settings = new JsonSerializerSettings();
+            var useData = CreateShowNode(dn);
             settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
             var serializer = JsonSerializer.Create(settings);
-            var jObject = JObject.FromObject(dn, serializer);
+            var jObject = JObject.FromObject(useData, serializer);
             db.RefJObjects.Add(jObject);
             return db;
         }
-
-        private GVertex CreateVertex(DataNode dn)
+        public DataShowNode CreateShowNode(DataNode dn)
         {
-            GVertex vertex = new GVertex();
-            vertex.Location = dn.Postition.ConvertToPoint3D();
-            vertex.ElementColor = Colors.Red;
-            vertex.IsSolid = true;
-            vertex.Radius = 5;
-            vertex.Name = dn.EName + "-" + dn.Type;
-            return vertex;
+            DataShowNode node = CreateSingleShowNode(dn);
+            foreach (var data in dn.Childrens)
+            {
+                if (!string.IsNullOrWhiteSpace(data.InLineNo1) && data.InLineNo1 == dn.Sno)
+                {
+                    var standyNode= CreateSingleShowNode(data);
+                    standyNode.IsStandby = true;
+                    node.Childrens.Add(standyNode);
+                }
+                else
+                {
+                    node.Childrens.Add(CreateShowNode(data));
+                }             
+            }
+            return node;
+        }
 
+        private DataShowNode CreateSingleShowNode(DataNode dn)
+        {
+            DataShowNode node = new DataShowNode();
+            node.EId = dn.EId;
+            node.EName = dn.EName;
+            node.Type = dn.Type;
+            return node;
         }
 
-        public GTreeNode CreateTreeNode(DataNode dn)
+        /// <summary>
+        /// 拓扑图绘图数据格式
+        /// </summary>
+        public class DataShowNode
         {
-            GTreeNode node = new GTreeNode();
-            node.NodeId = dn.EId;
-            node.Name = dn.EName;
-            foreach (var data in dn.Childrens)
+            public DataShowNode()
             {
-                node.Children.Add(CreateTreeNode(data));
+                this.Childrens = new List<DataShowNode>();
             }
-            return node;
+
+            public string EId { get; set; }
+            public string EName { get; set; }
+
+            /// <summary>
+            /// 子元素
+            /// </summary>
+            /// 历史原因,命名有错误
+            public List<DataShowNode> Childrens { get; set; }
+            /// <summary>
+            /// 设备类型
+            /// </summary>
+            public string Type { get; set; }
+            /// <summary>
+            /// 与父级连接关系是否备用
+            /// </summary>
+            public bool IsStandby { get; set; }
         }
     }
 }

+ 0 - 1
MBI/SAGA.GplotDrawData/DBView/SpaceGraphView.cs

@@ -7,7 +7,6 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Media;
-using Node=SAGA.Models.Graphs.GNode;
 
 namespace SAGA.GplotDrawData
 {

+ 3 - 2
MBI/SAGA.GplotDrawData/DBView/VerticalPipeGraphView.cs

@@ -56,12 +56,13 @@ namespace SAGA.GplotDrawData
                     var existPipe = pipes.FirstOrDefault(p => p.FloorId == floorId);
                     if (existPipe != null)
                     {
-                        existPipe.Name = existPipe.Name + "," + verData.Id;
+                        existPipe.Name = existPipe.Name + "," + verData.Display;
                         continue;
                     }
                     VPipe pipe = new VPipe();
                     pipe.LinkId = verData.Id;
-                    pipe.Name = verData.Id;
+                    pipe.Name = verData.Display;
+                    pipe.Tip = verData.DisplayTip;
                     pipe.PipeSystemType = verData.PipeSytemType;
                     pipe.FloorId = floorId;
                     pipes.Add(pipe);

+ 0 - 172
MBI/SAGA.GplotDrawData/DBView/VirticalSpaceGraphView.cs

@@ -87,178 +87,6 @@ namespace SAGA.GplotDrawData
         {
             return this.SpaceType == spaceType;
         }
-       
-        public  GraphDB AppendDb1(SpaceData td, GraphDB db)
-        {
-            var levels = td.LevelNames;
-
-            //按标高排序,按名称分组
-            double width = 1000;
-            var hoffset = 100;
-            var voffset = 100;
-            var hseq = 200;
-            var vseq = 100;
-            var start = new Point(hoffset, voffset);
-            var index = 1;
-            for (int i = 0; i < levels.Count; i++)
-            {
-                #region 画标高
-                var startTemp = new Point(start.X, start.Y + i * vseq);
-                var endTemp = new Point(start.X + width - 2 * hoffset - 100, start.Y + i * vseq);
-                var line2 = new GLine(startTemp.ConvertToPoint3D(), endTemp.ConvertToPoint3D()) { ElementColor = Colors.Red };
-                line2.Name = levels[i];
-                db.Elements.Add(line2);
-                //加文字描述
-                var vertex = new GVertex();
-                vertex.Location = endTemp.ConvertToPoint3D();
-                vertex.Name = levels[i];
-                db.Elements.Add(vertex);      
-                #endregion
-
-                #region 画空间立面关系
-                //获取当前层的数据
-                var curData = td.FloorDatas.FirstOrDefault(t => t.LevelName == levels[i]);
-                if (curData == null) continue;
-                //空间标记不空
-                var theLevelSpaces = curData.EndPoints.Where(t => t.RoomFuncType != "").ToList();
-                #endregion
-                for (int j = 0; j < theLevelSpaces.Count; j++)
-                {
-                    index++;
-                    var x = start.X + index * 50;
-                    GetUpSpace(theLevelSpaces[j], new Point(x, start.Y), db, i, vseq, levels, td.FloorDatas);
-                }
-
-            }
-            return db;
-        }
-
-     
-
-        private void GetUpSpace(SgSpace space, Point start, GraphDB db, int level, double vseq, List<string> levelNames, List<FloorSpaceData> floorSpaces)
-        {
-            if (space.RoomFuncType == "") return;
-            var line2 = new GLine(start.ConvertToPoint3D(), new Point(start.X, start.Y +vseq).ConvertToPoint3D()) { ElementColor = Colors.Green };
-            db.Elements.Add(line2);
-;           var vertex = new GVertex();
-            vertex.Location = start.ConvertToPoint3D();
-            vertex.Name = Regex.Replace(space.Name, @"\s\d+", "");
-            db.Elements.Add(vertex);
-            if (space.UpElements.Count > 0)
-            {
-                var theSpace = space.UpElements.FirstOrDefault(t =>string.IsNullOrEmpty(t.Space.RoomFuncType));
-                if (theSpace == null) return;
-                level++;
-                //从上层数据中移除这个数据
-                var upFloorSpaces = floorSpaces.FirstOrDefault(t => t.LevelName == levelNames[level]);
-                //一级元素才存储UpElements才会有值,所以这里需要做一个转化
-
-                var upSpace = upFloorSpaces.EndPoints.FirstOrDefault(t => t.Id == theSpace.Space.Id);
-                if (upSpace != null)
-                {
-                    upFloorSpaces.EndPoints.Remove(upSpace);
-                    GetUpSpace(upSpace,new Point(line2.End.X,line2.End.Y), db, level, vseq, levelNames, floorSpaces);
-                }
-
-            }
-            else
-            {
-                //return;
-                level++;
-                if (level > levelNames.Count - 1) return;
-                //取出上层数据
-                var upFloorSpaces = floorSpaces.FirstOrDefault(t => t.LevelName == levelNames[level]);
-                if (upFloorSpaces == null)
-                {
-                    GetUpSpace(space, start, db, level, vseq, levelNames, floorSpaces);
-                }
-                else//根据轮廓进行比较
-                {
-                    //当前空间的轮廓与此层所有的空间轮廓进行比较
-                    var sgSpace = upFloorSpaces.EndPoints.Where(t => t.RoomFuncType == space.RoomFuncType).FirstOrDefault(t => JudgeTwoLineIntersect(t.BoundarySegment, space.BoundarySegment));
-                    if (sgSpace != null)
-                    {
-
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// 闭合区域,没有包含关系
-        /// </summary>
-        /// <param name="curve1"></param>
-        /// <param name="curve2"></param>
-        /// <returns></returns>
-        private bool JudgeTwoLineIntersect(List<List<Point>> close1, List<List<Point>> close2)
-        {
-            for (int i = 0; i < close1.Count - 1; i++)
-            {
-                for (int j = 0; j < close2.Count - 1; j++)
-                {
-                    if (JudgeTwoLineIntersect(close1[i], close2[j]))
-                    {
-                        return true;
-                    }
-                }
-            }
-
-            //TODO:判断是否包含,下面有点是否在闭合区域内
-            return false;
-        }
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="curve1"></param>
-        /// <param name="curve2"></param>
-        /// <returns></returns>
-        public bool JudgeTwoLineIntersect(List<Point> curve1, List<Point> curve2)
-        {
-            for (int i = 0; i < curve1.Count - 1; i++)
-            {
-                for (int j = 0; j < curve2.Count - 1; j++)
-                {
-                    if (JudgeTwoLineIntersect(curve1[i], curve1[i + 1], curve2[j], curve2[j + 1]))
-                    {
-                        return true;
-                    }
-                }
-            }
-            return false;
-        }
-        /// <summary>
-        /// 两条直线是否相交
-        /// </summary>
-        /// <param name="a"></param>
-        /// <param name="b"></param>
-        /// <param name="c"></param>
-        /// <param name="d"></param>
-        /// <returns></returns>
-        bool JudgeTwoLineIntersect(Point a, Point b, Point c, Point d)
-        {
-            /*
-            快速排斥:
-            两个线段为对角线组成的矩形,如果这两个矩形没有重叠的部分,那么两条线段是不可能出现重叠的
-            */
-            if (!(Math.Min(a.X, b.X) <= Math.Max(c.X, d.X) && Math.Min(c.Y, d.Y) <= Math.Max(a.Y, b.Y) && Math.Min(c.X, d.X) <= Math.Max(a.X, b.X) && Math.Min(a.Y, b.Y) <= Math.Max(c.Y, d.Y)))//这里的确如此,这一步是判定两矩形是否相交
-                                                                                                                                                                                                //1.线段ab的低点低于cd的最高点(可能重合) 2.cd的最左端小于ab的最右端(可能重合)
-                                                                                                                                                                                                //3.cd的最低点低于ab的最高点(加上条件1,两线段在竖直方向上重合) 4.ab的最左端小于cd的最右端(加上条件2,两直线在水平方向上重合)
-                                                                                                                                                                                                //综上4个条件,两条线段组成的矩形是重合的
-                                                                                                                                                                                                /*特别要注意一个矩形含于另一个矩形之内的情况*/
-                return false;
-            /*
-            跨立实验:
-            如果两条线段相交,那么必须跨立,就是以一条线段为标准,另一条线段的两端点一定在这条线段的两段
-            也就是说a b两点在线段cd的两端,c d两点在线段ab的两端
-            */
-            double u, v, w, z;//分别记录两个向量
-            u = (c.X - a.X) * (b.Y - a.Y) - (b.X - a.X) * (c.Y - a.Y);
-            v = (d.X - a.X) * (b.Y - a.Y) - (b.X - a.X) * (d.Y - a.Y);
-            w = (a.X - c.X) * (d.Y - c.Y) - (d.X - c.X) * (a.Y - c.Y);
-            z = (b.X - c.X) * (d.Y - c.Y) - (d.X - c.X) * (b.Y - c.Y);
-            return (u * v <= 0.00000001 && w * z <= 0.00000001);
-        }
-
         /// <summary>
         /// 空间分组信息
         /// </summary>

+ 2 - 0
MBI/SAGA.GplotDrawData/WinControlRelation-Web.xaml.cs

@@ -170,6 +170,8 @@ namespace SAGA.GplotDrawData
                             var data = InDataNodes.FirstOrDefault(d => d.EId == currNode.EId);
                             if (data != null)
                             {
+                                //该节点需要重新处理如果是通过备用标志关联,则不构建其下级关联信息;
+                                //链表信息不合适会造成操作上的不方便
                                 Draw(data);
                                 RevitModelFileUpload.ShowSpaceProperty(data.EId);
                             }

+ 6 - 31
MBI/SAGA.GplotDrawData/WinDrawSpace-Web.xaml.cs

@@ -38,26 +38,9 @@ namespace SAGA.GplotDrawData
 
             this.m_showType = showType;
             this.Loaded += WinDrawWaterNode_Loaded;
-            //ucShowElement.ComputerAction = () =>
-            //{
-            //    ComputerAction.Invoke();
-            //    WinDrawWaterNode_Loaded(null, null); //重新加载数据
-            //};
-
-            //ucShowElement.SaveAction = () =>
-            //{
-            //    RevitModelFileUpload.FileUpload();
-            //};
         }
         private bool IsRead = true;
-        private DataNode m_data;
-        private WallData m_wallData;
-
-        public WinDrawSpace_Web(DataNode node) : this()
-        {
 
-
-        }
         private void WinDrawWaterNode_Loaded(object sender, RoutedEventArgs e)
         {
             if (m_showType == GplotShowType.VerticalPlan)
@@ -72,9 +55,6 @@ namespace SAGA.GplotDrawData
             {
                 var node = GetSpaceData();
                 this.rootNode.ItemsSource = new List<DataNode>() { node };
-                m_data = node;
-                //读取墙数据
-                m_wallData = DrawDataServer.GetWallData();
             }
         }
         #region 立面空间处理
@@ -152,7 +132,7 @@ namespace SAGA.GplotDrawData
             DataNode root = new DataNode("空间关系");
             DataNode a = new DataNode("空间临接关系")
             {
-                Childrens = aData.FloorDatas.Select(f =>
+                Childrens = aData.FloorDatas.Reverse<FloorSpaceData>().Select(f =>
                 {
                     var dn = new DataNode(f.Name);
                     dn.SetData(f);
@@ -162,7 +142,7 @@ namespace SAGA.GplotDrawData
 
             DataNode t = new DataNode("建筑交通关系")
             {
-                Childrens = tData.FloorDatas.Select(f =>
+                Childrens = tData.FloorDatas.Reverse<FloorSpaceData>().Select(f =>
                 {
                     var dn = new DataNode(f.Name);
                     dn.SetData(f);
@@ -171,7 +151,7 @@ namespace SAGA.GplotDrawData
             };
             DataNode v = new DataNode("空气流通关系")
             {
-                Childrens = vData.FloorDatas.Select(f =>
+                Childrens = vData.FloorDatas.Reverse<FloorSpaceData>().Select(f =>
                 {
                     var dn = new DataNode(f.Name);
                     dn.SetData(f);
@@ -180,7 +160,7 @@ namespace SAGA.GplotDrawData
             };
             DataNode r = new DataNode("光照辐射关系")
             {
-                Childrens = rData.FloorDatas.Select(f =>
+                Childrens = rData.FloorDatas.Reverse<FloorSpaceData>().Select(f =>
                 {
                     var dn = new DataNode(f.Name);
                     dn.SetData(f);
@@ -189,15 +169,10 @@ namespace SAGA.GplotDrawData
             };
             root.Childrens.AddRange(new List<DataNode>() { a, t, v, r });
             return root;
-        }
-
-   
+        }   
         /// <summary>
         /// 外部命令启动计算
         /// </summary>
-        public Action ComputerAction;
-
-
-      
+        public Action ComputerAction;      
     }
 }

+ 3 - 3
MBI/SAGA.GplotManage/GplotCommand.cs

@@ -5,6 +5,7 @@ using Autodesk.Revit.DB;
 using Autodesk.Revit.UI;
 using SAGA.GplotDrawData;
 using SAGA.GplotManage.UploadRelated;
+using SAGA.MBI.Common;
 using SAGA.Models;
 using SAGA.RevitUtils.Extends;
 
@@ -18,10 +19,9 @@ namespace SAGA.GplotManage
     public class SpaceComputerGraph : ExternalCommand
     {
         public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
-        {
+        {        
             var space = GplotFactory.Create(GraphTypeEnum.ElementSpNeighborhood);
-            space.Show(GplotShowType.ViewPlan);
-      
+            space.Show(GplotShowType.ViewPlan);           
             return Result.Succeeded;
         }
 

+ 0 - 1
MBI/SAGA.GplotRelationComputerManage/Command.cs

@@ -50,7 +50,6 @@ namespace SAGA.GplotRelationComputerManage
     {
         public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
         {
-
             #region 核心
             try
             {

+ 38 - 33
MBI/SAGA.GplotRelationComputerManage/ComputerPipes.cs

@@ -5,64 +5,69 @@
  * ==============================================================================*/
 
 
+using System;
 using SAGA.GplotRelationComputerManage.PumpEnd;
 using SAGA.RevitUtils.Extends;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
-using System.Text.RegularExpressions;
 using Autodesk.Revit.DB.Plumbing;
 using Autodesk.Revit.DB;
+using SAGA.RevitUtils;
+
 namespace SAGA.GplotRelationComputerManage
 {
     public class ComputerPipes
     {
         public static void Computer()
         {
-            //记录立管
-            //List<Pipe> verticalPipe = new List<Pipe>();
-            Dictionary<Level, List<Pipe>> dicVerticalPipes = new Dictionary<Level, List<Pipe>>();
-            //打开所有楼层数据
-            // var fileInfos = RevitModelPath.GetAllRevitFiles();//.Where(t=>Regex.IsMatch(t, "Fl1101080003e883286bb63d11e8b92a092227bd993a"));//B2
-            var fileInfos = RevitModelPath.GetAllRevitFiles();//.Where(t=>Regex.IsMatch(t, "ee2c4"));//Test
+            //打开所有楼层数据     
+            PipeCalcContext context = new PipeCalcContext();
+            var fileInfos = RevitModelPath.GetAllRevitFiles();
             foreach (var fileInfo in fileInfos)
             {
                 if (File.Exists(fileInfo))
                 {
                     var uiApp = ExternalDataWrapper.Current.UiApp.Application;
                     var doc = uiApp.OpenDocumentFile(fileInfo);
-                    new ExternalDataWrapper(doc);
-                   
-                    List<Pipe> verticalPipe = new List<Pipe>();
-                    //计算水管
-                   DuctTerminalBll.DrawPipePlane(false, verticalPipe);
-                    #region 立管处理
-                    //立管处理,分楼层存储 
-                    var usePlan = doc.GetViewPlan().Where(p => p.Name.Contains("-saga"))?.FirstOrDefault();
-                    var currentLevel = usePlan?.GenLevel;
-                    if (usePlan == null)
+                    if (doc == null)
+                        continue;
+                    try
                     {
-                        currentLevel = verticalPipe.FirstOrDefault()?.ReferenceLevel;
+                        new ExternalDataWrapper(doc);
+                        List<Pipe> verticalPipes = new List<Pipe>();
+                        //计算水管
+                        DuctTerminalBll.DrawPipePlane(false, verticalPipes);
+                        #region 立管处理
+                        ComputerVerticalPipe computerPipes = new ComputerVerticalPipe(doc);
+                        //立管处理,分楼层存储 
+                        var usePlan = doc.GetViewPlan().Where(p => p.Name.Contains("-saga"))?.FirstOrDefault();
+                        var currentLevel = usePlan?.GenLevel;
+                        if (usePlan == null)
+                        {
+                            currentLevel = verticalPipes.FirstOrDefault()?.ReferenceLevel;
+                        }
+                        //楼层必须要有,管道不一定要有
+                        if (currentLevel != null)
+                        {
+                            computerPipes.ComputerVerticalPipes(currentLevel, verticalPipes, context);
+                        }
+                        #endregion
+                        //计算风管
+                        DuctTerminalBll.DrawDuct();
                     }
-                    //楼层必须要有,管道不一定要有
-                    if (currentLevel != null)
+                    catch (System.Exception ex)
                     {
-                        dicVerticalPipes.Add(currentLevel, verticalPipe);
-                    }
 
-                    #endregion
-                    //计算风管
-                    DuctTerminalBll.DrawDuct();
+                        Console.WriteLine(ex.Message);
+                    }
+                    finally
+                    {
+                        doc.Close();
+                    }
                 }
             }
-
-            
-            //计算立管
-            //if(ExternalDataWrapper.Current?.Doc==null)return;
-            //var levels =ExternalDataWrapper.Current.Doc.GetLevels();
-            var pipeComputer = new ComputerVerticalPipe();
-            pipeComputer.Computer(dicVerticalPipes);
+            ComputerVerticalPipe.Computer(context);
         }
-     
     }
 }

+ 139 - 37
MBI/SAGA.GplotRelationComputerManage/ComputerVerticalPipe.cs

@@ -6,82 +6,184 @@
 
 using Autodesk.Revit.DB;
 using Autodesk.Revit.DB.Plumbing;
-
-using SAGA.GplotDrawData;
-using SAGA.MBI;
 using SAGA.Models;
 using SAGA.RevitUtils.Extends;
-
-using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Windows.Controls;
 using System.Windows.Media.Media3D;
-using Point = System.Windows.Point;
+using Autodesk.Revit.DB.Mechanical;
+using Newtonsoft.Json.Linq;
+using SAGA.MBI.RequestData;
+using SAGA.RevitUtils;
+
 namespace SAGA.GplotRelationComputerManage
 {
-    public class ComputerVerticalPipe
+    /// <summary>
+    /// 计算上下文
+    /// </summary>
+    public class PipeCalcContext
     {
-        public void Computer(Dictionary<Level, List<Pipe>> dicPipes)
+        public PipeCalcContext()
+        {
+            VerticalPipes = new List<VerticalPipe>();
+            Levels = new List<LevelData>();
+        }
+        #region 空间缓存信息
+        /// <summary>
+        /// 缓存空间对象
+        /// </summary>
+        private Dictionary<string, RoomItem> m_Rooms = null;
+        /// <summary>
+        /// 获取根据指定bimId,获取空间信息
+        /// </summary>
+        /// <param name="bimId"></param>
+        /// <returns></returns>
+        public RoomItem GetRoomItem(string bimId)
         {
-            List<VerticalPipe> pipes = new List<VerticalPipe>();
-            foreach (var dicPipe in dicPipes)
+            if (m_Rooms == null)
             {
-                   var vps = ConvertTo(dicPipe.Key,dicPipe.Value);
-                pipes.AddRange(vps);
+                m_Rooms = new Dictionary<string, RoomItem>();
+                var str = new string[] { MBIBuiltInCategory.Si };//元空间为Si
+                List<JObject> datas = CommonConvert.QueryObjectInfoByTypes(str);
+                foreach (var data in datas)
+                {
+                    var roomItem = MBIItemFactory.Create<RoomItem>(data);
+                    m_Rooms[roomItem.BimId] = roomItem;
+                }
             }
 
-            var levels = dicPipes.Keys.ToList();
-            levels.Sort((l1, l2) => l1.Elevation.CompareTo(l2.Elevation));
-            var levelDatas = levels.Select(t => new LevelData()
-            {
-                Id = t.Id.ToString(),
-                Name = t.Name.Replace("-saga",""),
-                Elevation = t.Elevation
-            }).ToList();
+            m_Rooms.TryGetValue(bimId, out RoomItem resultItem);
+            return resultItem;
+        }
 
 
-            var datas = new VerticalPipeData()
+        #endregion
+        #region 空间缓存约束
+        public string GetSpaceDisplay(Space space)
+        {
+            if (space == null)
+                return string.Empty;
+            string bimId = space.GetBimId();
+            var room = GetRoomItem(bimId);
+            string useName = space.Name;
+            if (room != null&&!string.IsNullOrWhiteSpace(room.LocalName))
             {
-                Datas = pipes,
-                Levels = levelDatas
-            };
+                useName = room.LocalName;
+            }
+            //此类缓存所有空间信息
+            //本地名称为null的话要使用Name
+            return useName;
+        }
+        public string GetSpaceDisplay(Space space,out string tip)
+        {
+            tip = string.Empty;
+            if (space == null)
+            {
+                tip = $"未知空间:BIMID编码";
+                return "未知";//string.Empty;
+            }        
+            string bimId = space.GetBimId();
+            var room = GetRoomItem(bimId);
+            string useName = space.Name;
+            tip =$"空间模型名称:BIMID编码";
+            if (room != null && !string.IsNullOrWhiteSpace(room.LocalName))
+            {
+                tip = $"空间本地名称:BIMID编码";
+                useName = room.LocalName;
+            }
 
-            //保存数据到本地
-            DrawDataServer.SaveAsFile(datas);
+            //此类缓存所有空间信息
+            //本地名称为null的话要使用Name
+            return useName;
         }
+        #endregion
+
+        public List<VerticalPipe> VerticalPipes { get; private set; }
+        public List<LevelData> Levels { get; private set; }
+    }
 
-        private List<VerticalPipe> ConvertTo(Level refLevel,List<Pipe> data)
+    public class ComputerVerticalPipe
+    {
+        public Document Document { get; private set; }
+        public ComputerVerticalPipe(Document document)
+        {
+            Document = document;
+        }
+        #region 修订函数
+        /// <summary>
+        /// 计算立管信息
+        /// </summary>
+        /// <param name="refLevel"></param>
+        /// <param name="pipes"></param>
+        /// <param name="context"></param>
+        public void ComputerVerticalPipes(Level refLevel, List<Pipe> pipes, PipeCalcContext context)
         {
             var result = new List<VerticalPipe>();
-
-            foreach (var pipe in data)
+            var spaces = Document.GetElements<SpatialElement>(BuiltInCategory.OST_MEPSpaces).OfType<Space>();
+            foreach (var pipe in pipes)
             {
-                var level =refLevel;
-
+                if (pipe == null)
+                    continue;
+                var level = refLevel;
                 var vp = new VerticalPipe
                 {
-                    Id = pipe.Id.IntegerValue.ToString(),
-                    LevelName = level.Name.Replace("-saga",""),
+                    Id=pipe.Id.IntegerValue.ToString(),
+                    LevelName = level.Name.Replace("-saga", ""),
                     LevelElevation = level.Elevation,
                     UpPoint3D = Convert3DToWin(pipe.GetVerticalTopPoint()),
                     DownPoint3D = Convert3DToWin(pipe.GetVerticalBottomPoint()),
                     PipeSytemType = pipe.GetParameterString(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM)
                 };
+                //获取立管关联控件
+                var locationCurve = pipe.GetLocationCurve();
+                var midPoint = (locationCurve.StartPoint() + locationCurve.EndPoint()) / 2;
+                Space refSpace = spaces.FirstOrDefault(s => s.IsPointInSpace(midPoint));//关联
+                var display = context.GetSpaceDisplay(refSpace, out string tip);
+                vp.Display = $"{display}:{pipe.Id.IntegerValue.ToString()}";
+                vp.DisplayTip = tip ?? string.Empty;
                 result.Add(vp);
             }
+            LevelData levelData = new LevelData()
+            {
+                Id = refLevel.Id.ToString(),
+                Name = refLevel.Name.Replace("-saga", ""),
+                Elevation = refLevel.Elevation
+            };
+            context.VerticalPipes.AddRange(result);
+            context.Levels.Add(levelData);
+        }
 
-            return result;
+        /// <summary>
+        /// 计算整体信息
+        /// </summary>
+        /// <param name="context"></param>
+        public static void Computer(PipeCalcContext context)
+        {
+            var verticalPipes = context.VerticalPipes;
+            if (verticalPipes == null)
+                return;
+            List<VerticalPipe> pipes = new List<VerticalPipe>(verticalPipes);
+            var levels = new List<LevelData>(context.Levels);
+            levels.Sort((l1, l2) => l1.Elevation.CompareTo(l2.Elevation));
+
+            var datas = new VerticalPipeData()
+            {
+                Datas = pipes,
+                Levels = levels
+            };
+            //保存数据到本地
+            DrawDataServer.SaveAsFile(datas);
         }
+        #endregion
 
 
 
-        Point3D Convert3DToWin(XYZ xyz)
+        private static Point3D Convert3DToWin(XYZ xyz)
         {
             return new Point3D(xyz.X, xyz.Y, xyz.Z);
         }
 
-        XYZ Convert3DToRevit(Point3D point)
+        private static XYZ Convert3DToRevit(Point3D point)
         {
             return new XYZ(point.X, point.Y, point.Z);
         }

+ 5 - 2
MBI/SAGA.GplotRelationComputerManage/PowerDistribution/Common/DataNodeUtil.cs

@@ -37,13 +37,16 @@ namespace SAGA.GplotRelationComputerManage
             List<DataNode> standbyNodes = new List<DataNode>();
             foreach (var sourceNode in sourceNodes)
             {
+                if (sourceNode.Sno == baseNo)
+                {
+                    continue;
+                }
                 if (sourceNode.InLineNo == baseNo)
                 {
                     sourceNode.Parent = node;
                     mainNodes.Add(sourceNode);
                 }
-
-                if (sourceNode.InLineNo1 == baseNo)
+                else if(sourceNode.InLineNo1 == baseNo)
                 {
                     sourceNode.Parent = node;
                     standbyNodes.Add(sourceNode);

+ 1 - 1
MBI/SAGA.GplotRelationComputerManage/PumpEnd/DrawEnd.cs

@@ -9,6 +9,7 @@ using System.Collections.Generic;
 using System.Drawing;
 using System.Drawing.Drawing2D;
 using System.Linq;
+using System.Runtime.Caching;
 using System.Text.RegularExpressions;
 using System.Windows;
 using System.Windows.Media.Media3D;
@@ -569,7 +570,6 @@ namespace SAGA.GplotRelationComputerManage.PumpEnd
                             foreach (var sgSpace in levelSpaces.EndPoints)
                             {
                                 #region 点在区域内判断
-
                                 GraphicsPath myGraphicsPath = new GraphicsPath();
                                 Region myRegion = new Region();
                                 myGraphicsPath.Reset();

+ 1 - 1
MBI/SAGA.GplotRelationComputerManage/PumpEnd/DuctTerminalBll.cs

@@ -46,7 +46,7 @@ namespace SAGA.GplotRelationComputerManage.PumpEnd
         /// <summary>
         /// 计算风管
         /// </summary>
-        /// <param name="datas"></param>
+    
         public static void DrawDuct()
         {
             var doc = ExternalDataWrapper.Current.Doc;

+ 27 - 15
MBI/SAGA.GplotRelationComputerManage/ReadSpaceCommand.cs

@@ -11,7 +11,9 @@ using SAGA.DotNetUtils.Extend;
 using SAGA.MBI.DataArrange;
 using SAGA.MBI.Model;
 using SAGA.MBI.RequestData;
+using SAGA.MBI.Tools;
 using SAGA.Models;
+using SAGA.RevitUtils;
 using SAGA.RevitUtils.Extends;
 using Point = System.Windows.Point;
 
@@ -82,29 +84,39 @@ namespace SAGA.GplotRelationComputerManage
         {
             //缓存所有空间数据
             //查询所有设备
-             var str = new string[] { "Si" };//元空间为Si
-            List<JObject> datas = CommonConvert.QueryObjectInfoByTypes(str);
-            m_dicServerSpace = new Dictionary<string, JObject>();
-            datas.ForEach(t =>
-            {
-                var bimId = GetValue(t, "BIMID");
-                if (!string.IsNullOrEmpty(bimId))
-                {
-                    m_dicServerSpace[bimId] = t;
-                }
-
-            });
+            // var str = new string[] { "Si" };//元空间为Si
+            //List<JObject> datas = CommonConvert.QueryObjectInfoByTypes(str);
+            //m_dicServerSpace = new Dictionary<string, JObject>();
+            //datas.ForEach(t =>
+            //{
+            //    var bimId = GetValue(t, "BIMID");
+            //    if (!string.IsNullOrEmpty(bimId))
+            //    {
+            //        m_dicServerSpace[bimId] = t;
+            //    }
+
+            //});
             //打开所有楼层数据
+            //Stopwatch watch = new Stopwatch();
+            //watch.Start();
             var fileInfos = RevitModelPath.GetAllRevitFiles();//.Where(t => t.IndexOf("71062c") > -1);
+            SpaceComputerContext context = new SpaceComputerContext();
             foreach (var fileInfo in fileInfos)
             {
                 if (File.Exists(fileInfo))
                 {
-                    var uiApp = ExternalDataWrapper.Current.UiApp.Application;
-                    var doc = uiApp.OpenDocumentFile(fileInfo);   
-                    ComputerSpace(doc);
+                    //var uiApp = ExternalDataWrapper.Current.UiApp.Application;
+                   // var doc = uiApp.OpenDocumentFile(fileInfo);
+                    FloorSpaceItems floorItems = context.GetFloorItems(fileInfo);
+                    floorItems.Parse(context);
+                    //if(floorItems.Document.Application.Creat)
+                    floorItems.Document.CloseDocSimple();
+                    //ComputerSpace(doc);
                 }
             }
+            //MessageShow.Infomation((watch.ElapsedMilliseconds / 1000).ToString());
+            //watch.Stop();
+            //MessageShow.Infomation((watch.ElapsedMilliseconds / 1000).ToString());
         }
 
         /// <summary>

+ 5 - 1
MBI/SAGA.GplotRelationComputerManage/RevitModelPath.cs

@@ -26,9 +26,13 @@ namespace SAGA.GplotRelationComputerManage
             }
             if (FilePaths.Count == 0)
             {//TODO:有测试
+                List<string> files = new List<string>();
                 var projectFloors = DalModeFileManange.GetMissFileFloors(false);//.Where(t => t.Item.LocalName == "大师傅地方").ToList();
 
-                projectFloors.ForEach((tni) => GetFilePaths(tni, FilePaths));
+                projectFloors.ForEach((tni) => GetFilePaths(tni, files));
+                files.Reverse();
+                FilePaths = new List<string>(files);
+
             }
 
             return FilePaths;

+ 5 - 0
MBI/SAGA.GplotRelationComputerManage/SAGA.GplotRelationComputerManage.csproj

@@ -64,6 +64,7 @@
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.IO.Compression" />
+    <Reference Include="System.Runtime.Caching" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.ServiceModel" />
     <Reference Include="System.Transactions" />
@@ -108,10 +109,14 @@
     <Compile Include="RevitSystemParse\Handler\SystemParseSetting.cs" />
     <Compile Include="RevitSystemParse\StartElementsManager.cs" />
     <Compile Include="SpaceEdgeInfo.cs" />
+    <Compile Include="SpaceRelation\ComputerSpaceItem.cs" />
     <Compile Include="SpaceRelation\FloorSpaceItems.cs" />
     <Compile Include="SpaceRelation\SpaceComputerContext.cs" />
     <Compile Include="SpaceRelation\SpaceComputerHandler.cs" />
     <Compile Include="SpaceRelation\SpaceComputerManager.cs" />
+    <Compile Include="SystemRelation\Common\SystemCalcUtil.cs" />
+    <Compile Include="SystemRelation\FloorSystemItems.cs" />
+    <Compile Include="SystemRelation\SystemComputerContext.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\SAGA.GplotDrawData\SAGA.GplotDrawData.csproj">

+ 149 - 0
MBI/SAGA.GplotRelationComputerManage/SpaceRelation/ComputerSpaceItem.cs

@@ -0,0 +1,149 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:ComputerSpaceItem
+ * 作者:xulisong
+ * 创建时间: 2018/12/24 17:22:10
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.DB.Mechanical;
+using SAGA.DotNetUtils.Extend;
+using SAGA.RevitUtils;
+using SAGA.RevitUtils.Extends;
+
+namespace SAGA.GplotRelationComputerManage
+{
+    /// <summary>
+    /// 计算相关信息
+    /// </summary>
+    public class ComputerSpaceItem
+    {
+        public ComputerSpaceItem(Space space)
+        {
+            this.Space = space;
+            this.BimId = space.GetBimId();
+            var mySegments = space.GetBoundarySegments(new SpatialElementBoundaryOptions());
+            OriginCurves = new List<Curve>();
+            var seg = mySegments.FirstOrDefault();
+            if (seg != null)
+            {
+                this.OriginCurves = mySegments[0].Select(s => s.GetCurve()).ToList();
+            
+            }
+            this.ZeroCurves = TransfomCurvesToZero(OriginCurves);
+        }
+        public Space Space { get; private set; }
+        /// <summary>
+        /// bimId
+        /// </summary>
+        public string BimId { get; set; }
+        /// <summary>
+        /// 空间功能类型
+        /// </summary>
+        public string FuncType { get; set; }
+        /// <summary>
+        /// 原始边框
+        /// </summary>
+        public List<Curve> OriginCurves { get; set; }
+        /// <summary>
+        /// 投影边框
+        /// </summary>
+        public List<Curve> ZeroCurves { get; set; }
+        /// <summary>
+        /// 标志是否被处理
+        /// </summary>
+        public bool IsHandled { get; set; }
+
+        #region 包围盒构件
+        private Outline m_Box;
+
+        public Outline Box
+        {
+            get
+            {
+                if (m_Box == null)
+                {
+                    List<double> listX = new List<double>();
+                    List<double> listY = new List<double>();
+                    ZeroCurves.ForEach(c =>
+                    {
+                        var listXYZ = new List<XYZ>(c.Tessellate());
+                        listXYZ.ForEach(xyz =>
+                        {
+                            listX.Add(xyz.X);
+                            listY.Add(xyz.Y);
+                        });
+                    });
+                    var tupleX = GetMaxMin(listX);
+                    var tupleY = GetMaxMin(listY);
+                    if (tupleX == null || tupleY == null)
+                    {
+                        m_Box = new Outline(XYZ.Zero,XYZ.Zero);
+                    }
+                    else
+                    {
+                        double coff = 1;//扩充误差
+                        m_Box = new Outline(new XYZ(tupleX.Item2 - coff, tupleY.Item2 - coff,0),new XYZ(tupleX.Item1 + coff, tupleY.Item1+ coff,0));
+                       
+                    }
+                    
+                }
+                return m_Box;
+            }
+        }
+
+        #endregion
+
+        #region 私有方法
+        private List<Curve> TransfomCurvesToZero(List<Curve> curves)
+        {
+            var zeroCurves = new List<Curve>();
+            if (curves != null)
+            {
+                var z = curves.FirstOrDefault()?.StartPoint()?.Z;
+                Transform tf = Transform.CreateTranslation(XYZ.Zero.NewZ(0 - z));
+                foreach (var curve in curves)
+                {
+                    zeroCurves.Add(curve.CreateTransformed(tf));
+                }
+            }
+            return zeroCurves;
+        }
+
+        /// <summary>
+        /// 取出集合的最大值和最小值Item1,最大值,Item2,最小值
+        /// </summary>
+        /// <param name="list"></param>
+        /// <returns></returns>
+        public Tuple<double, double> GetMaxMin(List<double> list)
+        {
+            if (list == null || !list.Any())
+            {
+                return null;
+            }
+            double min = list[0];
+            double max = list[0];
+            for (int i = 1; i < list.Count; i++)
+            {
+                var current = list[i];
+                if (current > max)
+                {
+                    max = current;
+                }
+
+                if (current < min)
+                {
+                    min = current;
+                }
+            }
+            return new Tuple<double, double>(max, min);
+        }
+
+        #endregion
+    }
+}

+ 364 - 13
MBI/SAGA.GplotRelationComputerManage/SpaceRelation/FloorSpaceItems.cs

@@ -9,14 +9,37 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text.RegularExpressions;
 using Autodesk.Revit.DB;
 using Autodesk.Revit.DB.Mechanical;
 using FWindSoft.Data;
 using SAGA.DotNetUtils.Extend;
+using SAGA.MBI.DataArrange;
+using SAGA.MBI.Model;
+using SAGA.Models;
+using SAGA.RevitUtils;
 using SAGA.RevitUtils.Extends;
 
-namespace SAGA.GplotRelationComputerManage.SpaceRelation
+namespace SAGA.GplotRelationComputerManage
 {
+    [Flags]
+    public enum AdjanceElementType
+    {
+        None=0,
+        Wall=1,
+        VirtualWall=1<<1,
+        Door=1<<2,
+        Window=1<<3,
+        /// <summary>
+        /// 垂直邻接
+        /// </summary>
+        Vertical=1<<4,
+        /// <summary>
+        /// 垂直洞口,交通
+        /// </summary>
+        VerticalOpening = 1 << 5,
+    }
+
     /// <summary>
     ///模型解析对应的楼层空间数据
     /// </summary>
@@ -30,9 +53,11 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
         public FloorSpaceItems(Document doc)
         {
             Document = doc;
-            Doors = new List<FamilyInstance>();
-            Windows = new List<FamilyInstance>();
+            Doors = new Dictionary<string, List<FamilyInstance>>();
+            Windows = new Dictionary<string, List<FamilyInstance>>();
             Spaces = new List<Space>();
+            ComputerSpaceItems = new List<ComputerSpaceItem>();
+            InitData();
         } 
         #endregion
 
@@ -44,30 +69,214 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
         /// <summary>
         /// 关联门信息
         /// </summary>
-        public List<FamilyInstance> Doors { get; private set; }
+        public Dictionary<string,List<FamilyInstance>> Doors { get; private set; }
         /// <summary>
         /// 关联窗体信息
         /// </summary>
-        public List<FamilyInstance> Windows { get; private set; }
+        public Dictionary<string, List<FamilyInstance>> Windows { get; private set; }
         /// <summary>
         /// 关联空间信息
         /// </summary>
-        public List<Space> Spaces { get; private set; } 
+        public List<Space> Spaces { get; private set; }
+
+        /// <summary>
+        /// 空间计算数据
+        /// </summary>
+        public List<ComputerSpaceItem> ComputerSpaceItems { get; private set; }
         #endregion
 
+        private bool m_IsInited;
+        public void InitData()
+        {
+            if (!m_IsInited) 
+            {
+                var doc = Document;
+                Doors = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Doors).GroupBy(e =>
+                {
+                    var host = e.Host;
+                    if (host == null)
+                        return "-1";
+                    return host.Id.IntegerValue.ToString();
+                }).ToDictionary(g => g.Key, g => g.ToList());
+                Windows = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Windows).GroupBy(e =>
+                {
+                    var host = e.Host;
+                    if (host == null)
+                        return "-1";
+                    return host.Id.IntegerValue.ToString();
+                }).ToDictionary(g => g.Key, g => g.ToList());
+                Spaces = doc.GetElements<SpatialElement>(BuiltInCategory.OST_MEPSpaces).OfType<Space>().Where(s=>s.Area>0.001).ToList();
+                ComputerSpaceItems = Spaces.Select(s => new ComputerSpaceItem(s)).ToList();            
+                m_IsInited = true;
+            }          
+        }
+        #region 持久缓存数据
+        private Dictionary<string, SgSpace> m_SaveSpaces = new Dictionary<string, SgSpace>();
+
         /// <summary>
-        /// 解析
+        /// 获取空间持久数据【缓存没有的话,创建新对象,并加入缓存】
         /// </summary>
-        public void Parse()
+        /// <param name="space"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public SgSpace GetSpace(Space space,SpaceComputerContext context)
         {
+            string key = space.GetBimId();
+            if (m_SaveSpaces.TryGetValue(key, out SgSpace useSpace))
+            {
+                return useSpace;
+            }
+            useSpace = context.NewSpace(space);
+            m_SaveSpaces[key] = useSpace;
+            return useSpace;
+        } 
+        #endregion
+        /// <summary>
+        /// 解析空间关系
+        /// </summary>
+        public void Parse(SpaceComputerContext context)
+        {
+            //初始化空间信息
+            Spaces.ForEach(s => GetSpace(s, context));
+
+            CurrentFloorParse(context);
+            UpFloorParse(context);
+            #region 保存缓存数据
             var doc = Document;
-            Doors = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Doors);
-            Windows = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Windows);
-            Spaces = doc.GetElements<SpatialElement>(BuiltInCategory.OST_MEPSpaces).OfType<Space>().ToList();
+            var id = Regex.Replace(doc.PathName, @".+\\(\w+)\\(\w+).rvt$", "$1-$2");
+            var saveName = DalProjectTree.GetFloorNameByFloorId(id.Split('-')[1]);
+            var levels = doc.GetLevels();
+            string levelName = saveName;
+            var currLevels = levels.FirstOrDefault(t => t.Name.IndexOf("-saga") > -1);
+            if (currLevels != null) levelName = currLevels.Name;
+            FloorSpaceData floorData = new FloorSpaceData
+            {
+                Name = saveName,
+                Id = id,
+                LevelName = levelName.Replace("-saga", "")
+            };
+            m_SaveSpaces.Values.ToList().ForEach(s => floorData.EndPoints.Add(s));
+            //获取标高名称,并按高度排序
+            List<string> levelNames = levels.OrderBy(t => t.Elevation).Where(t => Regex.IsMatch(t.Name, "[F|B]")).Select(t => t.Name.Replace("-saga", "")).ToList();
+            DrawDataServer.SaveSpaceFloorData(new List<FloorSpaceData>() { floorData }, levelNames);
+            #endregion
+        }
+        /// <summary>
+        /// 本层空间关系解析
+        /// </summary>
+        /// <param name="context"></param>
+        private void CurrentFloorParse(SpaceComputerContext context)
+        {
+            BinaryRelationCollection<Space, AdjanceElementType> spaceRelations =
+                new BinaryRelationCollection<Space, AdjanceElementType>(false,space=>space.Id.IntegerValue.ToString());
+            spaceRelations.SetSetting(new BinaryCollectionSetting<Space, AdjanceElementType>()
+                {UpdateAction = (o, n) => o.Value | n.Value});
+            #region 本层关系处理
             //展开空间关系数据
             var flatSpaceItems = FlatSpaceEdges(Spaces);
             var groupSpaces = flatSpaceItems.GroupBy(t => t.EdgeElement.Id.IntegerValue).ToList();
-            var relation = CalcCombineRelations(groupSpaces.ToList().Select(g=>g.Key).ToList());
+            var relations = CalcCombineRelations(groupSpaces.ToList().Select(g => g.Key).ToList());
+            for (int i = 0; i < groupSpaces.Count; i++)
+            {
+                var baseSpace = groupSpaces[i];
+                var rels = relations.Where(c => !c.IsHandled && c.Contains(baseSpace.Key)).ToList();
+                List<SpaceEdgeInfo> refEdgeInfos = new List<SpaceEdgeInfo>(baseSpace.ToList());
+                foreach (var rel in rels)
+                {
+                    rel.IsHandled = true;
+                    var anotherId = rel.GetAnother(baseSpace.Key);
+                    if (anotherId == baseSpace.Key)
+                    {
+                        continue;
+                    }
+                    var anSpace = groupSpaces.FirstOrDefault(g => g.Key == anotherId);
+                    if (anSpace != null)
+                    {
+                        refEdgeInfos.AddRange(anSpace.ToList());
+                    }
+                }
+                for (int j = 0; j < refEdgeInfos.Count; j++)
+                {
+                    var baseEdge = refEdgeInfos[j];
+                    for (int k =j + 1; k < refEdgeInfos.Count; k++)
+                    {
+                        var refEdge = refEdgeInfos[k];
+                        var type = JudgeAdjancentSpace(baseEdge, refEdge);
+                        if (type != AdjanceElementType.None)
+                        {
+                            BinaryRelationItem<Space, AdjanceElementType> item =
+                                new BinaryRelationItem<Space, AdjanceElementType>(baseEdge.Space, refEdge.Space)
+                                    { Value = type };
+                            spaceRelations.Update(item);
+                        }                  
+                    }
+                }
+            }
+            #endregion
+
+            #region 整理关联数据
+            foreach (var binaryItem in spaceRelations)
+            {
+                SpaceRelatedEnum relationType= SpaceComputerManager.GetRelationEnum(binaryItem.Value);
+                var space1 = GetSpace(binaryItem.First, context);
+                space1.AdjacentSpaces.Add(new AdjacentSpace() {Space = context.NewSpace(binaryItem.Second),RelatedEnum= relationType });
+                var space2 = GetSpace(binaryItem.Second, context);
+                space2.AdjacentSpaces.Add(new AdjacentSpace() { Space = context.NewSpace(binaryItem.First), RelatedEnum = relationType });
+            }
+            #endregion
+        }
+        /// <summary>
+        /// 上下层空间关系解析
+        /// </summary>
+        /// <param name="context"></param>
+        private void UpFloorParse(SpaceComputerContext context)
+        {
+            #region 上下层关系处理
+            /*1、从下往上计算,则可以利用现有缓存
+                2、如果上一层是夹层,则继续找夹层的上一层,。处理这层中没有分配上下关系的空间
+             */
+            var currentDoc = Document;
+            var currentSpaces = this.ComputerSpaceItems;
+            currentSpaces.ForEach(c => c.IsHandled = false);
+            do
+            {
+                var floorId = currentDoc.PathName.GetFileName();
+                var upFloor = DalProjectTree.GetUpperFloor(floorId);
+                if (upFloor == null)
+                    break;            
+                var upFloorItems = context.GetFloorItems(upFloor.FullPath);
+                if (upFloorItems == null)
+                    return;
+              
+                var upSpaces = upFloorItems.ComputerSpaceItems;
+                foreach (var currentSpace in currentSpaces)
+                {
+                    if (currentSpace.IsHandled)
+                        continue;
+                    var space1 = GetSpace(currentSpace.Space, context);
+                    foreach (var upSpace in upSpaces)
+                    {
+                        var type= JudgeUpAdjancentSpace(currentSpace, upSpace);
+                        if (type != AdjanceElementType.None)
+                        {
+                            currentSpace.IsHandled = true;
+                            SpaceRelatedEnum relationType = SpaceComputerManager.GetRelationEnum(type);
+                            var refSpace = context.NewSpace(upSpace.Space);
+                            space1.UpElements.Add(new AdjacentSpace() { Space = refSpace, RelatedEnum = relationType });
+                        }
+                    }
+                    
+                }
+                if (upFloor.FloorType == "4") //夹层为4
+                {
+                    currentDoc = upFloorItems.Document;
+                }
+                else
+                {
+                    break;
+                }
+            } while (true);           
+            #endregion
         }
 
         #region 展开空间与边界的关联关系
@@ -145,6 +354,7 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
             var doc = Document;
             FilteredElementCollector collectors =
                 new FilteredElementCollector(doc, ids.Select(id => new ElementId(id)).ToList());
+            collectors.WhereElementIsNotElementType();
             var calcElements = collectors.ToElements();
             Dictionary<int, ElementGraphicItem> tempItems = new Dictionary<int, ElementGraphicItem>();
             for (int i = 0; i < calcElements.Count; i++)
@@ -173,7 +383,7 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
                         if (((outItem.Width + inItem.Width) / 2.0d).IsThanEq(length))
                         {
                             relations.Add(new BinaryRelationItem<int>(outElement.Id.IntegerValue,
-                                outElement.Id.IntegerValue));
+                                inElement.Id.IntegerValue));
                         }
                     }
                     #endregion
@@ -234,5 +444,146 @@ namespace SAGA.GplotRelationComputerManage.SpaceRelation
         }
 
         #endregion
+
+        #region 邻接关系判断
+        /// <summary>
+        /// 判断两个空间,在指定边上的相交关系
+        /// </summary>
+        /// <param name="space1"></param>
+        /// <param name="space2"></param>
+        /// <returns></returns>
+        public AdjanceElementType JudgeAdjancentSpace(SpaceEdgeInfo space1, SpaceEdgeInfo space2)
+        {
+            var result=AdjanceElementType.None;
+            if(space1.Space.Id.IntegerValue==space2.Space.Id.IntegerValue)
+                return result;
+            /*先判断是否是虚拟墙。如果是实体墙,则进一步判断是否所有门窗之间的关系;
+               两个space,可能不是公用一个Eelment,而是通过关联产生的
+             */
+            //平行直线和弧线的投影
+            var baseCurve = space1.Edge;//spac1的edge和space2的edge平行
+            Curve curve1 = GetProjectCurve(baseCurve, space1.SegEdge);
+            Curve curve2 = GetProjectCurve(baseCurve, space2.SegEdge);
+            IntersectionResultArray ira;
+            var isConn = curve2.Intersect(curve1, out ira) != SetComparisonResult.Disjoint;
+            if (!isConn||(ira != null && ira.Size == 1))
+            {
+                 return result;
+            }           
+            #region 虚拟墙判断
+            var virType = typeof(ModelCurve);
+            if (space1.EType == virType && space2.EType == virType)
+            {
+                return AdjanceElementType.VirtualWall;
+            }
+            #endregion
+            result = AdjanceElementType.Wall;//必然墙相连
+            #region 门窗判断
+            List<Wall> walls = new List<Wall>();
+            foreach (var spaceEdgeInfo in new []{space1,space2})
+            {
+                if (spaceEdgeInfo.EType == typeof(Wall))
+                {
+                    if (walls.Any(w => w.Id == spaceEdgeInfo.EdgeElement.Id))
+                    {
+                        continue;
+                    }
+                    walls.Add(spaceEdgeInfo.EdgeElement as Wall);
+                }
+            }
+            if (walls.Any())
+            {
+                result = result | AdjanceElementType.Wall;
+                var doors = new List<FamilyInstance>();
+                var windows = new List<FamilyInstance>();
+                foreach (var wall in walls)
+                {
+                    List<FamilyInstance> tempDoors = new List<FamilyInstance>();
+                    if (Doors.TryGetValue(wall.Id.IntegerValue.ToString(), out tempDoors))
+                    {
+                        doors.AddRange(tempDoors);
+                    }
+                    List<FamilyInstance> tempWindows = new List<FamilyInstance>();
+                    if (Windows.TryGetValue(wall.Id.IntegerValue.ToString(), out tempWindows))
+                    {
+                        windows.AddRange(tempWindows);
+                    }
+                }          
+                List<Curve> edgeCurves = new List<Curve>() {space1.SegEdge, space2.SegEdge};
+                if (doors.Any(d => edgeCurves.All(c => c.IsContain(c.GetProjectPt(d.GetLocationPoint())))))
+                {
+                    result = result | AdjanceElementType.Door;
+                }
+                if (windows.Any(w => edgeCurves.All(c => c.IsContain(c.GetProjectPt(w.GetLocationPoint())))))
+                {
+                    result = result | AdjanceElementType.Window;
+                }
+            }
+           
+            #endregion
+          
+            return result;
+        }
+        /// <summary>
+        /// 获取Curve1在Curve2上的投影【两线为平行关系的直线和弧线】【可简化】
+        /// </summary>
+        /// <param name="projectCurve"></param>
+        /// <param name="curve"></param>
+        /// <returns></returns>
+        private Curve GetProjectCurve(Curve projectCurve, Curve curve)
+        {
+            var startPoint = projectCurve.GetProjectPt(curve.StartPoint());
+            var endPoint = projectCurve.GetProjectPt(curve.EndPoint());
+            if (projectCurve is Arc)
+            {
+                //弧形应该是法向投影
+                var middle = projectCurve.GetProjectPt((startPoint + endPoint) / 2);
+                return Arc.Create(startPoint, endPoint, middle);
+            }
+            return Line.CreateBound(startPoint, endPoint);
+        }
+        #endregion
+
+        #region 上下层关系判断
+        /// <summary>
+        /// 判断两个空间是否是上下相交关系
+        /// </summary>
+        /// <param name="aFSpace"></param>
+        /// <param name="bSpace"></param>
+        /// <returns></returns>
+        public AdjanceElementType JudgeUpAdjancentSpace(ComputerSpaceItem aFSpace, ComputerSpaceItem bSpace)
+        {
+            AdjanceElementType result = AdjanceElementType.None;
+            if (!aFSpace.Box.Intersects(bSpace.Box, 0))
+            {
+                return result;
+            }
+            if (ClosedIntersect(aFSpace.ZeroCurves, bSpace.ZeroCurves))
+            {
+                result = AdjanceElementType.Vertical;
+                if (SpaceComputerManager.IsCrossFunType(aFSpace.FuncType) && SpaceComputerManager.IsCrossFunType(bSpace.FuncType))
+                {
+                    result = result | AdjanceElementType.VerticalOpening;
+                }
+            }
+            return result;
+        }
+        public bool ClosedIntersect(List<Curve> closed1, List<Curve> closed2)
+        {
+            //判断所有的线是否有相交
+            foreach (var curve1 in closed1)
+            {
+                if (curve1.IsIntersectPoly(closed2)) return true;
+            }
+
+            //判断是否包含
+            foreach (var curve in closed1)
+            {
+                if (curve.StartPoint().PointInPolygon(closed2)) return true;
+            }
+
+            return closed2.Any(curve => curve.StartPoint().PointInPolygon(closed1));
+        }
+        #endregion
     }
 }

+ 80 - 0
MBI/SAGA.GplotRelationComputerManage/SpaceRelation/SpaceComputerContext.cs

@@ -7,17 +7,28 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Autodesk.Revit.DB.Mechanical;
 using Newtonsoft.Json.Linq;
+using SAGA.DotNetUtils.Extend;
 using SAGA.MBI.RequestData;
 using SAGA.Models;
+using SAGA.RevitUtils;
+using SAGA.RevitUtils.Extends;
 
 namespace SAGA.GplotRelationComputerManage
 {
     public class SpaceComputerContext
     {
+        public SpaceComputerContext()
+        {
+            FloorItems =new Dictionary<string, FloorSpaceItems>();
+        }
+
         #region 空间信息
         /// <summary>
         /// 缓存空间对象
@@ -45,6 +56,75 @@ namespace SAGA.GplotRelationComputerManage
             m_Rooms.TryGetValue(bimId, out RoomItem resultItem);
             return resultItem;
         }
+
+        
+        /// <summary>
+        /// 创建空间持久数据
+        /// </summary>
+        /// <param name="space"></param>
+        /// <returns></returns>
+        public SgSpace NewSpace(Space space)
+        {
+            string key = space.GetBimId();
+            var roomItem = GetRoomItem(key);
+            var  useSpace = new SgSpace()
+            {
+                Id = space.Id.ToString(),
+                Name = space.Name,
+                Point = space.Location.GetPoint().ToW2DPoint(),
+
+            };
+            if (roomItem != null)
+            {
+                var display = roomItem.LocalName;
+                useSpace.Name = string.IsNullOrEmpty(display) ? space.Name : display;
+                useSpace.RoomFuncType = roomItem.RoomFuncType;
+            }
+            return useSpace;
+        }
+
         #endregion
+
+        #region 空间计算缓存信息
+        /// <summary>
+        /// 楼层空间数据缓存
+        /// </summary>
+        public Dictionary<string, FloorSpaceItems> FloorItems { get; private set; }
+
+        /// <summary>
+        /// 获取指定路径项目的楼层信息
+        /// </summary>
+        /// <param name="path"></param>
+        /// <returns></returns>
+        public FloorSpaceItems GetFloorItems(string path)
+        {
+            var floorId = Path.GetFileNameWithoutExtension(path);
+            if (FloorItems.TryGetValue(floorId, out FloorSpaceItems floor))
+            {
+                return floor;
+            }
+
+            if (File.Exists(path))
+            {
+                var uiApp = ExternalDataWrapper.Current.UiApp.Application;
+                var doc = uiApp.OpenDocumentFile(path);
+                floor = new FloorSpaceItems(doc);
+                #region 初始化计算空间数据
+                floor.ComputerSpaceItems.ForEach(c =>
+                      {
+                          var room = GetRoomItem(c.BimId);
+                          if (room != null)
+                          {
+                              c.FuncType = room.RoomFuncType;
+                          }
+                      }); 
+                #endregion
+                FloorItems[floorId] = floor;
+            }
+            return floor;
+        }
+
+        #endregion
+
     }
 }

+ 49 - 3
MBI/SAGA.GplotRelationComputerManage/SpaceRelation/SpaceComputerManager.cs

@@ -10,6 +10,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using SAGA.Models;
 
 namespace SAGA.GplotRelationComputerManage
 {
@@ -21,13 +22,58 @@ namespace SAGA.GplotRelationComputerManage
     /// </summary>
     public class SpaceComputerManager
     {
+        private readonly static List<string> m_UpSpaceFunTypes= new List<string>() { "140","150","1A0","1B0" };
+     /// <summary>
+     /// 获取计算上下关系的空间类型
+     /// </summary>
+     /// <returns></returns>
+      public static List<string> GetUpSpaceFunTypes()
+       {
+            return m_UpSpaceFunTypes;  
+        }
+        /// <summary>
+        /// 是否是交通类型空间类型
+        /// </summary>
+        /// <param name="funType"></param>
+        /// <returns></returns>
+        public static bool IsCrossFunType(string funType)
+        {
+            return m_UpSpaceFunTypes.Contains(funType);
+        }
+
         /// <summary>
-        /// 获取计算上下关系的空间类型
+        /// 获取空间关系分类枚举
         /// </summary>
+        /// <param name="type"></param>
         /// <returns></returns>
-        public static List<string> GetUpSpaceFunTypes()
+        public static SpaceRelatedEnum GetRelationEnum(AdjanceElementType type)
         {
-            return new List<string>() { "140","150","1A0","1B0" };  
+            SpaceRelatedEnum result= SpaceRelatedEnum.Adjacent;//暂时先这么写,不会出现Type为None的关系
+            if (type == AdjanceElementType.None)
+                return result;         
+            if (type.HasFlag(AdjanceElementType.Wall))
+            {
+            }
+            if (type.HasFlag(AdjanceElementType.VirtualWall))
+            {
+                result = result | SpaceRelatedEnum.All;
+            }
+            if (type.HasFlag(AdjanceElementType.Door))
+            {
+                result = result | SpaceRelatedEnum.Crossing| SpaceRelatedEnum.Ventilation;
+            }
+            if (type.HasFlag(AdjanceElementType.Window))
+            {
+                result = result | SpaceRelatedEnum.Radiation | SpaceRelatedEnum.Ventilation;
+            }
+            if (type.HasFlag(AdjanceElementType.Vertical))
+            {
+            }
+            if (type.HasFlag(AdjanceElementType.VerticalOpening))
+            {
+                result = result | SpaceRelatedEnum.Crossing;
+            }
+            return result;
         }
     }
 }

+ 37 - 0
MBI/SAGA.GplotRelationComputerManage/SystemRelation/Common/SystemCalcUtil.cs

@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:SystemCalcUtil
+ * 作者:xulisong
+ * 创建时间: 2019/1/2 17:55:55
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SAGA.RevitUtils.Extends;
+
+namespace SAGA.GplotRelationComputerManage.SystemRelation.Common
+{
+    /// <summary>
+    /// 系统计算相关
+    /// </summary>
+    public class SystemCalcUtil
+    {
+        /// <summary>
+        /// 判断元素是否是开始元素
+        /// </summary>
+        /// <param name="element"></param>
+        /// <returns></returns>
+        public bool IsStart(Element element)
+        {
+           if (element is FamilyInstance)
+           {
+               return element.GetFamily()?.Name == "流向指示符";
+           }
+           return element.GetParameterString(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS) == "start";
+        }
+    }
+}

+ 48 - 0
MBI/SAGA.GplotRelationComputerManage/SystemRelation/FloorSystemItems.cs

@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:FloorSystemItems
+ * 作者:xulisong
+ * 创建时间: 2019/1/4 17:50:04
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+
+namespace SAGA.GplotRelationComputerManage
+{
+    public class FloorSystemItems
+    {
+        #region 构造函数
+        /// <summary>
+        /// 初始化解析类
+        /// </summary>
+        /// <param name="doc"></param>
+        public FloorSystemItems(Document doc)
+        {
+            Document = doc;
+            InitData();
+        }
+        #endregion
+        #region 属性相关
+        /// <summary>
+        /// 关联模型信息
+        /// </summary>
+        public Document Document { get; private set; }
+        private void InitData()
+        { }
+        #endregion
+
+        #region 数据解析方法
+        public void ParsePipe()
+        { }
+
+        public void ParseDuct()
+        { }
+        #endregion
+
+    }
+}

+ 55 - 0
MBI/SAGA.GplotRelationComputerManage/SystemRelation/SystemComputerContext.cs

@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:SystemComputerContext
+ * 作者:xulisong
+ * 创建时间: 2019/1/4 17:52:22
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SAGA.RevitUtils.Extends;
+
+namespace SAGA.GplotRelationComputerManage
+{
+    public class SystemComputerContext
+    {
+        public SystemComputerContext()
+        {
+            FloorItems = new Dictionary<string, FloorSystemItems>();
+        }
+        #region 空间计算缓存信息
+        /// <summary>
+        /// 楼层系统数据缓存
+        /// </summary>
+        public Dictionary<string, FloorSystemItems> FloorItems { get; private set; }
+
+        /// <summary>
+        /// 获取指定路径项目的楼层信息
+        /// </summary>
+        /// <param name="path"></param>
+        /// <returns></returns>
+        public FloorSystemItems GetFloorItems(string path)
+        {
+            var floorId = Path.GetFileNameWithoutExtension(path);
+            if (FloorItems.TryGetValue(floorId, out FloorSystemItems floor))
+            {
+                return floor;
+            }
+
+            if (File.Exists(path))
+            {
+                var uiApp = ExternalDataWrapper.Current.UiApp.Application;
+                var doc = uiApp.OpenDocumentFile(path);
+                floor = new FloorSystemItems(doc);
+                FloorItems[floorId] = floor;
+            }
+            return floor;
+        }
+
+        #endregion
+    }
+}

+ 8 - 5
MBI/SAGA.MBI/Command.cs

@@ -412,17 +412,20 @@ namespace SAGA.MBI
         {
             try
             {
-
+                WaitingView wait = new WaitingView();
+                wait.Start();
                 var floors = DalUploadFloor.GetHasFileFloors();
                 List<CalcContext> contexts = new List<CalcContext>();
                 foreach (UploadFloor floor in floors)
                 {
-
+                    if (floor.MFloor.FloorLock.LockState != MFloorLockState.LockBySelf)
+                    {
+                        continue;
+                    }
                     contexts.Add(new CalcContext(floor.MFloor));
                 }
                  MBIModelInfoManager.SyncPlatformToRevit(contexts);
-                //var doc = ExternalDataWrapper.Current.Doc;             
-                //MBIModelInfoManager.SyncPlatformToRevit(doc);
+                wait.Close();
             }
             catch (Exception e)
             {
@@ -434,7 +437,7 @@ namespace SAGA.MBI
 
         public override bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
         {
-            return false;
+            return true;
         }
     }
 }

+ 76 - 0
MBI/SAGA.MBI/Common/WaitingView.cs

@@ -0,0 +1,76 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:WaitingView
+ * 作者:xulisong
+ * 创建时间: 2018/12/26 17:46:49
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Interop;
+using System.Windows.Threading;
+using FWindSoft.Tools;
+using FWindSoft.Wpf;
+using SAGA.DotNetUtils;
+using SAGA.DotNetUtils.WPF.Windows;
+
+namespace SAGA.MBI.Common
+{
+    public class WaitingView : IWaitingView
+    {
+        private WinIndeterminationWaiting m_Win;
+        public void Close()
+        {
+            m_Win.Dispatcher.Invoke(() =>
+                {
+                    if (IsWinValid())
+                    {
+                        m_Win.Close();
+                    }
+                }
+            );
+        }
+        public void Start()
+        {
+            TaskUtil.StartSTATask(() =>
+            {
+                if (!IsWinValid())
+                {
+                    m_Win = new WinIndeterminationWaiting();
+                    WindowInteropHelper helper = new WindowInteropHelper(m_Win);
+                    helper.Owner = WindowHelper.HWndRevit.Handle;
+                    WindowHelper.SetWindowForeground(helper.EnsureHandle());
+                    m_Win.Closed += (d, k) =>
+                    {
+                        // 当窗口关闭后马上结束消息循环
+                      Dispatcher.ExitAllFrames();
+                    };
+                }
+
+                SetMessage("正在执行,请稍等...");
+                //m_Win.ShowDialog();
+                m_Win.Show();
+                //一定要处理退出机制,不然该监控线程不会消失,有时间再研究
+              Dispatcher.Run();
+            });
+        }
+
+        public void Update(object args)
+        {
+            SetMessage(args.ToString());
+        }
+
+        private bool IsWinValid()
+        {
+            return !(m_Win == null || m_Win.IsDisposed());          
+        }
+
+        private void SetMessage(string message)
+        {
+            m_Win.Dispatcher.BeginInvoke(new Action(() => m_Win.Message = message),DispatcherPriority.Background,null);
+        }
+    }
+}

+ 5 - 0
MBI/SAGA.MBI/DataArrange/DalUploadFloor.cs

@@ -19,6 +19,7 @@ using SAGA.MBI.Calc;
 using SAGA.MBI.Common;
 using SAGA.MBI.Extend;
 using SAGA.MBI.FileStream;
+using SAGA.MBI.Interaction;
 using SAGA.MBI.JsonConvert;
 using SAGA.MBI.Model;
 using SAGA.MBI.RequestData;
@@ -231,6 +232,10 @@ namespace SAGA.MBI.DataArrange
                     //检测到自己加锁 才读取日志
                     if (uploadFloor.MFloor.FloorLock.LockState != MFloorLockState.LockBySelf)
                         continue;
+                    #region 同步空间名称
+                    var document = ExternalDataWrapper.Current.App.OpenDocumentFile(uploadFloor.MFloor.FullPath);
+                    MBIModelInfoManager.SyncPlatformToRevit(document);
+                    #endregion
                     //检测有日志文件,才上传
                     var logs = DalLogOperate.GetLogs(uploadFloor.MFloor.Id);
                     if (!logs.Any()) continue;

+ 20 - 0
MBI/SAGA.MBI/Extend/DocExtend.cs

@@ -80,6 +80,26 @@ namespace SAGA.MBI.Tools
             Element elem = null;
             return CloseDoc(doc.PathName);
         }
+        /// <summary>
+        /// 简单关闭模型不保存
+        /// </summary>
+        /// <param name="doc"></param>
+        /// <returns></returns>
+        public static bool CloseDocSimple(this Document doc)
+        {
+            bool result = true;
+            var basePath = doc.PathName;
+            var uiApp = ExternalDataWrapper.Current.UiApp;
+            if (uiApp.ActiveUIDocument != null && uiApp.ActiveUIDocument.Document.PathName == basePath)
+            {
+                result= false;
+            }
+            else
+            {
+                result= doc.Close();
+            }
+            return result;
+        }
 
         /// <summary>
         /// 获取当前层的MFloor对象

+ 76 - 0
MBI/SAGA.MBI/Interaction/MBILocalNameTrigger.cs

@@ -0,0 +1,76 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:MBILocalNameTrigger
+ * 作者:xulisong
+ * 创建时间: 2018/12/27 13:12:48
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using SAGA.DotNetUtils.Extend;
+using SAGA.RevitUtils;
+using SAGA.RevitUtils.ExtendInterface;
+using SAGA.RevitUtils.Extends;
+
+namespace SAGA.MBI.Interaction
+{
+    public class MBILocalNameTrigger : UpdaterRegister
+    {
+        private readonly Guid GUID = Guid.NewGuid();
+
+        private static bool m_IsPause;
+        public static void Suspend()
+        {
+            m_IsPause = true;
+        }
+        public static void Resume()
+        {
+            m_IsPause = false;
+        }
+        protected override List<RevitTrigger> GetTriggers()
+        {
+            List<RevitTrigger> triggers = new List<RevitTrigger>();
+            var changeType = Element.GetChangeTypeParameter(new ElementId((int) BuiltInParameter.ROOM_NAME));
+            triggers.Add(new RevitTrigger(new ElementCategoryFilter(BuiltInCategory.OST_MEPSpaces), changeType));
+            return triggers;
+        }
+
+        protected override RevitUpdater GetUpdater()
+        {
+            //当触发器返回空时,自动不进行属性监控
+            var  addInId= RevitEventsBingding.CurrentApp.ActiveAddInId;
+            RevitUpdater updaer = new RevitUpdater(new UpdaterId(addInId, GUID), (data) =>
+            {
+                if (m_IsPause)
+                    return;
+                var document = data.GetDocument();
+                if (!document.PathName.GetFileName().StartsWith("Fl"))
+                    return;
+                foreach (var modifiedElementId in data.GetModifiedElementIds())
+                {
+                    var element = document.GetElement(modifiedElementId);
+                    if (element != null)
+                    {
+                        #region 异步调用线程更新
+                        Task.Factory.StartNew(() =>
+                                      {
+                                          try
+                                          {
+                                              element.UpdateMBIName(element.GetParameterString(BuiltInParameter.ROOM_NAME));
+                                          }
+                                          catch (Exception)
+                                          {
+                                          }
+                                      }); 
+                        #endregion
+                    }
+                }                
+            });
+            return updaer;
+        }
+    }
+}

+ 7 - 9
MBI/SAGA.MBI/Interaction/MBIModelInfoManager.cs

@@ -60,15 +60,13 @@ namespace SAGA.MBI.Interaction
                                 {
                                     continue;
                                 }
-                                 element.UdpateName(mbiItem.LocalName);
-                            
+                                 element.UdpateName(mbiItem.LocalName,true);                           
                                 sub.Commit();
                             }
                             catch (Exception e)
                             {
                                 sub.RollBack();
                             }
-
                         } 
                         #endregion
                     }
@@ -80,6 +78,11 @@ namespace SAGA.MBI.Interaction
                     flag = false;
                 }
             }
+
+            if (flag)
+            {
+                document.Save();
+            }
             return flag;
         }
 
@@ -97,13 +100,8 @@ namespace SAGA.MBI.Interaction
                 bool isOpened = false;
                 try
                 {
-
                     isOpened = documents.Any(d => d.PathName == context.MFloor.FullPath);
-                    //if (!isOpened)
-                    //{
-                    //开,全部开启.;关,新打开的关掉
-                        context.OpenDocument();
-                  //  }               
+                    context.OpenDocument();            
                     Document doc = context.RevitDoc;                   
                     var floorId = doc.PathName.GetFileName();
                     var flag = SyncPlatformToRevit(doc);

+ 3 - 2
MBI/SAGA.MBI/Model/MRevitEquipBase.cs

@@ -22,6 +22,7 @@ using SAGA.MBI.JsonConvert;
 using SAGA.MBI.RequestData;
 using SAGA.MBI.Tools;
 using SAGA.MBI.WinView.ModeInfoMaintenance;
+using SAGA.RevitUtils.Windows;
 using WPG.Data;
 
 namespace SAGA.MBI.Model
@@ -258,7 +259,7 @@ namespace SAGA.MBI.Model
             var attributes = info?.GetCustomAttributes(typeof(DescriptionAttribute));
             var att = attributes?.FirstOrDefault();
             if (att == null) return;
-
+           
             if (att is DescriptionAttribute descriptionAttribute)
             {
                 var description = descriptionAttribute.Description;
@@ -270,7 +271,7 @@ namespace SAGA.MBI.Model
                     {
                         if (info.PropertyType == typeof(int))
                             value = ((int)value).ToString();
-
+                        RevitParameterUpdate.UpdateParameter(BimID, description, value.ToString());
                         UpdateSingleProperty(description, (string)value);
                     }
                 }

+ 109 - 1
MBI/SAGA.MBI/RevitModelHandle/RevitParameterUpdate.cs

@@ -1,11 +1,21 @@
 using Autodesk.Revit.DB;
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Autodesk.Revit.DB.Mechanical;
+using Newtonsoft.Json.Linq;
+using SAGA.DotNetUtils;
+using SAGA.MBI.Common;
+using SAGA.MBI.DataArrange;
+using SAGA.MBI.Interaction;
+using SAGA.MBI.RequestData;
+using SAGA.Models;
+using SAGA.RevitUtils;
 using SAGA.RevitUtils.Extends;
+using SAGA.RevitUtils.Windows;
 
 namespace SAGA.MBI
 {
@@ -14,6 +24,7 @@ namespace SAGA.MBI
     /// </summary>
     public static class RevitParameterUpdate
     {
+        #region 同步模型
         /// <summary>
         /// 更新模型名称
         /// </summary>
@@ -26,7 +37,7 @@ namespace SAGA.MBI
             {
                 if (element is Space space)
                 {
-                    if (space.Name == useName || space.GetParameterString(BuiltInParameter.ROOM_NAME) == useName)
+                    if (space.Name != useName && space.GetParameterString(BuiltInParameter.ROOM_NAME) != useName)
                     {
                         space.SetParameter(BuiltInParameter.ROOM_NAME, useName);
 
@@ -34,5 +45,102 @@ namespace SAGA.MBI
                 }
             } while (false);
         }
+        /// <summary>
+        /// 更新元素名称
+        /// </summary>
+        /// <param name="element"></param>
+        /// <param name="name"></param>
+        /// <param name="stopLocalTrigger">是否暂停触发器,暂停触发器则不会发送对数据平台的同步</param>
+        public static void UdpateName(this Element element, string name, bool stopLocalTrigger)
+        {
+            if (!stopLocalTrigger)
+            {
+                UdpateName(element, name);
+                return;
+            }
+            try
+            {
+                MBILocalNameTrigger.Suspend();
+                UdpateName(element, name);
+            }
+            catch (Exception ex)
+            {
+            }
+            finally
+            {
+                MBILocalNameTrigger.Resume();
+            }
+        }
+
+        public static void UpdateNameAsync(this Element element, string name)
+        {
+            ExecuteCmd.ExecuteCommand(() =>
+            {
+                using (Transaction tran = new Transaction(element.Document, "同步"))
+                {
+                    try
+                    {
+                        tran.Start();
+                        UdpateName(element, name, true);
+                        tran.Commit();
+                    }
+                    catch (Exception e)
+                    {
+                        tran.RollBack();
+                    }
+                }
+                return Autodesk.Revit.UI.Result.Succeeded;
+            });
+        }
+        public static void UpdateNameAsync(string bimId, string name)
+        {
+            if (bimId == null)
+                return;
+            var ids = bimId.Split(':');
+            if (ids.Count() < 2)
+                return;
+            string floorId = ids[0];
+            int elementID = ids[1].ToInt();
+            var mFloor = DalProjectTree.GetFloorByFloorId(floorId);
+            if (mFloor == null)
+            {
+                return;
+            }            
+            if (!File.Exists(mFloor.FullPath))
+            {
+                return;
+            }
+            var doc = ExternalDataWrapper.Current.App.OpenDocumentFile(mFloor.FullPath);// ExternalDataWrapper.Current.Doc;
+            if (doc == null)
+                return;
+            var element = doc.GetElement(new ElementId(elementID));
+            if (element == null)
+                return;
+            UpdateNameAsync(element, name);
+        }
+
+
+        public static void UpdateParameter(string bimId, string parameterName,string value)
+        {
+            if (parameterName == MBIBuiltInParameter.RoomLocalName)
+            {
+                UpdateNameAsync(bimId, value);
+            }         
+        }
+
+        #endregion
+        public static void UpdateMBIName(this Element element, string name)
+        {
+            //更新物理世界信息点内容
+            var bimId = element.GetBimId();         
+            JArray jArray = CommonTool.GetPropertyJArray(name);
+            JObject jObject = new JObject();
+            jObject.Add(MBIBuiltInParameter.RoomLocalName, jArray);
+            var cloudElement = DalCommon.GetEquipmentQueryId(element);
+            if (cloudElement == null)
+                return;
+            CommonConvert.UpdateInfosSigle(cloudElement.Id, jObject);
+           // MessageShow.Infomation(bimId);
+        }
     }
 }

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

@@ -242,6 +242,7 @@
     <Compile Include="CmbData\BuildingCmbVm.cs" />
     <Compile Include="CmbData\ProvinceCityVm.cs" />
     <Compile Include="Common\CacheAspect.cs" />
+    <Compile Include="Common\WaitingView.cs" />
     <Compile Include="Html5Command.cs" />
     <Compile Include="Command.cs" />
     <Compile Include="Common\MBIAssistHelper.cs" />
@@ -263,6 +264,7 @@
     <Compile Include="DataArrange\DalProjectTree.cs" />
     <Compile Include="DataArrange\DalSpace.cs" />
     <Compile Include="DataArrange\DalUserMenuPermission.cs" />
+    <Compile Include="Interaction\MBILocalNameTrigger.cs" />
     <Compile Include="Interaction\MBIModelInfoManager.cs" />
     <Compile Include="JsonConvert\QRCodeConvert.cs" />
     <Compile Include="ModeInfoEdit\WinPointMergeTip.xaml.cs">
@@ -627,6 +629,7 @@
       <DependentUpon>WinBeacon.xaml</DependentUpon>
     </Compile>
     <Compile Include="DataArrange\DalUploadFloor.cs" />
+    <Compile Include="WinView\Space\ExternalEventHandler.cs" />
     <Compile Include="WinView\Space\FloorSpaceContext.cs" />
     <Compile Include="WinView\Space\GeometryHelper.cs" />
     <Compile Include="WinView\Space\ServerSpace.cs" />

+ 139 - 0
MBI/SAGA.MBI/TestCommand.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Windows.Media;
 using Autodesk.Revit.Attributes;
 using Autodesk.Revit.DB;
 using Autodesk.Revit.DB.Plumbing;
@@ -22,6 +23,7 @@ using SAGA.RevitUtils;
 using SAGA.RevitUtils.Extends;
 using SAGA.RevitUtils.MEP;
 using WPfPointInfo;
+using Color = Autodesk.Revit.DB.Color;
 
 namespace SAGA.MBI
 {
@@ -155,4 +157,141 @@ namespace SAGA.MBI
             }
         }
     }
+
+    /// <summary>
+    /// 管道系统类型
+    /// </summary>
+    [Transaction(TransactionMode.Manual)]
+    [Regeneration(RegenerationOption.Manual)]
+    public class CheckLocationCommand : ExternalCommand, IExternalCommandAvailability
+    {
+        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+        {
+            try
+            {
+                var pickElement = ExternalDataWrapper.Current.UiApp.PickElement("请选择设备", new EquipmentFilter()) as FamilyInstance;
+                if (pickElement == null)
+                {
+                    return Result.Succeeded;
+                }
+                using (Transaction tran = new Transaction(ExternalDataWrapper.Current.Doc, "显示"))
+
+                {
+                    try
+                    {
+                        tran.Start();
+                        var doc = ExternalDataWrapper.Current.Doc;
+                        var s = pickElement.GetLocationPointMBIXYZ();
+                        DirectShape ds = DirectShape.CreateElement(doc,new ElementId(BuiltInCategory.OST_GenericModel));
+                        var solid = CreateSphereAt(s, 1);
+                        ds.AppendShape(new List<GeometryObject>() { solid });
+                        SetColor(ds,new Color(255, 0, 0));            
+                        tran.Commit();
+                        ExternalDataWrapper.Current.UiApp.SetShowElements(new List<Element>() { ds });
+                    }
+                    catch (Exception ex)
+                    {
+                        MessageShow.Show(ex);
+                        tran.RollBack();
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                MessageShow.Show(e);
+                return Result.Cancelled;
+            }
+            return Result.Succeeded;
+        }
+
+
+        #region 静态方法
+        /// <summary>
+        /// 替换视图中的图形,来修改颜色
+        /// </summary>
+        public static void SetColor( Element elem, Color color, View view = null,
+            int transparency = 0)
+        {
+            var ogs = new OverrideGraphicSettings();
+
+
+            #region 表面填充图案
+
+            //可见
+            ogs.SetProjectionFillPatternVisible(true);
+            //颜色
+            ogs.SetProjectionFillColor(color);
+            //透明度
+            ogs.SetSurfaceTransparency(transparency);
+
+            #endregion
+
+            #region 截面填充图案
+
+            //可见
+            ogs.SetCutFillPatternVisible(true);
+            //颜色
+            ogs.SetCutFillColor(color);
+            //填充图案
+            #endregion
+
+            if (view != null)
+            {
+                view.SetElementOverrides(elem.Id, ogs);
+            }
+            else
+            {
+                elem.Document.ActiveView.SetElementOverrides(elem.Id, ogs);
+            }
+        }
+
+        /// <summary>
+        /// 使用指定的球心和半径创建球体
+        /// </summary>
+        static public Solid CreateSphereAt(
+            XYZ centre,
+            double radius)
+        {
+            // 使用标准的全局坐标系创建 Frame
+
+            Frame frame = new Frame(centre,
+                XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ);
+
+            // 创建一个Z轴方向的半圆闭合曲线(注意所有的坐标都是相对全局坐标系的)
+
+            Arc arc = Arc.Create(
+                centre - radius * XYZ.BasisZ,
+                centre + radius * XYZ.BasisZ,
+                centre + radius * XYZ.BasisX);
+
+            Line line = Line.CreateBound(
+                arc.EndPoint(),
+                arc.StartPoint());
+
+            CurveLoop halfCircle = new CurveLoop();
+            halfCircle.Append(arc);
+            halfCircle.Append(line);
+
+            List<CurveLoop> loops = new List<CurveLoop>(1);
+            loops.Add(halfCircle);
+
+            return GeometryCreationUtilities
+                .CreateRevolvedGeometry(
+                    frame, loops, 0, 2 * Math.PI);
+        }
+
+        #endregion
+        public class EquipmentFilter : ISelectionFilter
+        {
+            public bool AllowElement(Element elem)
+            {
+                return elem is FamilyInstance;
+            }
+
+            public bool AllowReference(Reference reference, XYZ position)
+            {
+                return true;
+            }
+        }
+    }
 }

+ 67 - 0
MBI/SAGA.MBI/WinView/Space/ExternalEventHandler.cs

@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:ExternalEventHandler
+ * 作者:xulisong
+ * 创建时间: 2019/1/4 10:59:50
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using Autodesk.Revit.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SAGA.MBI.WinView.Space
+{
+    /// <summary>
+    /// 为了在外部事件中打开OpenAndActiveDocument
+    /// </summary>
+    public class ExternalEventHandler : IExternalEventHandler
+    {
+        public ExternalEventHandler(Action<UIApplication> handler)
+        {
+            m_Execute = handler;
+        }
+        private Action<UIApplication> m_Execute;
+        // 事件处理函数
+        public void Execute(UIApplication app)
+        {
+            if (m_Execute != null)
+            {
+                m_Execute(app);
+            }
+        }
+        // 事件处理函数的名称
+        public string GetName()
+        {
+            return "上传";
+        }
+    }
+
+    public class EventCommand
+    {
+        private ExternalEventHandler m_Handler;
+        public EventCommand(ExternalEventHandler handler)
+        {
+            m_Handler = handler;
+        }
+        public ExternalEvent Event { get; private set; }
+        public void Register()
+        {
+            if (m_Handler != null&& Event==null)
+            {
+                Event = ExternalEvent.Create(m_Handler);
+            }         
+        }
+
+        public void Raise()
+        {
+            if (Event == null)
+            {
+                Register();
+            }
+            Event?.Raise();
+        }
+    }
+}

+ 9 - 4
MBI/SAGA.MBI/WinView/Space/FloorSpaceContext.cs

@@ -47,8 +47,9 @@ namespace SAGA.MBI.WinView
                     {
                         throw new Exception("无法找到相关模型文件!");
                     }
-                    var uiDoc = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(filePath);
-                    m_Document = uiDoc.Document;
+                    //var uiDoc = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(filePath);
+                    //var uiDoc = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(filePath);
+                    m_Document = ExternalDataWrapper.Current.App.OpenDocumentFile(filePath);//uiDoc.Document;
                 }
                 return m_Document;
             }
@@ -108,9 +109,13 @@ namespace SAGA.MBI.WinView
                     #endregion
 
                     #region 冲突处理代码
-                    spacePreprocessor.SetOperate(false);
+                    FailureHandlingOptions fhoDe = tran.GetFailureHandlingOptions();
+                    fhoDe.SetFailuresPreprocessor(new SpaceFailuresPreprocessor(false) );
+                    tran.SetFailureHandlingOptions(fhoDe);
+                    //spacePreprocessor.SetOperate(false);
                     tran.Start();
-                    SpaceManager.DealSpaceFailuresPreprocessor(document,spacePreprocessor.Items,this);
+                    //返回值临时使用
+                    flag=SpaceManager.DealSpaceFailuresPreprocessor(document,spacePreprocessor.Items,this);
                     tran.Commit();
 
                     #endregion

+ 5 - 1
MBI/SAGA.MBI/WinView/Space/SpaceManager.cs

@@ -143,8 +143,10 @@ namespace SAGA.MBI.WinView
         /// <param name="doc"></param>
         /// <param name="failItems"></param>
         /// <param name="context">楼层上下文</param>
-        public static void DealSpaceFailuresPreprocessor(Document doc, List<FailItem> failItems,FloorSpaceContext context)
+        /// <returns>ture表示处理完成,false表示存在没处理的空间【冲突空间可能未处理】</returns>
+        public static bool DealSpaceFailuresPreprocessor(Document doc, List<FailItem> failItems,FloorSpaceContext context)
         {
+            bool flag = true;
             #region 处理逻辑
             /*
              * 1、根据条件过滤,满足自动处理的自动处理。
@@ -287,8 +289,10 @@ namespace SAGA.MBI.WinView
                 else
                 {
                     //没处理会有什么操作
+                    flag = false;
                 }
             }
+            return flag;
         }
 
         /// <summary>

+ 146 - 120
MBI/SAGA.MBI/WinView/Space/WinCreateSpace.xaml.cs

@@ -3,8 +3,6 @@ using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.IO;
 using System.Linq;
-using System.Reflection;
-using System.Text.RegularExpressions;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
@@ -19,20 +17,12 @@ using Point = System.Windows.Point;
 using System.Windows.Media.Animation;
 using System.Windows.Threading;
 using Autodesk.Revit.UI;
-using Newtonsoft.Json.Linq;
-using SAGA.DotNetUtils.Logger;
-using SAGA.MBI.Common;
 using SAGA.MBI.DataArrange;
-using SAGA.MBI.JsonConvert;
 using SAGA.MBI.Model;
-using SAGA.MBI.RequestData;
-using SAGA.MBI.Tools;
 using SAGA.MBI.WinView.ModeInfoMaintenance;
 using SAGA.RevitUtils;
 using SAGA.RevitUtils.Windows;
 using Visibility = System.Windows.Visibility;
-using Path = System.IO.Path;
-using System.Threading.Tasks;
 
 //TODO:1.目前存在的问题,如果只选两个已有的端点画线不能实现
 //TODO:2.画图过程中,ESC可取消当前画图
@@ -574,11 +564,15 @@ namespace SAGA.MBI.WinView.Space
         private void btnSave_Click(object sender, RoutedEventArgs e)
         {
             SaveFloor();
-
+            ExecuteCmd.ExecuteCommandOnce(() =>
+            {
+                if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
+                {
+                    InitFloor(floor);
+                }
+                return Result.Succeeded;
+            }, () => { return Result.Succeeded; });
         }
-
-   
-
         /// <summary>
         /// 离开画布,改变鼠标样式
         /// </summary>
@@ -588,7 +582,6 @@ namespace SAGA.MBI.WinView.Space
         {
             this.Cursor = Cursors.Arrow;
         }
-
         /// <summary>
         /// 鼠标进入画布,改变鼠标样式
         /// </summary>
@@ -690,32 +683,43 @@ namespace SAGA.MBI.WinView.Space
         /// <param name="e"></param>
         private void Tv_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
         {
-            //检测是否有未保存的数据,数据分两部分:新建的空间分隔符,删除的空间分隔符
-            #region 切换前节点处理
-            if (DeletedPolylines.Count > 0 || this.canvas.Children.OfType<UIElement>().Any(el => (el is WPolyline line && line.Stroke == Brushes.Red)))
+            try
             {
-                WinConfirm confirm = new WinConfirm()
-                {
-                    ShowMessage = "尚未保存空间变化,确认放弃修改?",
-                    TTitle = "空间修改确认",
-                    BtnSure = "保存并更改模型",
-                    BtnCancel = "放弃修改",
-                    Owner=this
-                    
-                };
-                var result = confirm.ShowDialog();
-                if (result == true)
+                //检测是否有未保存的数据,数据分两部分:新建的空间分隔符,删除的空间分隔符
+                #region 切换前节点处理
+                if (DeletedPolylines.Count > 0 || this.canvas.Children.OfType<UIElement>().Any(el => (el is WPolyline line && line.Stroke == Brushes.Red)))
                 {
-                    SaveFloor();
-                    return;
+                    WinConfirm confirm = new WinConfirm()
+                    {
+                        ShowMessage = "尚未保存空间变化,确认放弃修改?",
+                        TTitle = "空间修改确认",
+                        BtnSure = "保存并更改模型",
+                        BtnCancel = "放弃修改",
+                        Owner = this
+                    };
+                    var result = confirm.ShowDialog();
+                    if (result == true)
+                    {
+                        SaveFloor();
+                        //return;
+                    }                
                 }
-                DeletedPolylines.Clear();
-            } 
-            #endregion
-
-            if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
+                #endregion
+                //异步造成执行顺序混乱的情况,所以使用idling排队
+                ExecuteCmd.ExecuteCommandOnce(() =>
+                {                  
+                    if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
+                    {
+                        InitFloor(floor);
+                    }
+                    return Result.Succeeded;
+                }, () => { return Result.Succeeded; });
+             
+            }
+            catch (Exception ex)
             {
-                InitFloor(floor);
+
+                MessageShow.Show(ex);
             }
         }
 
@@ -723,6 +727,9 @@ namespace SAGA.MBI.WinView.Space
         {
             try
             {
+                //保存按钮不可用
+                this.btnSave.IsEnabled = false;
+                DeletedPolylines.Clear();
                 //关闭空间属性窗
                 WinModeInfoMaintenance.GetWindow().Hide();
                 this.canvas.Children.Clear();
@@ -813,83 +820,97 @@ namespace SAGA.MBI.WinView.Space
             m_isDraw = null;
             //需要保存的分隔符数据
             List<PointPair> saveDatas = GetPoints();
-            bool flagExecuteSuccess = true;//本应在回调函数里传值,目前代码不支持
-            ExecuteCmd.ExecuteCommandOnce(() =>
-            {
-                #region 创建空间
-                CurrentContext.UpdateSpaceSeqaration(saveDatas
-                                .Select(points => new SpaceSeparation(points.RPoint[0], points.RPoint[1])).ToList(),
-                            DeletedPolylines);
-                DeletedPolylines.Clear();
-                var createSuccess=CurrentContext.CreateSpaces();
-                if (!createSuccess)
-                {
-                    flagExecuteSuccess = false;
-                    MessageShow.Infomation("保存楼层空间失败");
-                    return Result.Succeeded;
-                }
-
-                #endregion
-
-                #region 初始化界面
-                this.canvas.IsEnabled = true;
-                btnOrigin_Click(null, null);
-                InitData();
-
-                #endregion
+            bool flagExecuteSuccess = true; //本应在回调函数里传值,目前代码不支持
+            #region 扩展事件处理相关
 
-                #region 上传模型选择
-                Window confirm = GetUploadConfirm();
-                var result = confirm.ShowDialog();
-                //选择以后界面可用
-                this.IsEnabled = true;
-                if (result == true)
-                {
-                    // 由于上传需要关闭所有模型,所以这里需要对所有数据进行清空
-                    this.canvas.Children.Clear();
-                    //添加默认提示
-                    CanvasDefaultTips();
-                    lbSpaces.ItemsSource = new ObservableCollection<MSpace>();
-                    WinModeInfoMaintenance.GetWindow().Hide();
-
-                    #region 错误尝试
-                    //上传中的一些操作,不能发生在idling中
-
-                    //    Action<FloorSpaceContext> action = new Action<FloorSpaceContext>((context) =>
-                    //    {
-                    //        try
-                    //        {
-                    //             CurrentContext.Document.Save();
-                    //            SpaceManager.UploadModel(context.Document);
-                    //        }
-                    //        catch (Exception ex)
-                    //        {
-                    //            MessageShow.Show(ex);
-                    //        }
-                    //    });
-                    //    action.BeginInvoke(CurrentContext, null, null); 
-                    #endregion
-                }
-                #endregion
-                return Result.Succeeded;
-            }, () =>
-            {
-                if (!flagExecuteSuccess)
-                {
-                    return Result.Succeeded;
-                }
+            EventCommand updateCommand = new EventCommand(new ExternalEventHandler((app) => {
                 try
                 {
                     var document = CurrentContext.Document;
                     document.Save();
-                   
+                    if (!flagExecuteSuccess)
+                    {
+                        return;
+                    }
                     SpaceManager.UploadModel(document);
                 }
                 catch (Exception ex)
                 {
                     MessageShow.Show(ex);
                 }
-                 return Result.Succeeded;
+            }));
+            #endregion
+            ExecuteCmd.ExecuteCommandOnce(() =>
+            {
+                try
+                {
+                    updateCommand.Register();
+                    #region 创建空间
+                    using (TransactionGroup group = new TransactionGroup(CurrentContext.Document, "保存空间修改"))
+                    {
+                        group.Start();
+                        CurrentContext.UpdateSpaceSeqaration(saveDatas
+                                .Select(points => new SpaceSeparation(points.RPoint[0], points.RPoint[1])).ToList(),
+                            DeletedPolylines);
+                        DeletedPolylines.Clear();
+                        var createSuccess = CurrentContext.CreateSpaces();
+                        if (!createSuccess)
+                        {
+                            flagExecuteSuccess = false;
+                            group.RollBack();
+                            MessageShow.Infomation("保存楼层空间失败");                       
+                            return Result.Succeeded;
+                        }
+                        group.Assimilate();
+                    }
+                    #endregion
+
+                    #region 上传模型选择
+                    Window confirm = GetUploadConfirm();
+                    var result = confirm.ShowDialog();
+                    //选择以后界面可用
+                    this.IsEnabled = true;
+                    if (result == true)
+                    {
+                        // 由于上传需要关闭所有模型,所以这里需要对所有数据进行清空
+                        this.canvas.Children.Clear();
+                        //添加默认提示
+                        CanvasDefaultTips();
+                        lbSpaces.ItemsSource = new ObservableCollection<MSpace>();
+                        WinModeInfoMaintenance.GetWindow().Hide();
+                    }
+                    else
+                    {
+                        flagExecuteSuccess = false;
+                    }
+                    #endregion
+                }
+                finally
+                {
+                    this.IsEnabled = true;
+                }
+
+                return Result.Succeeded;
+            }, () =>
+            {
+                #region 代码中包含事务,不能再回调线程中使用
+                //try
+                //{
+                //    var document = CurrentContext.Document;
+                //    document.Save();
+                //    if (!flagExecuteSuccess)
+                //    {
+                //        return Result.Succeeded;
+                //    }
+                //    SpaceManager.UploadModel(document);
+                //}
+                //catch (Exception ex)
+                //{
+                //    MessageShow.Show(ex);
+                //}
+                #endregion
+                updateCommand.Raise();
+                return Result.Succeeded;
             });
         }
 
@@ -984,29 +1005,34 @@ namespace SAGA.MBI.WinView.Space
 
         private void lbSpaces_SelectionChanged(object sender, SelectionChangedEventArgs e)
         {
-            if (lbSpaces.SelectedItems.Count == 0) return;
-            var space = lbSpaces.SelectedItems[0] as MSpace;
-
-
-
-            var bimId = space.BimID.Split(':')[1];
-
-            foreach (var polyline in this.canvas.Children.OfType<WPolyline>())
+            try
             {
-                if (polyline.Tag is Autodesk.Revit.DB.Mechanical.Space s)
+                #region 核心代码
+                if (lbSpaces.SelectedItems.Count == 0) return;
+                var space = lbSpaces.SelectedItems[0] as MSpace;
+                var bimId = space.BimID.Split(':')[1];
+                foreach (var polyline in this.canvas.Children.OfType<WPolyline>())
                 {
-                    if (s.Id.ToString() == (bimId))
+                    if (polyline.Tag is Autodesk.Revit.DB.Mechanical.Space s)
                     {
-                        polyline.Fill = Brushes.Aquamarine;
+                        if (s.Id.ToString() == (bimId))
+                        {
+                            polyline.Fill = Brushes.Aquamarine;
 
-                        //显示属性窗口
-                        ShowSpaceProperty(s);
-                    }
-                    else if (polyline.Fill == Brushes.Aquamarine)
-                    {
-                        polyline.Fill = Brushes.Transparent;
+                            //显示属性窗口
+                            ShowSpaceProperty(s);
+                        }
+                        else if (polyline.Fill == Brushes.Aquamarine)
+                        {
+                            polyline.Fill = Brushes.Transparent;
+                        }
                     }
                 }
+                #endregion
+            }
+            catch (Exception ex)
+            {
+                MessageShow.Show(ex);
             }
         }
 

+ 76 - 9
MBI/SAGA.MBI/WinView/Space/WinCreateSpaceWeb.xaml

@@ -6,19 +6,86 @@
              xmlns:local="clr-namespace:SAGA.MBI.WinView.Space"
              xmlns:windows="clr-namespace:SAGA.RevitUtils.Windows;assembly=SAGA.RevitUtils"
              xmlns:cefSharpWpf="clr-namespace:CEFSharpWPF;assembly=CEFSharpWPF"
-                 Title="空间管理"
-             mc:Ignorable="d" 
-             d:DesignHeight="450" d:DesignWidth="800">
+             xmlns:converter="clr-namespace:SAGA.DotNetUtils.WPF.Converter;assembly=SAGA.DotNetUtils"
+             Title="空间管理" mc:Ignorable="d" Height="950" Width="1525">
+    <Window.Resources>
+        <Style TargetType="Button">
+            <Setter Property="Height" Value="30"/>
+            <Setter Property="Width" Value="100"/>
+            <Setter Property="Margin" Value="10"></Setter>
+        </Style>
+        <converter:StringToImageConverter  x:Key="StringToImageConverter"/>
+    </Window.Resources>
     <Grid>
         <Grid.RowDefinitions>
-            <RowDefinition></RowDefinition>
-            <RowDefinition Height="Auto"></RowDefinition>
-              <RowDefinition Height="Auto"></RowDefinition>
-               <RowDefinition Height="Auto"></RowDefinition>
+            <RowDefinition Height="50"/>
+            <RowDefinition Height="*"/>
+            <RowDefinition Height="50"/>
         </Grid.RowDefinitions>
-        <cefSharpWpf:UcGplotShow Grid.Row="0" Grid.Column="0" x:Name="ucShowElement"></cefSharpWpf:UcGplotShow>
-            <TextBox Name="Js" Grid.Row="1"></TextBox>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="200"/>
+            <ColumnDefinition Width="*"/>
+            <ColumnDefinition Width="200"/>
+        </Grid.ColumnDefinitions>
+
+        <TreeView Grid.Row="0" Grid.Column="0" Grid.RowSpan="3"  Name="tv"  Margin="10,10"  SelectedItemChanged="Tv_OnSelectedItemChanged">
+            <TreeView.ItemTemplate >
+                <HierarchicalDataTemplate ItemsSource="{Binding Path=Children,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" >
+                    <RadioButton IsChecked="{Binding Path=IsSelected}">
+                        <RadioButton.Style>
+                            <Style TargetType="RadioButton">
+                                <Setter Property="Template">
+                                    <Setter.Value>
+                                        <ControlTemplate TargetType="RadioButton">
+                                            <Border x:Name="myBorder" >
+                                                <StackPanel Orientation="Horizontal" >
+                                                    <Image Source="{Binding Path=ImageStr,Converter={StaticResource StringToImageConverter}}"></Image>
+                                                    <TextBlock x:Name="myText" VerticalAlignment="Bottom" Text="{Binding Path=Item.TvItemName,UpdateSourceTrigger=PropertyChanged}" ></TextBlock>
+                                                </StackPanel>
+                                            </Border>
+                                            <ControlTemplate.Triggers>
+                                                <Trigger Property="IsChecked" Value="True">
+                                                    <Setter TargetName="myBorder" Property="Background" Value="Blue"></Setter>
+                                                    <Setter TargetName="myText" Property="Foreground" Value="White"></Setter>
+                                                </Trigger>
+                                                <Trigger Property="IsChecked" Value="False">
+                                                    <Setter TargetName="myBorder" Property="Background" Value="White"></Setter>
+                                                    <Setter TargetName="myText" Property="Foreground" Value="Black"></Setter>
+                                                </Trigger>
+                                            </ControlTemplate.Triggers>
+                                        </ControlTemplate>
+                                    </Setter.Value>
+                                </Setter>
+                            </Style>
+                        </RadioButton.Style>
+                    </RadioButton>
+
+
+                </HierarchicalDataTemplate>
+            </TreeView.ItemTemplate>
+            <TreeView.ItemContainerStyle>
+                <Style TargetType="{x:Type TreeViewItem}">
+                    <Setter Property="IsExpanded" Value="True" />
+                    <Setter Property="IsSelected" Value="{Binding Path=IsSelected}"></Setter>
+                    <!--<EventSetter Event="TreeViewItem.LostFocus" Handler="TreeViewItem_LostFocus"></EventSetter>-->
+                </Style>
+            </TreeView.ItemContainerStyle>
+        </TreeView>
+
+        <cefSharpWpf:UcGplotShow Grid.Row="0" Grid.Column="1" Grid.RowSpan="3" x:Name="ucShowElement"></cefSharpWpf:UcGplotShow>
+
+
+
+        <ListBox Name="lbSpaces" Grid.Row="0"  Grid.Column="2" Grid.RowSpan="3" SelectionChanged="lbSpaces_SelectionChanged" SelectionMode="Single">
+            <ListBox.ItemTemplate>
+                <DataTemplate>
+                    <TextBlock Text="{Binding }"></TextBlock>
+                </DataTemplate>
+            </ListBox.ItemTemplate>
+        </ListBox>
+        <TextBox Name="Js" Grid.Row="1"></TextBox>
         <Button Content="调用" Grid.Row="2" Click="Button_Click"></Button>
          <Button Content="刷新" Grid.Row="3" Click="Button_Click_1" ></Button>
     </Grid>
+
 </windows:WinBase>

+ 337 - 19
MBI/SAGA.MBI/WinView/Space/WinCreateSpaceWeb.xaml.cs

@@ -1,18 +1,23 @@
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Newtonsoft.Json.Linq;
+using SAGA.DotNetUtils;
+using SAGA.MBI.DataArrange;
+using SAGA.MBI.Model;
+using SAGA.MBI.RevitExport;
+using SAGA.MBI.WinView.ModeInfoMaintenance;
+using SAGA.RevitUtils;
+using SAGA.RevitUtils.Extends;
 using SAGA.RevitUtils.Windows;
+using Visibility = System.Windows.Visibility;
 
 namespace SAGA.MBI.WinView.Space
 {
@@ -25,14 +30,320 @@ namespace SAGA.MBI.WinView.Space
         {
             InitializeComponent();
              ucShowElement.RegisterJsObject("wpfEvent", this);
-            this.Loaded += WinCreateSpaceWeb_Loaded;
-         
-           
+            this.Loaded += WinCreateSpaceWeb_Loaded;                  
         }
-
         private void WinCreateSpaceWeb_Loaded(object sender, RoutedEventArgs e)
         {
-               ucShowElement.Show(" http://192.168.20.86:8091/#/demo");
+            InitData();
+            ucShowElement.Show(" http://192.168.20.86:8091/#/demo");
+        }
+
+        private void InitData()
+        {
+            tv.ItemsSource = new ObservableCollection<TreeNodeItem>(DalModeFileManange.GetMissFileFloors(false));
+        }
+
+        #region 条目切换事件
+      
+        private void Tv_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
+        {
+            try
+            {
+                #region 核心代码
+                //检测是否有未保存的数据,数据分两部分:新建的空间分隔符,删除的空间分隔符
+                //删除空间分割的id和新建空间分割的线
+                var editData = GetEditData();
+                List<int> deletedIds = editData.DeletedIds;
+                var newDatas = editData.NewDatas;
+                #region 切换前节点处理
+                if (deletedIds.Count > 0 || newDatas.Any())
+                {
+                    WinConfirm confirm = CreateSaveConfirm();
+                    var result = confirm.ShowDialog();
+                    if (result == true)
+                    {
+                        SaveFloor(editData);
+                       // return;
+                    }
+                }
+                #endregion
+                //异步造成执行顺序混乱的情况,所以使用idling排队
+                ExecuteCmd.ExecuteCommandOnce(() =>
+                {
+                    if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
+                    {
+                        InitFloor(floor);
+                    }
+
+                    return Result.Succeeded;
+                }, () => { return Result.Succeeded; });
+                #endregion
+            }
+            catch (Exception ex)
+            {
+
+                MessageShow.Show(ex);
+            }
+        }
+
+        /// <summary>
+        /// 切换空间,亮显空间
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+
+        private void lbSpaces_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            try
+            {
+                if (lbSpaces.SelectedItems.Count == 0) return;
+                var space = lbSpaces.SelectedItems[0] as MSpace;
+                var bimId = space.BimID.Split(':')[1];
+                //发送js填充命令
+                var strJs = $"getData('{bimId.ToString()}')";
+                ucShowElement.ExecuteJsFun(strJs);
+                #region 显示属性窗格
+                var doc = CurrentContext.Document;
+                if (doc == null)
+                    return;
+                var revitSpace = doc.GetElement(new ElementId(bimId.ToInt()));
+                if (revitSpace == null)
+                    return;
+                MRevitEquipBase equipment = DalCommon.GetEquipmentQueryId(revitSpace);
+                if (equipment != null)
+                {
+                    var win = WinModeInfoMaintenanceForSpace.GetWindow();
+                    win.Topmost = true;
+                    win.Show(equipment);
+                    win.Visibility = Visibility.Visible;
+                }
+               #endregion
+            }
+            catch (Exception ex)
+            {
+                MessageShow.Show(ex);
+            }
+        }
+        #endregion
+
+
+        #region 确认窗口初始化
+        /// <summary>
+        /// 创建保存确认提示框
+        /// </summary>
+        /// <returns></returns>
+        private WinConfirm CreateSaveConfirm()
+        {
+            WinConfirm confirm = new WinConfirm()
+            {
+                ShowMessage = "尚未保存空间变化,确认放弃修改?",
+                TTitle = "空间修改确认",
+                BtnSure = "保存并更改模型",
+                BtnCancel = "放弃修改",
+                Owner = this
+
+            };
+            return confirm;
+        }
+        /// <summary>
+        /// 获取上传确认窗口
+        /// </summary>
+        /// <returns></returns>
+        private Window CreateUploadConfirm()
+        {
+            WinConfirm confirm = new WinConfirm()
+            {
+                ShowMessage = "空间已发生变化,是否现在就上传模型并计算空间?",
+                TTitle = "空间计算确认",
+                BtnSure = "上传模型并计算空间",
+                BtnCancel = "暂不计算",
+                Owner = this,
+            };
+            return confirm;
+        }
+        #endregion
+
+        #region 界面信息相关处理
+        /// <summary>
+        /// 清理窗口显示的楼层相关数据
+        /// </summary>
+        private void ClearFloorData()
+        {
+            WinModeInfoMaintenance.GetWindow().Hide();
+            this.lbSpaces.ItemsSource = new ObservableCollection<MSpace>(); ;
+        }
+        /// <summary>
+        /// 设置窗口楼层相关数据
+        /// </summary>
+        public void SetFloorData(Document document)
+        {
+            var spaces = CurrentContext.Document.GetElements<SpatialElement>().Where(s => s is Autodesk.Revit.DB.Mechanical.Space && s.Area > 0).ToList();
+            var datas = CurrentContext.GetPhysicalSpaces(spaces.Select(t => t.Id.IntegerValue.ToString()).ToList());
+            var localSpace = spaces.Where(t => !datas.Any(s => s.BimID.Split(':')[1] == t.Id.ToString()))
+                .Select(t => new MSpace("", $"{Guid.NewGuid()}:{t.Id.ToString()}") { Name = t.Name});
+            datas.AddRange(localSpace);
+            lbSpaces.ItemsSource = new ObservableCollection<MSpace>(datas);
+        }
+
+        #endregion
+
+        #region 空间管理相关逻辑
+        public FloorSpaceContext CurrentContext;
+        public void InitFloor(MFloor floor)
+        {
+            try
+            {
+                ClearFloorData();
+                #region 数据整理
+                FloorSpaceContext context = new FloorSpaceContext(floor);
+                CurrentContext = context;
+                var doc = context.Document;
+                var view = doc.GetUseView();
+                if (view == null)
+                {
+                    MessageBox.Show("无法找到名称以-saga结尾的视图!");
+                    return;
+                }
+                ExecuteCmd.ExecuteCommand(() =>
+                {
+                    context.CreateSpaces();
+                    #region 初始化界面
+                    SetCanvasShow();
+                    #endregion
+                    SetFloorData(doc);
+                    return Result.Succeeded;
+                });
+                #endregion           
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.Message);
+            }
+        }
+
+        private void SaveFloor(EditData editData)
+        {
+            //禁用界面,防止重复提交
+            this.IsEnabled = false;
+            var deletedIds = editData.DeletedIds;
+            List<PointPair> saveDatas = editData.NewDatas;
+            bool flagExecuteSuccess = true;//本应在回调函数里传值,目前代码不支持
+            ExecuteCmd.ExecuteCommandOnce(() =>
+            {
+                #region 创建空间
+                var seqs = saveDatas.Select(points => new SpaceSeparation(points.RPoint[0], points.RPoint[1])).ToList();
+                using (TransactionGroup group = new TransactionGroup(CurrentContext.Document, "保存空间修改"))
+                {
+                    group.Start();
+                    CurrentContext.UpdateSpaceSeqaration(seqs, deletedIds);
+                    var createSuccess = CurrentContext.CreateSpaces();
+                    if (!createSuccess)
+                    {
+                        flagExecuteSuccess = false;
+                        group.RollBack();
+                        MessageShow.Infomation("保存楼层空间失败");
+                        return Result.Succeeded;
+                    }
+
+                    group.Assimilate();
+                }
+
+              
+                #endregion
+                #region 初始化界面
+                SetCanvasShow();
+                #endregion
+                #region 上传模型选择
+                Window confirm = CreateUploadConfirm();
+                var result = confirm.ShowDialog();
+                //选择以后界面可用
+                this.IsEnabled = true;
+                if (result == true)
+                {
+                    //添加默认提示
+                    SetEmptyTip();
+                    ClearFloorData();
+                }
+                else
+                {
+                    flagExecuteSuccess = false;
+                }
+                #endregion
+                return Result.Succeeded;
+            }, () =>
+            {
+                try
+                {
+                    var document = CurrentContext.Document;
+                    document.Save();
+                    if (!flagExecuteSuccess)
+                    {
+                        return Result.Succeeded;
+                    }
+                    SpaceManager.UploadModel(document);
+                }
+                catch (Exception ex)
+                {
+                    MessageShow.Show(ex);
+                }
+                return Result.Succeeded;
+            });
+        }
+        #endregion
+
+
+        #region 界面交互
+
+        public EditData GetEditData()
+        {
+            EditData data = new EditData();
+            return data;
+        }
+
+        public void SetEmptyTip()
+        {
+            //清空空间,提示相关信息
+            string tips = "请选择一个需要进行空间管理的楼层";
+        }
+
+        public void SetCanvasShow()
+        {
+            var jobject = GetModelDrawing();
+            
+        }
+        #endregion
+
+        #region js调用命令
+
+        public void Save()
+        {
+
+            var editData = GetEditData();
+            SaveFloor(editData);
+            ExecuteCmd.ExecuteCommandOnce(() =>
+            {
+                if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
+                {
+                    InitFloor(floor);
+                }
+                return Result.Succeeded;
+            }, () => { return Result.Succeeded; });
+            MessageBox.Show("Save");
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 获取模型绘图数据
+        /// </summary>
+        /// <returns></returns>
+        private JObject GetModelDrawing()
+        {
+            //柱子,墙,虚拟墙,空间
+            Document linkDoc = CurrentContext.Document;
+            MbiElementManager manager = new MbiElementManager();
+            var exportDb = manager.ExportMbiEelemntDB(ExportDataBuilder.CreateExportData(linkDoc));
+            return exportDb.ToJsonObject();
         }
 
         private void Button_Click(object sender, RoutedEventArgs e)
@@ -48,12 +359,7 @@ namespace SAGA.MBI.WinView.Space
             ucShowElement.ExecuteJsFun(strJs);
         }
 
-        public void Save()
-        {
-         
-
-            MessageBox.Show("Save");
-        }
+       
 
         public void SaveStr(string path)
         {
@@ -73,5 +379,17 @@ namespace SAGA.MBI.WinView.Space
                ucShowElement.Show(" http://192.168.20.86:8091/#/demo");
         }
     }
- 
+
+
+    public class EditData
+    {
+        public EditData()
+        {
+            DeletedIds = new List<int>();
+            NewDatas = new List<PointPair>();
+        }
+
+        public List<int> DeletedIds { get; set; }
+        public List<PointPair> NewDatas { get; set; }
+    }
 }

+ 3 - 0
MBI/SAGA.Models/DrawDataServer.cs

@@ -129,6 +129,7 @@ namespace SAGA.Models {
             DbHelper.SaveAsFile(wd);
         }
         public static SpaceData GetSpaceData(SpaceRelatedEnum spaceRelated) {
+            //每次读取都是新的数据源
             SpaceData dn = DbHelper.FindOneByFile<SpaceData>();
             if (dn == null) return default(SpaceData);
 
@@ -143,6 +144,8 @@ namespace SAGA.Models {
                 foreach (var sgElement in fd.EndPoints) {
                     if (sgElement is SgSpace space) {
                         space.AdjacentSpaces = space.AdjacentSpaces.Where(Predicate).ToList();
+                        //垂直空间也处理
+                        space.UpElements = space.UpElements.Where(Predicate).ToList();
                     }
                 }
             }

+ 6 - 1
MBI/SAGA.Models/Graphs/GElement.cs

@@ -21,7 +21,7 @@ namespace SAGA.Models.Graphs
         /// <summary>
         /// 关联Id
         /// </summary>
-        public int Id { get; internal set; }
+        public string Id { get; internal set; }
         public string Name { get; set; } = string.Empty;
         /// <summary>
         /// 元素类型
@@ -33,5 +33,10 @@ namespace SAGA.Models.Graphs
         /// 关联数据
         /// </summary>
         public object RefData { get; set; }
+
+        public void SetId(string id)
+        {
+            Id = id;
+        }
     }
 }

+ 2 - 1
MBI/SAGA.Models/Graphs/GElementConverter.cs

@@ -63,7 +63,8 @@ namespace SAGA.Models.Graphs
                         var result = serializer.Deserialize(jObject.CreateReader(), useType);
                         if (result is GElement element)
                         {
-                            element.Id = Convert.ToInt32(jObject["Id"]?.ToString());
+                            //element.Id = Convert.ToInt32(jObject["Id"]?.ToString());
+                            element.Id = jObject["Id"]?.ToString();
                         }
                         return result;
                     }

+ 5 - 0
MBI/SAGA.Models/Graphs/VElements/GVElement.cs

@@ -20,5 +20,10 @@ namespace SAGA.Models.Graphs
         /// 楼层信息
         /// </summary>
         public string FloorId { get; set; }
+
+        /// <summary>
+        /// 描述信息
+        /// </summary>
+        public string Tip { get; set; }
     }
 }

+ 2 - 0
MBI/SAGA.Models/VerticalPipe.cs

@@ -21,6 +21,8 @@ namespace SAGA.Models
 
         public Point CPoint { get; set; }
         public string PipeSytemType { get; set; }
+        public string Display { get; set; }
+        public string DisplayTip { get; set; }
     }
     [TableName("VerticalPipeDatass")]
     public class VerticalPipeData

+ 33 - 2
MBI/SAGA.RevitUtils/ExtendInterface/RevitEventsBingding.cs

@@ -15,17 +15,24 @@ namespace SAGA.RevitUtils
         static RevitEventsBingding()
         {
             EventsSetting = new RevitEventsSetting();
-        }
-        
+        }        
         public static void AddEvents(UIControlledApplication application)
         {
+            CurrentApp = application;
             application.ControlledApplication.DocumentSaved += Application_DocumentSaved;
+            AddUpdater();
         }
         public static void RemoveEvents(UIControlledApplication application)
         {
             application.ControlledApplication.DocumentSaved -= Application_DocumentSaved;
+            RemoveUpdater();
+            CurrentApp = application;
         }
         /// <summary>
+        /// 关联引用程序
+        /// </summary>
+        public static UIControlledApplication CurrentApp { get;private set; }
+        /// <summary>
         /// 保存使用的扩展
         /// </summary>
         private static List<IDocumentSaved> DocumentSaved { get;  set; }
@@ -40,5 +47,29 @@ namespace SAGA.RevitUtils
                 item.Handle(sender, e);
             }
         }
+
+        private static List<IUpdaterRegister> UpdaterRegister { get; set; }
+        public static void AddUpdater()
+        {
+            if (UpdaterRegister == null)
+            {
+                UpdaterRegister = EventsSetting.GetEventObjects<IUpdaterRegister>() ?? new List<IUpdaterRegister>();
+            }
+            foreach (var item in UpdaterRegister)
+            {
+                item.Register();
+            }
+        }
+        public static void RemoveUpdater()
+        {
+            if (UpdaterRegister == null)
+            {
+                UpdaterRegister = EventsSetting.GetEventObjects<IUpdaterRegister>() ?? new List<IUpdaterRegister>();
+            }
+            foreach (var item in UpdaterRegister)
+            {
+                item.UnRegist();
+            }
+        }
     }
 }

+ 221 - 0
MBI/SAGA.RevitUtils/ExtendInterface/RevitTrigger.cs

@@ -0,0 +1,221 @@
+using System;
+using System.Collections.Generic;
+using Autodesk.Revit.DB;
+
+namespace SAGA.RevitUtils.ExtendInterface
+{
+    #region 系统类封装
+    /*
+* 不知道revit的机制是不是一样的触发器会合并所有Updater,待测试。
+* 但一个updater可以被几个触发器关联
+*/
+    public class RevitUpdater : IUpdater
+    {
+        /*
+         * 可以通过扩展继承该类
+         */
+        protected Action<UpdaterData> m_Execute;
+        public RevitUpdater(UpdaterId id, Action<UpdaterData> execute)
+        {
+            this.Id = id;
+            this.m_Execute = execute;
+        }
+        #region 接口继承方法
+        public virtual void Execute(UpdaterData data)
+        {
+            if (m_Execute != null)
+            {
+                m_Execute(data);
+            }
+        }
+        public string GetAdditionalInformation()
+        {
+            return AdditionalInformation ?? string.Empty;
+        }
+
+        public ChangePriority GetChangePriority()
+        {
+            return ChangePriority;
+        }
+        public UpdaterId GetUpdaterId()
+        {
+            return Id;
+        }
+
+        public string GetUpdaterName()
+        {
+            return UpdaterName ?? this.GetType().ToString();
+        }
+        #endregion
+
+        #region 相关属性延伸
+        /// <summary>
+        /// 附加信息
+        /// </summary>
+        public string AdditionalInformation { get; set; }
+        /// <summary>
+        /// 触发器名称
+        /// </summary>
+        public string UpdaterName { get; set; }
+
+        /// <summary>
+        /// 改变优先级
+        /// </summary>
+        public ChangePriority ChangePriority { get; set; }
+        /// <summary>
+        /// UpdaterId
+        /// </summary>
+        public UpdaterId Id { get; protected set; }
+        #endregion
+
+
+        #region 注册和注销
+        private bool IsExistId(Document doc)
+        {
+            bool flag = false;
+            if (doc == null)
+            {
+                flag = UpdaterRegistry.IsUpdaterRegistered(this.GetUpdaterId());
+            }
+            else
+            {
+                flag = UpdaterRegistry.IsUpdaterRegistered(this.GetUpdaterId(), doc);
+            }
+            return flag;
+        }
+
+        public void RegisterUpdater(Document doc, bool isOptional = true)
+        {
+            if (IsExistId(doc))
+                return;
+            if (doc == null)
+            {
+                UpdaterRegistry.RegisterUpdater(this, isOptional);
+            }
+            else
+            {
+                UpdaterRegistry.RegisterUpdater(this, doc, isOptional);
+            }
+        }
+        public void UnregisterUpdater(Document doc)
+        {
+            if (!IsExistId(doc))
+                return;
+            if (doc == null)
+            {
+                UpdaterRegistry.UnregisterUpdater(this.Id);
+            }
+            else
+            {
+                UpdaterRegistry.UnregisterUpdater(this.Id, doc);
+            }
+        }
+        #endregion  
+    }
+
+    /// <summary>
+    /// 触发器就是过滤器
+    /// </summary>
+    public class RevitTrigger
+    {
+        public RevitTrigger(ElementFilter filter, ChangeType change)
+        {
+            Filter = filter;
+            ChangeType = change;
+        }
+        public RevitTrigger(Document document, ElementFilter filter, ChangeType change) : this(filter, change)
+        {
+            Document = document;
+        }
+        public RevitTrigger(Document document, ICollection<ElementId> elements, ChangeType change) : this(document, filter: null, change: change)
+        {
+            ElementIds = elements;
+        }
+        #region 触发器关联属性
+        public Document Document { get; set; }
+        public ICollection<ElementId> ElementIds { get; set; }
+        public ChangeType ChangeType { get; set; }
+        public ElementFilter Filter { get; set; }
+        #endregion
+        #region 方法标记
+        /// <summary>
+        /// 附加触发器
+        /// </summary>
+        /// <param name="updater"></param>
+        public void AttachUpdater(RevitUpdater updater)
+        {
+            AttachUpdaterId(updater.GetUpdaterId());
+        }
+        public void AttachUpdaterId(UpdaterId updaterId)
+        {
+            if (Document == null)
+            {
+                UpdaterRegistry.AddTrigger(updaterId, Filter, ChangeType);
+            }
+            else if (ElementIds == null)
+            {
+                UpdaterRegistry.AddTrigger(updaterId, Document, Filter, ChangeType);
+            }
+            else if (Filter == null)
+            {
+                UpdaterRegistry.AddTrigger(updaterId, Document, ElementIds, ChangeType);
+            }
+        }
+        #endregion
+    } 
+    #endregion
+
+    public interface IUpdaterRegister
+    {
+        void Register();
+        void UnRegist();
+    }
+
+    /// <summary>
+    /// 注册updater相关
+    /// </summary>
+    public abstract class UpdaterRegister : IUpdaterRegister
+    {
+        public UpdaterRegister()
+        {
+        }
+        /// <summary>
+        /// 关联项目
+        /// </summary>
+        public Document RefDocument { get; set; }
+        public bool IsOptional { get; set; }
+        /// <summary>
+        /// 当前updater,注册后生效
+        /// </summary>
+        public RevitUpdater CurrentUpdater { get; private set; }
+        /// <summary>
+        /// 注册更新触发器
+        /// </summary>
+        public virtual  void Register()
+        {
+            CurrentUpdater = GetUpdater();
+            if (CurrentUpdater == null)
+                return;
+            CurrentUpdater.RegisterUpdater(RefDocument, IsOptional);
+            var triggers = GetTriggers();
+            foreach (var revitTrigger in triggers)
+            {
+                revitTrigger.AttachUpdater(CurrentUpdater);
+            }
+        }
+        /// <summary>
+        /// 注销更新触发器
+        /// </summary>
+        public virtual  void UnRegist()
+        {
+            CurrentUpdater = CurrentUpdater??GetUpdater();
+            if (CurrentUpdater == null)
+            {
+                return;
+            }
+            CurrentUpdater.UnregisterUpdater(RefDocument);
+        }
+        protected abstract List<RevitTrigger> GetTriggers();
+        protected abstract RevitUpdater GetUpdater();
+    }
+}

+ 11 - 0
MBI/SAGA.RevitUtils/MBIExtension/MBIDocExtension.cs

@@ -11,6 +11,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Autodesk.Revit.DB;
+using SAGA.DotNetUtils.Extend;
 using SAGA.RevitUtils.Extends;
 
 namespace SAGA.RevitUtils
@@ -28,5 +29,15 @@ namespace SAGA.RevitUtils
                       t.Name?.IndexOf("-saga") > -1 && t.ViewType == ViewType.FloorPlan);
             return view;
         }
+        /// <summary>
+        /// 获取element的BimId
+        /// </summary>
+        /// <param name="element"></param>
+        /// <returns></returns>
+        public static string GetBimId(this Element element)
+        {
+            var doc = element.Document;
+            return string.Format($"{doc.PathName.GetFileName()}:{element.Id.IntegerValue}");
+        }
     }
 }

+ 1 - 0
MBI/SAGA.RevitUtils/SAGA.RevitUtils.csproj

@@ -175,6 +175,7 @@
     </Compile>
     <Compile Include="ExtendInterface\IDocumentSaved.cs" />
     <Compile Include="ExtendInterface\RevitEventsSetting.cs" />
+    <Compile Include="ExtendInterface\RevitTrigger.cs" />
     <Compile Include="Extends\ArcExtend.cs" />
     <Compile Include="Extends\Configuration.cs" />
     <Compile Include="Extends\CurveArrayExtend.cs" />