Преглед на файлове

Merge branch 'master' of https://git.dev.tencent.com/xuhuo1234/saga

xulisong преди 6 години
родител
ревизия
e2ddbecc5e
променени са 38 файла, в които са добавени 4908 реда и са изтрити 262 реда
  1. 63 0
      .gitattributes
  2. 1 0
      MBI/.gitignore
  3. 2 0
      MBI/MBIResource/Config/HttpSetting.ini
  4. BIN
      MBI/MBIResource/Family/坐标箭头.rfa
  5. 13 37
      MBI/Menu/MBITool.xml
  6. 53 0
      MBI/Menu/Tool.xml
  7. 29 0
      MBI/SAGA.DotNetUtils/Geometry/Extends.cs
  8. 1681 0
      MBI/SAGA.DotNetUtils/Geometry/Geometry2d.cs
  9. 89 0
      MBI/SAGA.DotNetUtils/Geometry/HTwoPointRelation.cs
  10. 413 0
      MBI/SAGA.DotNetUtils/Geometry/OffsetPolyLine.cs
  11. 76 0
      MBI/SAGA.DotNetUtils/Geometry/RelationOptions.cs
  12. 592 0
      MBI/SAGA.DotNetUtils/Geometry/TszGeoUtil.cs
  13. 103 0
      MBI/SAGA.DotNetUtils/Geometry/TszTransform.cs
  14. 907 0
      MBI/SAGA.DotNetUtils/Geometry/TszXYZ.cs
  15. 63 0
      MBI/SAGA.DotNetUtils/Geometry/TwoPointRelation.cs
  16. 89 0
      MBI/SAGA.DotNetUtils/Geometry/VTwoPointRelation.cs
  17. 10 0
      MBI/SAGA.DotNetUtils/SAGA.DotNetUtils.csproj
  18. 4 3
      MBI/SAGA.MBI/Calc/ObjectCalc.cs
  19. 1 115
      MBI/SAGA.MBI/DataArrange/DalUploadFloor.cs
  20. 4 12
      MBI/SAGA.MBI/Extend/ElementExtend.cs
  21. 11 1
      MBI/SAGA.MBI/RequestData/UpLoadFileRequest.cs
  22. 72 0
      MBI/SAGA.MBI/RequestData/WebRequestProxy.cs
  23. 1 1
      MBI/SAGA.MBI/SAGA.MBI.csproj
  24. 118 0
      MBI/SAGA.MBI/TestCommand.cs
  25. 1 75
      MBI/SAGA.MBI/ToolCommand.cs
  26. 3 2
      MBI/SAGA.MBI/ToolsData/CheckEquipCategory.cs
  27. 5 3
      MBI/SAGA.MBI/ToolsData/CheckEquipInSpace.cs
  28. 5 3
      MBI/SAGA.MBI/ToolsData/ModeCheck/EquipmentInSpaceCheck.cs
  29. 77 0
      MBI/SAGA.Revit.sln
  30. 16 2
      MBI/SAGA.RevitUtils/Extends/XYZExtend.cs
  31. 159 0
      MBI/ToolCommand/Command.cs
  32. 58 0
      MBI/ToolCommand/DelZeroSpace.cs
  33. 3 8
      MBI/SAGA.MBI/ToolsData/ExportAllCategory.cs
  34. 36 0
      MBI/ToolCommand/Properties/AssemblyInfo.cs
  35. 96 0
      MBI/ToolCommand/ToolCommand.csproj
  36. 16 0
      MBI/ToolCommand/WinLocation.xaml
  37. 33 0
      MBI/ToolCommand/WinLocation.xaml.cs
  38. 5 0
      MBI/ToolCommand/packages.config

+ 63 - 0
.gitattributes

@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs     diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following 
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln       merge=binary
+#*.csproj    merge=binary
+#*.vbproj    merge=binary
+#*.vcxproj   merge=binary
+#*.vcproj    merge=binary
+#*.dbproj    merge=binary
+#*.fsproj    merge=binary
+#*.lsproj    merge=binary
+#*.wixproj   merge=binary
+#*.modelproj merge=binary
+#*.sqlproj   merge=binary
+#*.wwaproj   merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg   binary
+#*.png   binary
+#*.gif   binary
+
+###############################################################################
+# diff behavior for common document formats
+# 
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the 
+# entries below.
+###############################################################################
+#*.doc   diff=astextplain
+#*.DOC   diff=astextplain
+#*.docx  diff=astextplain
+#*.DOCX  diff=astextplain
+#*.dot   diff=astextplain
+#*.DOT   diff=astextplain
+#*.pdf   diff=astextplain
+#*.PDF   diff=astextplain
+#*.rtf   diff=astextplain
+#*.RTF   diff=astextplain

+ 1 - 0
MBI/.gitignore

@@ -0,0 +1 @@
+TestCommand

+ 2 - 0
MBI/MBIResource/Config/HttpSetting.ini

@@ -13,3 +13,5 @@ FileAddress = http://service.sagacloud.cn:28888
 H5Address = http://mbi.sagacloud.cn:8889/#
 Html5DetailLocalHost = http://mbi.sagacloud.cn:8889/#/
 Html5ImageLocalHost = http://mbi.sagacloud.cn:8890/
+ProxyHost=218.60.8.98
+ProxyPort=3129

BIN
MBI/MBIResource/Family/坐标箭头.rfa


+ 13 - 37
MBI/Menu/MBITool.xml

@@ -4,7 +4,7 @@
     <AppIndex>1</AppIndex>
     <AppName>SAGA</AppName>
   </App>
-  <Tab TabName="工具">
+  <Tab TabName="MBI工具">
     <MenuTab>MBITool_W</MenuTab>
     <Modules>MBITool</Modules>
   </Tab>
@@ -111,20 +111,8 @@
   </Panel>
   <Panel PanelName="工具" GroupFlag="True" GroupImage="" RevitVer="R14,R15,R16,R17"  ButtonStyles="Large">
     <Button ButtonStyles="Stacked">
-      <ButtonName>SAGA.MBI.CopyLocalIdCommand</ButtonName>
-      <ButtonText>复制设备编号的值</ButtonText>
-      <ImageName>1、打开楼层模型</ImageName>
-      <DllName>..\OutputDll\SAGA.MBI.exe</DllName>
-      <ClassName>SAGA.MBI.CopyLocalIdCommand</ClassName>
-      <ToolTip>将设备编号的值复制到设备本地编码中。</ToolTip>
-      <LongDescription>将设备编号的值复制到设备本地编码中,结果将列出本层复制失败的对象的id,如果本层都复制成功则没有提示。</LongDescription>
-      <ToolTipImage></ToolTipImage>
-      <MenuTab>MBITool_W</MenuTab>
-      <Modules>MBITool</Modules>
-    </Button>
-    <Button ButtonStyles="Stacked">
       <ButtonName>SAGA.MBI.DeleteZeroSpaceCommand</ButtonName>
-      <ButtonText>删除本层Zero空间</ButtonText>
+      <ButtonText>删除Zero空间</ButtonText>
       <ImageName>1、打开楼层模型</ImageName>
       <DllName>..\OutputDll\SAGA.MBI.exe</DllName>
       <ClassName>SAGA.MBI.DeleteZeroSpaceCommand</ClassName>
@@ -136,26 +124,25 @@
     </Button>
 
     <Button ButtonStyles="Stacked">
-      <ButtonName>SAGA.MBI.ExportCategoriesCommand</ButtonName>
-      <ButtonText>导出所有的设备类别</ButtonText>
+      <ButtonName>SAGA.MBI.ReportEquipInSpaceCommand</ButtonName>
+      <ButtonText>查询设备所在的空间</ButtonText>
       <ImageName>1、打开楼层模型</ImageName>
       <DllName>..\OutputDll\SAGA.MBI.exe</DllName>
-      <ClassName>SAGA.MBI.ExportCategoriesCommand</ClassName>
-      <ToolTip>更新设备所在楼层关系。</ToolTip>
-      <LongDescription>更新设备所在楼层关系。</LongDescription>
+      <ClassName>SAGA.MBI.ReportEquipInSpaceCommand</ClassName>
+      <ToolTip>查询设备所在的空间</ToolTip>
+      <LongDescription>查询设备所在的空间</LongDescription>
       <ToolTipImage></ToolTipImage>
       <MenuTab>MBITool_W</MenuTab>
       <Modules>MBITool</Modules>
     </Button>
-
     <Button ButtonStyles="Stacked">
-      <ButtonName>SAGA.MBI.ReportEquipInSpaceCommand</ButtonName>
-      <ButtonText>查询设备所在的空间</ButtonText>
+      <ButtonName>SAGA.MBI.CopyLocalIdCommand</ButtonName>
+      <ButtonText>复制设备编号的值</ButtonText>
       <ImageName>1、打开楼层模型</ImageName>
       <DllName>..\OutputDll\SAGA.MBI.exe</DllName>
-      <ClassName>SAGA.MBI.ReportEquipInSpaceCommand</ClassName>
-      <ToolTip>查询设备所在的空间</ToolTip>
-      <LongDescription>查询设备所在的空间</LongDescription>
+      <ClassName>SAGA.MBI.CopyLocalIdCommand</ClassName>
+      <ToolTip>将设备编号的值复制到设备本地编码中。</ToolTip>
+      <LongDescription>将设备编号的值复制到设备本地编码中,结果将列出本层复制失败的对象的id,如果本层都复制成功则没有提示。</LongDescription>
       <ToolTipImage></ToolTipImage>
       <MenuTab>MBITool_W</MenuTab>
       <Modules>MBITool</Modules>
@@ -172,6 +159,7 @@
       <MenuTab>MBITool_W</MenuTab>
       <Modules>MBITool</Modules>
     </Button>
+
     <Button ButtonStyles="Stacked">
       <ButtonName>SAGA.MBI.VerticalPipeAlginCommand</ButtonName>
       <ButtonText>立管对齐</ButtonText>
@@ -184,18 +172,6 @@
       <MenuTab>MBITool_W</MenuTab>
       <Modules>MBITool</Modules>
     </Button>
-    <Button ButtonStyles="Stacked">
-      <ButtonName>SAGA.MBI.VerticalPipeIsolationCommand</ButtonName>
-      <ButtonText>框选立管</ButtonText>
-      <ImageName>1、打开楼层模型</ImageName>
-      <DllName>..\OutputDll\SAGA.MBI.exe</DllName>
-      <ClassName>SAGA.MBI.VerticalPipeIsolationCommand</ClassName>
-      <ToolTip>框选立管</ToolTip>
-      <LongDescription>框选立管</LongDescription>
-      <ToolTipImage></ToolTipImage>
-      <MenuTab>MBITool_W</MenuTab>
-      <Modules>MBITool</Modules>
-    </Button>
   </Panel>
  <Panel PanelName="功能扩展" GroupFlag="True" GroupImage="" RevitVer="R14,R15,R16,R17"  ButtonStyles="Large">   
     <Button ButtonStyles="Large">

+ 53 - 0
MBI/Menu/Tool.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Menus>
+  <App>
+    <AppIndex>2</AppIndex>
+    <AppName>SAGA</AppName>
+  </App>
+  <Tab TabName="工具">
+    <MenuTab>Tool_W</MenuTab>
+    <Modules>Tool</Modules>
+  </Tab>
+  <Panel PanelName="工具" GroupFlag="True" GroupImage="" RevitVer="R14,R15,R16,R17"  ButtonStyles="Large">
+
+    <Button ButtonStyles="Stacked">
+      <ButtonName>ToolCommand.DeleteZeroSpaceCommand</ButtonName>
+      <ButtonText>删除本层Zero空间</ButtonText>
+      <ImageName>1、打开楼层模型</ImageName>
+      <DllName>..\OutputDll\ToolCommand.dll</DllName>
+      <ClassName>ToolCommand.DeleteZeroSpaceCommand</ClassName>
+      <ToolTip>删除本层Zero空间。</ToolTip>
+      <LongDescription>删除本层Zero空间。</LongDescription>
+      <ToolTipImage></ToolTipImage>
+      <MenuTab>Tool_W</MenuTab>
+      <Modules>Tool</Modules>
+    </Button>
+    <Button ButtonStyles="Stacked">
+      <ButtonName>ToolCommand.ExportCategoriesCommand</ButtonName>
+      <ButtonText>导出所有的设备类别</ButtonText>
+      <ImageName>1、打开楼层模型</ImageName>
+      <DllName>..\OutputDll\ToolCommand.dll</DllName>
+      <ClassName>ToolCommand.ExportCategoriesCommand</ClassName>
+      <ToolTip>更新设备所在楼层关系。</ToolTip>
+      <LongDescription>更新设备所在楼层关系。</LongDescription>
+      <ToolTipImage></ToolTipImage>
+      <MenuTab>Tool_W</MenuTab>
+      <Modules>Tool</Modules>
+    </Button>
+
+    <Button ButtonStyles="Stacked">
+      <ButtonName>ToolCommand.FocusLocationCommand</ButtonName>
+      <ButtonText>浏览坐标</ButtonText>
+      <ImageName>1、打开楼层模型</ImageName>
+      <DllName>..\OutputDll\ToolCommand.dll</DllName>
+      <ClassName>ToolCommand.FocusLocationCommand</ClassName>
+      <ToolTip>浏览坐标</ToolTip>
+      <LongDescription>浏览坐标</LongDescription>
+      <ToolTipImage></ToolTipImage>
+      <MenuTab>Tool_W</MenuTab>
+      <Modules>Tool</Modules>
+    </Button>
+  </Panel>
+</Menus>
+<!--名称里面换行-->
+<!-- <ButtonText>扫楼App&#x000A;用户管理</ButtonText>-->

+ 29 - 0
MBI/SAGA.DotNetUtils/Geometry/Extends.cs

@@ -0,0 +1,29 @@
+/////////////////////////////////////////////
+//Copyright (c) 2011, 北京探索者软件公司
+//All rights reserved.       
+//文件名称: 
+//文件描述: 
+//创 建 者: mjy
+//创建日期: 2011-11-02
+//版 本 号:4.0.0.0  
+/////////////////////////////////////////////
+
+using System.Drawing;
+
+namespace SAGA.DotNetUtils.Geometry
+{
+    public static class Extends
+    {
+        public static Geometry2D.PointD ToPointD(this PointF p)
+        {
+            return new Geometry2D.PointD(p.X, p.Y);
+        }
+
+        public static PointF ToPointF(this Geometry2D.PointD p)
+        {
+            return new PointF((float)p.X, (float)p.Y);
+        }
+
+
+    }
+}

Файловите разлики са ограничени, защото са твърде много
+ 1681 - 0
MBI/SAGA.DotNetUtils/Geometry/Geometry2d.cs


+ 89 - 0
MBI/SAGA.DotNetUtils/Geometry/HTwoPointRelation.cs

@@ -0,0 +1,89 @@
+/////////////////////////////////////////////
+//Copyright (c) 2011, 北京探索者软件公司
+//All rights reserved.       
+//文件名称: 
+//文件描述: 
+//创 建 者: mjy
+//创建日期: 2011-11-02
+//版 本 号:4.0.0.0  
+/////////////////////////////////////////////
+
+using System;
+using System.Drawing;
+
+namespace SAGA.DotNetUtils.Geometry
+{
+    public class HTwoPointRelation
+    {
+        private PointF fix;
+        private PointF other;
+        public HTwoPointRelation(PointF fix, PointF other)
+        {
+            this.fix = fix;
+            this.other = other;
+        }
+
+        public PointF Fix { get { return fix; } }
+        public PointF Other { get { return other; } }
+        public double Distance
+        {
+            get
+            {
+                return Geometry2D.Dist(fix.ToPointD(), other.ToPointD());
+            }
+        }
+
+        public RelationOptions RelationGraphics
+        {
+            get
+            {
+                if (fix == other)
+                    return RelationOptions.Override;
+                if (other.X > fix.X)
+                {
+                    return RelationOptions.Right;
+                }
+                else
+                {
+                    return RelationOptions.Left;
+                }
+            }
+        }
+
+        public RelationOptions RelationCAD
+        {
+            get
+            {
+                if (fix == other)
+                    return RelationOptions.Override;
+                if (other.X > fix.X)
+                {
+                    return RelationOptions.Right;
+                }
+                else
+                {
+                    return RelationOptions.Left;
+                }
+            }
+        }
+
+        public PointF HOther
+        {
+            get
+            {               
+                return new PointF(other.X, fix.Y);
+            }
+        }
+
+        public double HDistance
+        {
+            get
+            {
+                double d = Math.Abs(other.X - fix.X);
+                if (d < 0.000001d)
+                    return 0d;
+                return d;
+            }
+        }
+    }
+}

+ 413 - 0
MBI/SAGA.DotNetUtils/Geometry/OffsetPolyLine.cs

@@ -0,0 +1,413 @@
+/////////////////////////////////////////////
+//Copyright (c) 2011, 北京探索者软件公司
+//All rights reserved.       
+//文件名称: 
+//文件描述: 
+//创 建 者: mjy
+//创建日期: 2011-11-02
+//版 本 号:4.0.0.0  
+/////////////////////////////////////////////
+
+using System;
+using System.Collections.Generic;
+
+namespace SAGA.DotNetUtils.Geometry
+{
+    public static class OffsetPolyLine
+    {
+        public static Geometry2D.PointD[] Offset(Geometry2D.PointD[] ps, double dOffset, int nRotType)
+        {
+            int nData = ps.Length;
+            double[,] polyLine = new double[nData, 2];
+            for (int i = 0; i < ps.Length; i++)
+            {
+                polyLine[i, 0] = ps[i].X;
+                polyLine[i, 1] = ps[i].Y;
+            }
+            bool result = Offset(dOffset, nData, polyLine, nRotType);
+            if (!result) return null;
+            List<Geometry2D.PointD> listPoints = new List<Geometry2D.PointD>();
+            for (int i = 0; i < polyLine.GetLength(0); i++)
+            {
+                Geometry2D.PointD p = new Geometry2D.PointD();
+                p.X = polyLine[i, 0];
+                p.Y = polyLine[i, 1];
+                listPoints.Add(p);
+            }
+            return listPoints.ToArray();
+        }
+
+        private static bool Offset(double dOffset, int nData, double[,] polyLine, int nRotType)
+        {
+            List<double> raOffset = new List<double>(nData);
+            for (int i = 0; i < nData; i++)
+                raOffset.Add(dOffset);
+            if (nData < 3) return false;
+            double[,] polyLine_Org = new double[nData, 2];
+            for (int i = 0; i < nData; i++)
+            {
+                for (int j = 0; j < 2; j++)
+                    polyLine_Org[i, j] = polyLine[i, j];
+            }
+            if (nRotType <= 0)
+            {
+                nRotType = mathGetRotType(nData, polyLine) ? 1 : 2;
+            }
+            double[] vector = new double[2];
+            double[] cross = new double[2];
+            double[] vectorOuter = new double[2];
+            double[,] line1 = new double[2, 2];
+            double[,] line2 = new double[2, 2];
+            double dL_line1, dL_line2;
+            int nStrID, nEndID;
+            nStrID = nData - 1;
+            nEndID = 0;
+            vector[0] = polyLine_Org[nEndID, 0] - polyLine_Org[nStrID, 0];
+            vector[1] = polyLine_Org[nEndID, 1] - polyLine_Org[nStrID, 1];
+            mathNormalize(vector[0], vector[1], ref vector[0], ref vector[1]);
+            if (nRotType == 1)
+            {
+                vectorOuter[0] = vector[1];
+                vectorOuter[1] = -1.0*vector[0];
+            }
+            else
+            {
+                vectorOuter[0] = -1.0*vector[1];
+                vectorOuter[1] = vector[0];
+            }
+            line1[0, 0] = polyLine_Org[nStrID, 0] + raOffset[nStrID]*vectorOuter[0];
+            line1[0, 1] = polyLine_Org[nStrID, 1] + raOffset[nStrID]*vectorOuter[1];
+            line1[1, 0] = polyLine_Org[nEndID, 0] + raOffset[nStrID]*vectorOuter[0];
+            line1[1, 1] = polyLine_Org[nEndID, 1] + raOffset[nStrID]*vectorOuter[1];
+            dL_line1 = mathLength(line1[0, 0], line1[0, 1], line1[1, 0], line1[1, 1]);
+            for (int i = 0; i < nData; i++)
+            {
+                if (i < nData - 1)
+                {
+                    nStrID = i;
+                    nEndID = i + 1;
+                }
+                else
+                {
+                    nStrID = i;
+                    nEndID = 0;
+                }
+                vector[0] = polyLine_Org[nEndID, 0] - polyLine_Org[nStrID, 0];
+                vector[1] = polyLine_Org[nEndID, 1] - polyLine_Org[nStrID, 1];
+                mathNormalize(vector[0], vector[1], ref vector[0], ref vector[1]);
+                if (nRotType == 1)
+                {
+                    vectorOuter[0] = vector[1];
+                    vectorOuter[1] = -1.0*vector[0];
+                }
+                else
+                {
+                    vectorOuter[0] = -1.0*vector[1];
+                    vectorOuter[1] = vector[0];
+                }
+                line2[0, 0] = polyLine_Org[nStrID, 0] + raOffset[nStrID]*vectorOuter[0];
+                line2[0, 1] = polyLine_Org[nStrID, 1] + raOffset[nStrID]*vectorOuter[1];
+                line2[1, 0] = polyLine_Org[nEndID, 0] + raOffset[nStrID]*vectorOuter[0];
+                line2[1, 1] = polyLine_Org[nEndID, 1] + raOffset[nStrID]*vectorOuter[1];
+                dL_line2 = mathLength(line2[0, 0], line2[0, 1], line2[1, 0], line2[1, 1]);
+                if (mathLength(line1[1, 0], line1[1, 1], line2[0, 0], line2[0, 1])
+                    <= m_NormalZero*(dL_line1 + dL_line2))
+                {
+                    polyLine[i, 0] = line2[0, 0];
+                    polyLine[i, 1] = line2[0, 1];
+                }
+                else
+                {
+                    if (mathLineLineCross2D(line1, line2, cross) == 0)
+                    {
+                        return false;
+                    }
+                    else
+                    {
+                        polyLine[i, 0] = cross[0];
+                        polyLine[i, 1] = cross[1];
+                    }
+                }
+                line1[0, 0] = line2[0, 0];
+                line1[0, 1] = line2[0, 1];
+                line1[1, 0] = line2[1, 0];
+                line1[1, 1] = line2[1, 1];
+                dL_line1 = dL_line2;
+            }
+            return true;
+        }
+
+        private static bool mathGetRotType(int nData, double[,] polyLine)
+        {
+            int nRotType = 1;
+            int iBegin = 0;
+            for (int i = 0; i < nData; i++)
+            {
+                if (polyLine[i, 0] < polyLine[iBegin, 0] + m_NormalZero)
+                {
+                    iBegin = i;
+                }
+            }
+            double dblX1 = polyLine[iBegin + 0, 0];
+            double dblY1 = polyLine[iBegin + 0, 1];
+            double dblX2 = polyLine[0, 0];
+            double dblY2 = polyLine[0, 1];
+            if (iBegin < nData - 1)
+            {
+                dblX2 = polyLine[iBegin + 1, 0];
+                dblY2 = polyLine[iBegin + 1, 1];
+            }
+            double[] vector = new double[2];
+            vector[0] = dblX2 - dblX1;
+            vector[1] = dblY2 - dblY1;
+            mathNormalize(vector[0], vector[1], ref vector[0], ref vector[1]);
+            double[] vectorLeft = new double[2];
+            vectorLeft[0] = -1.0*vector[1];
+            vectorLeft[1] = vector[0];
+            double dDeltaLength = 10.0* /*m_NormalZero*/0.000001*mathLength(dblX2 - dblX1, dblY2 - dblY1);
+            double[] dPoint = new double[2];
+            dPoint[0] = (dblX2 + dblX1)/2.0 + dDeltaLength*vectorLeft[0];
+            dPoint[1] = (dblY2 + dblY1)/2.0 + dDeltaLength*vectorLeft[1];
+            bool bInside = mathIsInsidePoint2D(dPoint, nData, polyLine, true);
+            if (bInside)
+                nRotType = 1;
+            else
+                nRotType = 2;
+            return nRotType == 1 ? true : false;
+        }
+
+        public static bool mathIsInsidePoint2D(double[] p1, int nData, double[,] polyLine, bool bIncludeOutLine = true)
+        {
+            int count = 0;
+            int ic = 0;
+            double[] p2 = new double[2];
+            p2[0] = p1[1] + 10e10;
+            p2[1] = p1[1];
+            int i;
+            for (i = 0; i < nData; i++)
+            {
+                if (p2[0] < polyLine[i, 0]) p2[0] = polyLine[i, 0] + 100;
+            }
+            double[] polyLineSub1 = new double[2];
+            double[] polyLineSub2 = new double[2];
+            for (i = 0; i < nData - 1; i++)
+            {
+                //ic = mathIntersect_ccw2D(p1, p2, polyLine[i], polyLine[i + 1]);
+                polyLineSub1[0] = polyLine[i, 0];
+                polyLineSub1[1] = polyLine[i, 0];
+                polyLineSub2[0] = polyLine[i + 1, 0];
+                polyLineSub2[1] = polyLine[i + 1, 0];
+                ic = mathIntersect_ccw2D(p1, p2, polyLineSub1, polyLineSub2);
+                if (ic > 0)
+                    count++;
+                else if (ic == 0)
+                {
+                    //if (mathIsPointOfLine2D(polyLine[i], polyLine[i + 1], p1))
+                    if (mathIsPointOfLine2D(polyLineSub1, polyLineSub2, p1))
+                        return bIncludeOutLine;
+                    if (p1[1] == Math.Min(polyLine[i, 1], polyLine[i + 1, 1]) && polyLine[i, 1] != polyLine[i + 1, 1])
+                        count++;
+                }
+            }
+            polyLineSub1[0] = polyLine[nData - 1, 0];
+            polyLineSub1[1] = polyLine[nData - 1, 0];
+            polyLineSub2[0] = polyLine[0, 0];
+            polyLineSub2[1] = polyLine[0, 0];
+            //ic = mathIntersect_ccw2D(p1, p2, polyLine[nData - 1], polyLine[0]);
+            ic = mathIntersect_ccw2D(p1, p2, polyLineSub1, polyLineSub2);
+            if (ic > 0)
+                count++;
+            else if (ic == 0)
+            {
+                //if (mathIsPointOfLine2D(polyLine[nData - 1], polyLine[0], p1))
+                if (mathIsPointOfLine2D(polyLineSub1, polyLineSub2, p1))
+                    return bIncludeOutLine;
+                if (p1[1] == Math.Min(polyLine[nData - 1, 1], polyLine[0, 1]) &&
+                    polyLine[nData - 1, 1] != polyLine[0, 1])
+                    count++;
+            }
+            return (count%2) == 1;
+        }
+
+        private static bool mathIsPointOfLine2D(double[] bound1, double[] bound2, double[] targetPt,
+            bool isOnLine = true)
+        {
+            double dNormalZero = m_NormalZero*10000.0;
+            return mathIsPointOfLine2D(bound1, bound2, targetPt, isOnLine, dNormalZero);
+        }
+
+        private static bool mathIsPointOfLine2D(double[] bound1, double[] bound2, double[] targetPt, bool isOnLine,
+            double dUserTol)
+        {
+            double dNormalZero = dUserTol;
+            double dTol = Math.Max(mathLength(bound1[0] - bound2[0], bound1[1] - bound2[1]), m_NormalZero);
+            if (Math.Abs(targetPt[0] - bound1[0]) < dNormalZero*dTol &&
+                Math.Abs(targetPt[1] - bound1[1]) < dNormalZero*dTol)
+                return isOnLine;
+            if (Math.Abs(targetPt[0] - bound2[0]) < dNormalZero*dTol &&
+                Math.Abs(targetPt[1] - bound2[1]) < dNormalZero*dTol)
+                return isOnLine;
+            double[] vector1 = new double[2];
+            vector1[0] = bound1[0] - targetPt[0];
+            vector1[1] = bound1[1] - targetPt[1];
+            mathNormalize2D(vector1, vector1);
+            double[] vector2 = new double[2];
+            vector2[0] = bound2[0] - targetPt[0];
+            vector2[1] = bound2[1] - targetPt[1];
+            mathNormalize2D(vector2, vector2);
+            if (Math.Abs(mathCross2D(vector1, vector2)) < dNormalZero*dTol &&
+                !(Math.Abs(vector1[0] - vector2[0]) < dNormalZero*dTol &&
+                  Math.Abs(vector1[1] - vector2[1]) < dNormalZero*dTol))
+                return true;
+            return false;
+        }
+
+        private static int mathIntersect_ccw2D(double[] p1Org, double[] p2Org, double[] p3Org, double[] p4Org)
+        {
+            double[] p1 = new double[2];
+            double[] p2 = new double[2];
+            double[] p3 = new double[2];
+            double[] p4 = new double[2];
+            for (int i = 0; i < 2; i++)
+            {
+                p1[i] = p1Org[i];
+                p2[i] = p2Org[i];
+                p3[i] = p3Org[i];
+                p4[i] = p4Org[i];
+            }
+            if (p1[0] > p2[0])
+            {
+                mathSwap2D(p1, p2);
+            }
+            if (p3[0] > p4[0])
+            {
+                mathSwap2D(p3, p4);
+            }
+            if (p1[1] > p2[1])
+            {
+                mathSwap2D(p1, p2);
+            }
+            if (p3[1] > p4[1])
+            {
+                mathSwap2D(p3, p4);
+            }
+            int r123 = math_ccw(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]);
+            int r124 = math_ccw(p1[0], p1[1], p2[0], p2[1], p4[0], p4[1]);
+            int r341 = math_ccw(p3[0], p3[1], p4[0], p4[1], p1[0], p1[1]);
+            int r342 = math_ccw(p3[0], p3[1], p4[0], p4[1], p2[0], p2[1]);
+            if (r123*r124 < 0 && r341*r342 < 0)
+                return 1;
+            if (r123 == 0 && r124 == 0)
+            {
+                if (!(p3[0] > p2[0] || p1[0] > p4[0]) && !(p3[1] > p2[1] || p1[1] > p4[1]))
+                    // JSOH (2008.8.29) y绵俊 措茄 厚背侥 眠啊
+                    return 0;
+                else
+                    return -1;
+            }
+            if (r123 == 0)
+            {
+                if (p1[0] <= p3[0] && p3[0] <= p2[0] && p1[1] <= p3[1] && p3[1] <= p2[1]) return 0;
+                else return -1;
+            }
+            if (r124 == 0)
+            {
+                if (p1[0] <= p4[0] && p4[0] <= p2[0] && p1[1] <= p4[1] && p4[1] <= p2[1]) return 0;
+                else return -1;
+            }
+            if (r341 == 0)
+            {
+                if (p3[0] <= p1[0] && p1[0] <= p4[0] && p3[1] <= p1[1] && p1[1] <= p4[1]) return 0;
+                else return -1;
+            }
+            if (r342 == 0)
+            {
+                if (p3[0] <= p2[0] && p2[0] <= p4[0] && p3[1] <= p2[1] && p2[1] <= p4[1]) return 0;
+                else return -1;
+            }
+            return -1;
+        }
+
+        private static void mathSwap2D(double[] p1, double[] p2)
+        {
+            double tx = p1[0];
+            double ty = p1[1];
+            p1[0] = p2[0];
+            p1[1] = p2[1];
+            p2[0] = tx;
+            p2[1] = ty;
+        }
+
+        private static int math_ccw(double ax, double ay, double bx, double by, double cx, double cy)
+        {
+            double l = bx*cy - ay*bx - ax*cy - by*cx + ax*by + ay*cx;
+            if (Math.Abs(l) < 1.0e-10) return 0;
+            else if (l > 0.0) return 1;
+            else return -1;
+        }
+
+        private static double mathLength(double dx, double dy, double dz = 0)
+        {
+            return Math.Sqrt(dx*dx + dy*dy + dz*dz);
+        }
+
+        private static double mathLength(double dxi, double dyi, double dxj, double dyj)
+        {
+            double dblLength = (dxi - dxj)*(dxi - dxj) + (dyi - dyj)*(dyi - dyj);
+            if (dblLength < 0)
+                dblLength = 0;
+            return Math.Sqrt(dblLength);
+        }
+
+        private static readonly double m_NormalZero = 0.0000000000001;
+
+        private static double mathLineLineCross2D(double[,] line1, double[,] line2, double[] cross)
+        {
+            double[] vector1 = new double[2];
+            vector1[0] = line1[0, 0] - line1[1, 0];
+            vector1[1] = line1[0, 1] - line1[1, 1];
+            mathNormalize2D(vector1, vector1);
+            double[] vector2 = new double[2];
+            vector2[0] = line2[0, 0] - line2[1, 0];
+            vector2[1] = line2[0, 1] - line2[1, 1];
+            mathNormalize2D(vector2, vector2);
+            double product = mathCross2D(vector1, vector2);
+            //if (fabs(product) < m_NormalZero*100000)  
+            if (Math.Abs(product) < m_NormalZero*100000)
+            {
+                cross[0] = 0.0;
+                cross[1] = 0.0;
+                return 0;
+            }
+            double[] vector3 = new double[2];
+            vector3[0] = line1[0, 0] - line2[0, 0];
+            vector3[1] = line1[0, 1] - line2[0, 1];
+            double H = mathCross2D(vector2, vector3);
+            cross[0] = line1[0, 0] + vector1[0]*(H/product);
+            cross[1] = line1[0, 1] + vector1[1]*(H/product);
+            return 1;
+        }
+
+        private static double mathCross2D(double[] vector1, double[] vector2)
+        {
+            return vector1[0]*vector2[1] - vector1[1]*vector2[0];
+        }
+
+        private static bool mathNormalize2D(double[] vector, double[] vectorn)
+        {
+            return mathNormalize(vector[0], vector[1], ref vectorn[0], ref vectorn[1]);
+        }
+
+        private static bool mathNormalize(double dx, double dy, ref double dxn, ref double dyn)
+        {
+            dxn = 0;
+            dyn = 0;
+            double Length = mathLength(dx, dy);
+            if (Length < m_NormalZero)
+                return false;
+            dxn = dx/Length;
+            dyn = dy/Length;
+            return true;
+        }
+    }
+}

+ 76 - 0
MBI/SAGA.DotNetUtils/Geometry/RelationOptions.cs

@@ -0,0 +1,76 @@
+/////////////////////////////////////////////
+//Copyright (c) 2011, 北京探索者软件公司
+//All rights reserved.       
+//文件名称: 
+//文件描述: 
+//创 建 者: mjy
+//创建日期: 2011-11-02
+//版 本 号:4.0.0.0  
+/////////////////////////////////////////////
+
+namespace SAGA.DotNetUtils.Geometry
+{
+    public enum RelationOptions
+    {
+        RightUp = 1,
+        RightDown,
+        LeftUp,
+        LeftDown,
+        Left,
+        Right,
+        Up,
+        Down,
+        Override
+    }
+
+    public class RelationOptionDirection
+    {
+        public static bool IsSameDirectionH(RelationOptions a, RelationOptions b)
+        {
+            switch (a)
+            {
+                case RelationOptions.LeftUp:
+                case RelationOptions.LeftDown:
+                case RelationOptions.Left:
+                    if (b == RelationOptions.LeftDown ||
+                        b == RelationOptions.LeftUp ||
+                        b == RelationOptions.Left)
+                        return true;
+                    break;
+                case RelationOptions.RightUp:
+                case RelationOptions.RightDown:
+                case RelationOptions.Right:
+                    if (b == RelationOptions.RightUp ||
+                        b == RelationOptions.RightDown ||
+                        b == RelationOptions.Right)
+                        return true;
+                    break;
+            }
+            return false;
+        }
+
+        public static bool IsSameDirectionV(RelationOptions a, RelationOptions b)
+        {
+            switch (a)
+            {
+                case RelationOptions.LeftUp:
+                case RelationOptions.RightUp:
+                case RelationOptions.Up:
+                    if (b == RelationOptions.LeftUp ||
+                        b == RelationOptions.RightUp ||
+                        b == RelationOptions.Up)
+                        return true;
+                    break;
+                case RelationOptions.RightDown:
+                case RelationOptions.LeftDown:
+                case RelationOptions.Down:
+                    if (b == RelationOptions.RightDown ||
+                        b == RelationOptions.LeftDown ||
+                        b == RelationOptions.Down)
+                        return true;
+                    break;
+            }
+            return false;
+        }
+    }
+}

+ 592 - 0
MBI/SAGA.DotNetUtils/Geometry/TszGeoUtil.cs

@@ -0,0 +1,592 @@
+using System;
+using System.Collections.Generic;
+using SAGA.DotNetUtils.Extend;
+
+namespace SAGA.DotNetUtils.Geometry
+{
+    public static class TszGeoUtil
+    {
+        /// <summary>
+        /// 转字符串
+        /// </summary>
+        /// <param name="xyz"></param>
+        /// <returns></returns>
+        public static string XYZToString(TszXYZ xyz)
+        {
+            return xyz.x + "," + xyz.y + "," + xyz.z;
+        }
+
+        /// <summary>
+        /// 转换成点
+        /// </summary>
+        /// <param name="strPtStr"></param>
+        /// <returns></returns>
+        public static TszXYZ StringToXYZ(string strPtStr)
+        {
+            strPtStr = strPtStr.TrimStart('(');
+            strPtStr = strPtStr.TrimEnd(')');
+            strPtStr = strPtStr.TrimStart('[');
+            strPtStr = strPtStr.TrimEnd(']');
+            string[] strTemps = strPtStr.Split(',');
+            return new TszXYZ(double.Parse(strTemps[0]), double.Parse(strTemps[1]), double.Parse(strTemps[2]));
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="strPtStr"></param>
+        /// <param name="dZ"></param>
+        /// <returns></returns>
+        public static TszXYZ StringToXYZ(string strPtStr, double dZ)
+        {
+            strPtStr = strPtStr.TrimStart('(');
+            strPtStr = strPtStr.TrimEnd(')');
+            strPtStr = strPtStr.TrimStart('[');
+            strPtStr = strPtStr.TrimEnd(']');
+            string[] strTemps = strPtStr.Split(',');
+            return new TszXYZ(double.Parse(strTemps[0]), double.Parse(strTemps[1]), dZ);
+        }
+
+        /// <summary>
+        /// Checks if the two double values are equal taking into consideration the equality value.
+        /// </summary>
+        /// <param name="val1">First double value needed.</param>
+        /// <param name="val2">Second double value needed.</param>
+        /// <param name="eq">A double value representing the equality(for example 0.00001)</param>
+        /// <returns>True if the two passed values are equal.</returns>
+        public static bool AreEqual(double val1, double val2, double eq)
+        {
+            return (Math.Abs((double)(val1 - val2)) < eq);
+        }
+
+        /// <summary>
+        /// Transform old coordinate system in the new coordinate system 
+        /// </summary>
+        /// <param name="point">the TszXYZ which need to be transformed</param>
+        /// <param name="transform">the value of the coordinate system to be transformed</param>
+        /// <returns>the new TszXYZ which has been transformed</returns>
+        public static TszXYZ TransformPoint(TszXYZ point, TszTransform transform)
+        {
+            //get the coordinate value in X, Y, Z axis
+            double x = point.x;
+            double y = point.y;
+            double z = point.z;
+            //transform basis of the old coordinate system in the new coordinate system
+            TszXYZ b0 = transform.get_Basis(0);
+            TszXYZ b1 = transform.get_Basis(1);
+            TszXYZ b2 = transform.get_Basis(2);
+            TszXYZ origin = transform.Origin;
+            //transform the origin of the old coordinate system in the new coordinate system
+            double xTemp = x * b0.x + y * b1.x + z * b2.x + origin.x;
+            double yTemp = x * b0.y + y * b1.y + z * b2.y + origin.y;
+            double zTemp = x * b0.z + y * b1.z + z * b2.z + origin.z;
+            return new TszXYZ(xTemp, yTemp, zTemp);
+        }
+
+        /// <summary>
+        /// Judge whether the two double data are equal
+        /// </summary>
+        /// <param name="d1">The first double data</param>
+        /// <param name="d2">The second double data</param>
+        /// <returns>true if two double data is equal, otherwise false</returns>
+        public static bool IsEqual(double d1, double d2)
+        {
+            return d1.IsEqual(d2);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="d1"></param>
+        /// <param name="d2"></param>
+        /// <param name="d3"></param>
+        /// <returns></returns>
+        public static bool IsEqual(double d1, double d2, double d3)
+        {
+            return IsEqual(d1, d2) && IsEqual(d1, d3);
+        }
+
+        /// <summary>
+        /// Judge whether the two TszXYZ point are equal
+        /// </summary>
+        /// <param name="first">The first TszXYZ point</param>
+        /// <param name="second">The second TszXYZ point</param>
+        /// <returns>true if two TszXYZ point is equal, otherwise false</returns>
+        public static bool IsEqual(TszXYZ first, TszXYZ second)
+        {
+            bool flag = true;
+            flag = flag && IsEqual(first.x, second.x);
+            flag = flag && IsEqual(first.y, second.y);
+            flag = flag && IsEqual(first.z, second.z);
+            return flag;
+        }
+
+        /// <summary>
+        /// dot product of two TszXYZ as Matrix
+        /// </summary>
+        /// <param name="p1">The first TszXYZ</param>
+        /// <param name="p2">The second TszXYZ</param>
+        /// <returns>the cosine value of the angle between vector p1 an p2</returns>
+        public static double DotMatrix(TszXYZ p1, TszXYZ p2)
+        {
+            //get the coordinate of the TszXYZ 
+            double v1 = p1.x;
+            double v2 = p1.y;
+            double v3 = p1.z;
+            double u1 = p2.x;
+            double u2 = p2.y;
+            double u3 = p2.z;
+            return v1 * u1 + v2 * u2 + v3 * u3;
+        }
+
+        /// <summary>
+        /// judge whether the two vectors have the same direction
+        /// </summary>
+        /// <param name="firstVec">the first vector</param>
+        /// <param name="secondVec">the second vector</param>
+        /// <returns>true if the two vector is in same direction, otherwise false</returns>
+        public static bool IsSameDirection(TszXYZ firstVec, TszXYZ secondVec)
+        {
+            // get the unit vector for two vectors
+            TszXYZ first = UnitVector(firstVec);
+            TszXYZ second = UnitVector(secondVec);
+            // if the dot product of two unit vectors is equal to 1, return true
+            double dot = DotMatrix(first, second);
+            return (IsEqual(dot, 1));
+        }
+
+        /// <summary>
+        /// Judge whether the two vectors have the opposite direction
+        /// </summary>
+        /// <param name="firstVec">the first vector</param>
+        /// <param name="secondVec">the second vector</param>
+        /// <returns>true if the two vector is in opposite direction, otherwise false</returns>
+        public static bool IsOppositeDirection(TszXYZ firstVec, TszXYZ secondVec)
+        {
+            // get the unit vector for two vectors
+            TszXYZ first = UnitVector(firstVec);
+            TszXYZ second = UnitVector(secondVec);
+            // if the dot product of two unit vectors is equal to -1, return true
+            double dot = DotMatrix(first, second);
+            return (IsEqual(dot, -1));
+        }
+
+        /// <summary>
+        /// multiplication cross of two TszXYZ as Matrix
+        /// </summary>
+        /// <param name="p1">The first TszXYZ</param>
+        /// <param name="p2">The second TszXYZ</param>
+        /// <returns>the normal vector of the face which first and secend vector lie on</returns>
+        public static TszXYZ CrossMatrix(TszXYZ p1, TszXYZ p2)
+        {
+            double x = p2.z * p1.y - p2.y * p1.z;
+            double y = p2.x * p1.z - p2.z * p1.x;
+            double z = p2.y * p1.x - p2.x * p1.y;
+            return new TszXYZ(x, y, z);
+        }
+
+        /// <summary>
+        /// Set the vector into unit length
+        /// </summary>
+        /// <param name="vector">the input vector</param>
+        /// <returns>the vector in unit length</returns>
+        public static TszXYZ UnitVector(TszXYZ vector)
+        {
+            // calculate the distance from grid origin to the TszXYZ
+            double length = GetLength(vector);
+            // changed the vector into the unit length
+            double x = vector.x / length;
+            double y = vector.y / length;
+            double z = vector.z / length;
+            return new TszXYZ(x, y, z);
+        }
+
+        /// <summary>
+        /// calculate the distance from grid origin to the TszXYZ(vector length)
+        /// </summary>
+        /// <param name="vector">the input vector</param>
+        /// <returns>the length of the vector</returns>
+        public static double GetLength(TszXYZ vector)
+        {
+            double x = vector.x;
+            double y = vector.y;
+            double z = vector.z;
+            return Math.Sqrt(x * x + y * y + z * z);
+        }
+
+        /// <summary>
+        /// Subtraction of two points(or vectors), get a new vector 
+        /// </summary>
+        /// <param name="p1">the first point(vector)</param>
+        /// <param name="p2">the second point(vector)</param>
+        /// <returns>return a new vector from point p2 to p1</returns>
+        public static TszXYZ SubXYZ(TszXYZ p1, TszXYZ p2)
+        {
+            double x = p1.x - p2.x;
+            double y = p1.y - p2.y;
+            double z = p1.z - p2.z;
+            return new TszXYZ(x, y, z);
+        }
+
+        /// <summary>
+        /// Add of two points(or vectors), get a new point(vector) 
+        /// </summary>
+        /// <param name="p1">the first point(vector)</param>
+        /// <param name="p2">the first point(vector)</param>
+        /// <returns>a new vector(point)</returns>
+        public static TszXYZ AddXYZ(TszXYZ p1, TszXYZ p2)
+        {
+            double x = p1.x + p2.x;
+            double y = p1.y + p2.y;
+            double z = p1.z + p2.z;
+            return new TszXYZ(x, y, z);
+        }
+
+        /// <summary>
+        /// Multiply a verctor with a number
+        /// </summary>
+        /// <param name="vector">a vector</param>
+        /// <param name="rate">the rate number</param>
+        /// <returns></returns>
+        public static TszXYZ MultiplyVector(TszXYZ vector, double rate)
+        {
+            double x = vector.x * rate;
+            double y = vector.y * rate;
+            double z = vector.z * rate;
+            return new TszXYZ(x, y, z);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="pt"></param>
+        /// <returns></returns>
+        public static double GetAngle(TszXYZ pt)
+        {
+            return Math.Atan2(pt.y, pt.x);
+        }
+
+        /// <summary>
+        /// Get the angle between two gPoints in radians.
+        /// </summary>
+        /// <param name="p1">First TszXYZ needed.</param>
+        /// <param name="p2">Second TszXYZ needed.</param>
+        /// <returns>The angle in radians between two gPoints.</returns>
+        public static double GetAngle(TszXYZ p1, TszXYZ p2)
+        {
+            if (AreEqual(p1.FindDistance2(p2), 0.0, 1E-08))
+            {
+                return 0.0;
+            }
+            return FixAngle(Math.Atan2(p2.y - p1.y, p2.x - p1.x));
+        }
+
+        /// <summary>
+        /// Fixes the passed angle in radians to be between 0.0 and 2 * PI.
+        /// </summary>
+        /// <param name="inangle">A passed angle in radians to be fixed.</param>
+        /// <returns>The fixed angle in radians.</returns>
+        public static double FixAngle(double inangle)
+        {
+            double eq = 1E-06;
+            if (AreEqual(inangle, 6.2831853071796, eq))
+            {
+                return 6.2831853071796;
+            }
+            double num2 = inangle;
+            num2 = num2 % 6.2831853071796;
+            if (num2 > (6.2831853071796 + eq))
+            {
+                num2 -= 6.2831853071796;
+            }
+            if ((num2 + eq) < 0.0)
+            {
+                num2 += 6.2831853071796;
+            }
+            if (AreEqual(num2, 0.0, eq))
+            {
+                return 0.0;
+            }
+            if (AreEqual(num2, 1.5707963267948, eq))
+            {
+                return 1.5707963267948;
+            }
+            if (AreEqual(num2, 3.1415926535898, eq))
+            {
+                return 3.1415926535898;
+            }
+            if (AreEqual(num2, 4.7123889803844, eq))
+            {
+                return 4.7123889803844;
+            }
+            if (AreEqual(num2, 6.2831853071796, eq))
+            {
+                return 6.2831853071796;
+            }
+            return num2;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="xyz"></param>
+        /// <returns></returns>
+        public static TszXYZ XYZ3DTo2D(TszXYZ xyz)
+        {
+            return new TszXYZ(xyz.x, xyz.y);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="xyz"></param>
+        /// <param name="z"></param>
+        /// <returns></returns>
+        public static TszXYZ XYZ2DTo3D(TszXYZ xyz, double z)
+        {
+            return new TszXYZ(xyz.x, xyz.y, z);
+        }
+
+        /// <summary>
+        /// Find the distance between two points
+        /// </summary>
+        /// <param name="first">the first point</param>
+        /// <param name="second">the first point</param>
+        /// <returns>the distance of two points</returns>
+        public static double FindDistance(TszXYZ first, TszXYZ second)
+        {
+            double x = first.x - second.x;
+            double y = first.y - second.y;
+            double z = first.z - second.z;
+            return Math.Sqrt(x * x + y * y + z * z);
+        }
+
+        /// <summary>
+        /// Find the distance between two points
+        /// </summary>
+        /// <param name="first">the first point</param>
+        /// <param name="second">the first point</param>
+        /// <returns>the distance of two points</returns>
+        public static double FindDistance2(TszXYZ first, TszXYZ second)
+        {
+            double x = first.x - second.x;
+            double y = first.y - second.y;
+            return Math.Sqrt(x * x + y * y);
+        }
+
+        /// <summary>
+        /// 点的平移再旋转
+        /// </summary>
+        /// <param name="pt"></param>
+        /// <param name="vecM"></param>
+        /// <param name="dAngle"></param>
+        /// <returns></returns>
+        public static TszXYZ GetXyz(TszXYZ pt,TszXYZ vecM,double dAngle)
+        {
+            TszXYZ vecMr = VectorRotate(vecM, dAngle, pt);
+            return pt + vecMr;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="ptS"></param>
+        /// <param name="ptE"></param>
+        /// <param name="dBulge"></param>
+        /// <param name="ptCenter"></param>
+        /// <param name="dRadius"></param>
+        /// <param name="dStartAngle"></param>
+        /// <param name="dEndAngle"></param>
+        public static void GetArcInfo(TszXYZ ptS, TszXYZ ptE, double dBulge,
+            out TszXYZ ptCenter, out double dRadius, out double dStartAngle, out double dEndAngle)
+        {
+            dStartAngle = 0;
+            dEndAngle = 0;
+            //半径
+            double dS = FindDistance2(ptS, ptE) / 2.0;
+            double dL = Math.Abs(dBulge) * dS;
+            dRadius = (dS * dS + dL * dL) / (dL * 2);
+            //圆心
+            TszXYZ VecArc = (ptE - ptS) / 2;
+            ptCenter = ptS + VecArc;
+            VecArc = VecArc.Normalize();
+            if (dBulge > 0)
+                VecArc = VectorRotate(VecArc, Math.PI / 2, ptCenter);
+            else
+                VecArc = VectorRotate(VecArc, -Math.PI / 2, ptCenter);
+            ptCenter = ptCenter + VecArc * (dRadius - dS * Math.Abs(dBulge));
+            //起始角
+            TszXYZ Vec = ptS - ptCenter;
+            if (dBulge < 0)
+                Vec = ptE - ptCenter;
+            dStartAngle = GetDeltaAngle(Vec);
+            //终点角
+            Vec = ptE - ptCenter;
+            if (dBulge < 0)
+                Vec = ptS - ptCenter;
+            dEndAngle = GetDeltaAngle(Vec);
+            //终点角必须大于起始角
+            if (dStartAngle > dEndAngle)
+            {
+                dEndAngle += 2 * Math.PI;
+            }
+        }
+
+        public static double GetDeltaAngle(TszXYZ vec)
+        {
+            double dRtn = 0;
+            if (vec.x == 0 || vec.y == 0)
+            {
+                if (vec.x == 0)
+                {
+                    if (vec.y > 0)
+                    {
+                        dRtn = Math.PI / 2;
+                    }
+                    else
+                    {
+                        dRtn = Math.PI / 2 + Math.PI;
+                    }
+                }
+                else
+                {
+                    if (vec.x > 0)
+                    {
+                        dRtn = 0;
+                    }
+                    else
+                    {
+                        dRtn = Math.PI;
+                    }
+                }
+            }
+            else
+            {
+                dRtn = Math.Atan(vec.y / vec.x);
+                dRtn = Math.Abs(dRtn);
+                if (vec.x > 0)
+                {
+                    if (vec.y > 0)
+                    {
+                        //1
+                        dRtn = Math.Abs(dRtn);
+                    }
+                    else
+                    {
+                        //4
+                        dRtn = (2 * Math.PI - dRtn);
+                    }
+                }
+                else
+                {
+                    if (vec.y > 0)
+                    {
+                        //2
+                        dRtn = (Math.PI - dRtn);
+                    }
+                    else
+                    {
+                        //3
+                        dRtn = (Math.PI + dRtn);
+                    }
+                }
+            }
+            return dRtn;
+        }
+
+        /// <summary>
+        /// (cosA -sinA 0 0)
+        /// (sinA cosA  0 0)
+        /// (0    0     1 0)
+        /// </summary>
+        /// <param name="vec"></param>
+        /// <param name="dAngle"></param>
+        /// <returns></returns>
+        public static TszXYZ VectorRotate(TszXYZ vec, double dAngle, TszXYZ pt)
+        {
+            TszTransform transform = new TszTransform();
+            transform.Origin = pt;
+            TszXYZ basisX = new TszXYZ(Math.Cos(dAngle), -Math.Sin(dAngle), 0);
+            TszXYZ basisY = new TszXYZ(Math.Sin(dAngle), Math.Cos(dAngle), 0);
+            TszXYZ basisZ = new TszXYZ(0, 0, 1);
+            transform.set_Basis(0, basisX);
+            transform.set_Basis(1, basisY);
+            transform.set_Basis(2, basisZ);
+            return TransformVector(vec, transform);
+        }
+
+        /// <summary>
+        /// 平移矩阵
+        /// </summary>
+        /// <param name="vec"></param>
+        /// <returns></returns>
+        public static TszTransform GetTranslation(TszXYZ vec)
+        {
+            TszTransform transform = new TszTransform();
+            transform.Origin = vec;
+            return transform;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="v"></param>
+        /// <param name="transform"></param>
+        /// <returns></returns>
+        public static TszXYZ TransformVector(TszXYZ v, TszTransform transform)
+        {
+            TszXYZ pt = TransformPoint(new TszXYZ(), transform);
+            TszXYZ ptV = TransformPoint(v, transform);
+            return SubXYZ(pt, ptV).Normalize();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="pStart"></param>
+        /// <param name="pEnd"></param>
+        /// <param name="pCenter"></param>
+        /// <param name="dWidth"></param>
+        /// <returns></returns>
+        public static List<TszXYZ> ArcElementEdges(TszXYZ pStart, TszXYZ pEnd, TszXYZ pCenter, double dWidth)
+        {
+            List<TszXYZ> listRtn = new List<TszXYZ>();
+            double dWidthHalf = dWidth / 2;
+            TszXYZ vStart = SubXYZ(pStart, pCenter);
+            TszXYZ vEnd = SubXYZ(pEnd, pCenter);
+            listRtn.Add(pStart + vStart.Normalize() * dWidthHalf);
+            listRtn.Add(pEnd + vEnd.Normalize() * dWidthHalf);
+            listRtn.Add(pStart - vStart.Normalize() * dWidthHalf);
+            listRtn.Add(pEnd - vEnd.Normalize() * dWidthHalf);
+            return listRtn;
+        }
+        
+        /// <summary>
+        /// 弧度转角度
+        /// </summary>
+        /// <param name="dRadian"></param>
+        /// <returns></returns>
+        public static double RadianToAngle(double dRadian)
+        {
+            return dRadian * 180 / Math.PI;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <returns></returns>
+        public static bool ListContainsXyz(List<TszXYZ> listPt, TszXYZ ptAdd)
+        {
+            bool blnRtn = false;
+            foreach (TszXYZ pt in listPt)
+            {
+                if (IsEqual(pt, ptAdd))
+                {
+                    blnRtn = true;
+                    break;
+                }
+            }
+            return blnRtn;
+        }
+    }
+}

+ 103 - 0
MBI/SAGA.DotNetUtils/Geometry/TszTransform.cs

@@ -0,0 +1,103 @@
+namespace SAGA.DotNetUtils.Geometry
+{
+    public class TszTransform
+    {
+        private TszXYZ m_BasisX = new TszXYZ(1, 0, 0);
+        /// <summary>
+        /// 
+        /// </summary>
+        public TszXYZ BasisX
+        {
+            get
+            {
+                return m_BasisX;
+            }
+            set
+            {
+                m_BasisX = value;
+            }
+        }
+
+        private TszXYZ m_BasisY = new TszXYZ(0, 1, 0);
+        /// <summary>
+        /// 
+        /// </summary>
+        public TszXYZ BasisY
+        {
+            get
+            {
+                return m_BasisY;
+            }
+            set
+            {
+                m_BasisY = value;
+            }
+        }
+
+        private TszXYZ m_BasisZ = new TszXYZ(0, 0, 1);
+        /// <summary>
+        /// 
+        /// </summary>
+        public TszXYZ BasisZ
+        {
+            get
+            {
+                return m_BasisZ;
+            }
+            set
+            {
+                m_BasisZ = value;
+            }
+        }
+
+        private TszXYZ m_Origin = new TszXYZ();
+        /// <summary>
+        /// 
+        /// </summary>
+        public TszXYZ Origin
+        {
+            get
+            {
+                return m_Origin;
+            }
+            set
+            {
+                m_Origin = value;
+            }
+        }
+
+        public TszXYZ get_Basis(int index)
+        {
+            TszXYZ xyzRtn = new TszXYZ();
+            switch (index)
+            {
+                case 0:
+                    xyzRtn = BasisX;
+                    break;
+                case 1:
+                    xyzRtn = BasisY;
+                    break;
+                case 2:
+                    xyzRtn = BasisZ;
+                    break;
+            }
+            return xyzRtn;
+        }
+
+        public void set_Basis(int index, TszXYZ ifcxyz)
+        {
+            switch (index)
+            {
+                case 0:
+                    BasisX = ifcxyz;
+                    break;
+                case 1:
+                    BasisY = ifcxyz;
+                    break;
+                case 2:
+                    BasisZ = ifcxyz;
+                    break;
+            }
+        }
+    }
+}

+ 907 - 0
MBI/SAGA.DotNetUtils/Geometry/TszXYZ.cs

@@ -0,0 +1,907 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using SAGA.DotNetUtils.Extend;
+
+namespace SAGA.DotNetUtils.Geometry
+{
+    public class TszXYZ
+    {
+        internal xyz mxyz;
+
+        /// <summary>
+        /// Initializes a TszXYZ object (0.0,0.0,0.0). 
+        /// </summary>
+        public TszXYZ()
+        {
+            this.x = 0.0;
+            this.y = 0.0;
+            this.z = 0.0;
+        }
+
+        public TszXYZ(double X, double Y)
+        {
+            this.x = X;
+            this.y = Y;
+            this.z = 0;
+        }
+
+        public TszXYZ(TszXYZ pt, double Z)
+        {
+            this.x = pt.x;
+            this.y = pt.y;
+            this.z = Z;
+        }
+
+        /// <summary>
+        /// Initializes a TszXYZ object (X,Y,Z).
+        /// </summary>
+        /// <param name="X">The x coordinate of the point.</param>
+        /// <param name="Y">The y coordinate of the point.</param>
+        /// <param name="Z">The z coordinate of the point.</param>
+        public TszXYZ(double X, double Y, double Z)
+        {
+            this.x = X;
+            this.y = Y;
+            this.z = Z;
+        }
+
+        /// <summary>
+        /// Initializes a TszXYZ object at the coordinates of the pt parameter.
+        /// </summary>
+        /// <param name="pt">A TszXYZ object from which the coordinjates will be taken from.</param>
+        public TszXYZ(TszXYZ pt)
+        {
+            this.x = pt.x;
+            this.y = pt.y;
+            this.z = pt.z;
+        }
+
+        /// <summary>
+        /// The x value of the point.
+        /// </summary>
+        public double x
+        {
+            get { return this.mxyz._x; }
+            set { this.mxyz._x = value; }
+        }
+
+        /// <summary>
+        /// The y value of the point.
+        /// </summary>
+        public double y
+        {
+            get { return this.mxyz._y; }
+            set { this.mxyz._y = value; }
+        }
+
+        /// <summary>
+        /// The z value of the point.
+        /// </summary>
+        public double z
+        {
+            get { return this.mxyz._z; }
+            set { this.mxyz._z = value; }
+        }
+
+        /// <summary>
+        /// X
+        /// </summary>
+        public static TszXYZ BasisX
+        {
+            get { return new TszXYZ(1, 0, 0); }
+        }
+
+        /// <summary>
+        /// Y
+        /// </summary>
+        public static TszXYZ BasisY
+        {
+            get { return new TszXYZ(0, 1, 0); }
+        }
+
+        /// <summary>
+        /// Z
+        /// </summary>
+        public static TszXYZ BasisZ
+        {
+            get { return new TszXYZ(0, 0, 1); }
+        }
+
+        /// <summary>
+        /// Get the angle between the given point and this in radians.
+        /// </summary>
+        /// <param name="pt">The other gPoint needed.</param>
+        /// <returns>The angle in radians.</returns>
+        public double GetAngle(TszXYZ pt)
+        {
+            return TszGeoUtil.GetAngle(this, pt);
+        }
+
+        /// <summary>
+        /// Implements the + operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="pt"></param>
+        /// <returns></returns>
+        public static TszXYZ operator +(TszXYZ p, TszXYZ pt)
+        {
+            TszXYZ point = new TszXYZ();
+            point.x = p.x + pt.x;
+            point.y = p.y + pt.y;
+            point.z = p.z + pt.z;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the / operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static TszXYZ operator /(TszXYZ p, double value)
+        {
+            TszXYZ point = new TszXYZ();
+            point.x = p.x/value;
+            point.y = p.y/value;
+            point.z = p.z/value;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the == operator for two gPoints.
+        /// </summary>
+        /// <param name="a"></param>
+        /// <param name="b"></param>
+        /// <returns></returns>
+        public static bool operator ==(TszXYZ a, TszXYZ b)
+        {
+            return (ReferenceEquals(a, b) || (((null != a) && (null != b)) && a.Equals(b)));
+        }
+
+        /// <summary>
+        /// Implements the != operator for two gPoints.
+        /// </summary>
+        /// <param name="obj1"></param>
+        /// <param name="obj2"></param>
+        /// <returns></returns>
+        public static bool operator !=(TszXYZ obj1, TszXYZ obj2)
+        {
+            return !(obj1 == obj2);
+        }
+
+        /// <summary>
+        /// Implements the * operator for a TszXYZ with a double value.
+        /// </summary>
+        /// <param name="value"></param>
+        /// <param name="p"></param>
+        /// <returns></returns>
+        public static TszXYZ operator *(double value, TszXYZ p)
+        {
+            TszXYZ point = new TszXYZ();
+            point.x = p.x*value;
+            point.y = p.y*value;
+            point.z = p.z*value;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the * operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static TszXYZ operator *(TszXYZ p, double value)
+        {
+            TszXYZ point = new TszXYZ();
+            point.x = p.x*value;
+            point.y = p.y*value;
+            point.z = p.z*value;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the - operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="pt"></param>
+        /// <returns></returns>
+        public static TszXYZ operator -(TszXYZ p, TszXYZ pt)
+        {
+            TszXYZ point = new TszXYZ();
+            point.x = p.x - pt.x;
+            point.y = p.y - pt.y;
+            point.z = p.z - pt.z;
+            return point;
+        }
+
+        /// <summary>
+        /// Serves as a hash function for the collection.
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            return ((this.x.GetHashCode() ^ this.y.GetHashCode()) ^ this.z.GetHashCode());
+        }
+
+        /// <summary>
+        /// Checks if the parameter object is equal to this object.
+        /// </summary>
+        /// <param name="obj">An object to be checked if it is equal with this TszXYZ object.</param>
+        /// <returns>True if the objects are equal.</returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == null)
+            {
+                return false;
+            }
+            TszXYZ p = obj as TszXYZ;
+            return this.Equals(p);
+        }
+
+        public override string ToString()
+        {
+            return string.Format("({0},{1},{2})", this.x, this.y, this.z);
+        }
+
+        /// <summary>
+        /// 相等判断
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="dTol"></param>
+        /// <returns></returns>
+        public bool Equals(TszXYZ p, double dTol = 0)
+        {
+            if (p == null)
+            {
+                return false;
+            }
+            return (((this.x.IsEqual(p.x, dTol)) && (this.y.IsEqual(p.y, dTol))) && (this.z.IsEqual(p.z, dTol)));
+        }
+
+        /// <summary>
+        /// Convert this Vector to one unit length.
+        /// </summary>
+        public TszXYZ Normalize()
+        {
+            double dX = 0;
+            double dY = 0;
+            double dZ = 0;
+            double num = Math.Sqrt(((x*x) + (y*y)) + (z*z));
+            if (TszGeoUtil.AreEqual(num, 0.0, 1E-08))
+            {
+                dX = 0.0;
+                dY = 0.0;
+                dZ = 1.0;
+            }
+            else
+            {
+                dX = x/num;
+                dY = y/num;
+                dZ = z/num;
+                if (TszGeoUtil.AreEqual(dX, 0.0, 1E-08))
+                {
+                    dX = 0.0;
+                }
+                if (TszGeoUtil.AreEqual(dX, 1.0, 1E-08))
+                {
+                    dX = 1.0;
+                }
+                if (TszGeoUtil.AreEqual(dY, 0.0, 1E-08))
+                {
+                    dY = 0.0;
+                }
+                if (TszGeoUtil.AreEqual(dY, 1.0, 1E-08))
+                {
+                    dY = 1.0;
+                }
+                if (TszGeoUtil.AreEqual(dZ, 0.0, 1E-08))
+                {
+                    dZ = 0.0;
+                }
+                if (TszGeoUtil.AreEqual(dZ, 1.0, 1E-08))
+                {
+                    dZ = 1.0;
+                }
+            }
+            return new TszXYZ(dX, dY, dZ);
+        }
+
+        /// <summary>
+        /// Changes this Vector regarding the crossing operation with another Vector.
+        /// </summary>
+        /// <param name="other">A Vector object required for the operation.</param>
+        public void Cross(TszXYZ other)
+        {
+            double num = (y*other.z) - (other.y*z);
+            double num2 = (z*other.x) - (other.z*x);
+            double num3 = (x*other.y) - (other.x*y);
+            x = num;
+            y = num2;
+            z = num3;
+        }
+
+        /// <summary>
+        /// Calculates and returns a Vector produced by crossing two other Vectors.
+        /// </summary>
+        /// <param name="v1">First Vector used.</param>
+        /// <param name="v2">Second Vector used.</param>
+        /// <returns>A Vector as a crossing result from the passed two vectors.</returns>
+        public static TszXYZ CrossProduct(TszXYZ v1, TszXYZ v2)
+        {
+            TszXYZ vector = new TszXYZ(v1);
+            vector.Cross(v2);
+            return vector;
+        }
+
+        /// <summary>
+        /// Check if the passed TszXYZ has equal x,y,z values with this object.
+        /// </summary>
+        /// <param name="pt">A TszXYZ to be checked if it is equal to this object.</param>
+        /// <param name="Equality">A double value representing the equality(for example 0.00001).</param>
+        /// <returns>True if the x,y,z values are equal.</returns>
+        public bool AreEqual(TszXYZ pt, double Equality)
+        {
+            return ((((pt != null) && TszGeoUtil.AreEqual(this.x, pt.x, Equality)) &&
+                     TszGeoUtil.AreEqual(this.y, pt.y, Equality)) && TszGeoUtil.AreEqual(this.z, pt.z, Equality));
+        }
+
+        /// <summary>
+        /// Returns the distance between this TszXYZ and the parameter.The z is not taken into consideration.
+        /// </summary>
+        /// <param name="pt">A TszXYZ needed for the calculation of the distance.</param>
+        /// <returns>The 2D distance between the two points.</returns>
+        public virtual double FindDistance2(TszXYZ pt)
+        {
+            return Math.Sqrt(((this.x - pt.x)*(this.x - pt.x)) + ((this.y - pt.y)*(this.y - pt.y)));
+        }
+
+        /// <summary>
+        /// Calculates the 2D distance between two gPoints.
+        /// </summary>
+        /// <param name="fromThis">First TszXYZ needed.</param>
+        /// <param name="toThis">Second TszXYZ needed.</param>
+        /// <returns>The 2D distance between the two given gPoints.</returns>
+        public static double FindDistance2(TszXYZ fromThis, TszXYZ toThis)
+        {
+            return
+                Math.Sqrt(((fromThis.x - toThis.x)*(fromThis.x - toThis.x)) +
+                          ((fromThis.y - toThis.y)*(fromThis.y - toThis.y)));
+        }
+
+        /// <summary>
+        /// Returns the distance between this TszXYZ and the parameter.
+        /// </summary>
+        /// <param name="other">A TszXYZ needed for the calculation of the distance.</param>
+        /// <returns>The distance between the two points.</returns>
+        public virtual double Distance3D(TszXYZ other)
+        {
+            return Math.Sqrt(this.DistanceSquared(other));
+        }
+
+        /// <summary>
+        /// Calculates the distance between two gPoints.
+        /// </summary>
+        /// <param name="fromThis">First TszXYZ needed.</param>
+        /// <param name="toThis">Second TszXYZ needed.</param>
+        /// <returns>The distance between the two given gPoints.</returns>
+        public static double Distance3D(TszXYZ fromThis, TszXYZ toThis)
+        {
+            return Math.Sqrt(DistanceSquared(fromThis, toThis));
+        }
+
+        /// <summary>
+        /// Returns the square of the distance between two gPoints.
+        /// </summary>
+        /// <param name="other">The other TszXYZ object.</param>
+        /// <returns>The square of distance between the given TszXYZ and this one.</returns>
+        public virtual double DistanceSquared(TszXYZ other)
+        {
+            double num = other.x - this.x;
+            double num2 = other.y - this.y;
+            double num3 = other.z - this.z;
+            return (((num*num) + (num2*num2)) + (num3*num3));
+        }
+
+        /// <summary>
+        /// Calculate the squared distance between two gPoints.
+        /// </summary>
+        /// <param name="fromThis">First TszXYZ needed.</param>
+        /// <param name="toThis">Second TszXYZ needed</param>
+        /// <returns>The squared distance between the two given gPoints.</returns>
+        public static double DistanceSquared(TszXYZ fromThis, TszXYZ toThis)
+        {
+            double num = toThis.x - fromThis.x;
+            double num2 = toThis.y - fromThis.y;
+            double num3 = toThis.z - fromThis.z;
+            return (((num*num) + (num2*num2)) + (num3*num3));
+        }
+
+        public TszXYZ Round()
+        {
+            return new TszXYZ(x.Round(), y.Round(), z.Round());
+        }
+
+        public TszXYZ NewZ(double dZ)
+        {
+            return new TszXYZ(x, y, dZ);
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct xyz
+        {
+            internal double _x;
+            internal double _y;
+            internal double _z;
+        }
+    }
+
+    public class TszXYZComparer : IComparer<TszXYZ>
+    {
+        /// <summary>
+        /// 左下、右上
+        /// </summary>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <returns></returns>
+        int IComparer<TszXYZ>.Compare(TszXYZ first, TszXYZ second)
+        {
+            // first compare z coordinate, then y coordinate, at last x coordinate
+            if (TszGeoUtil.IsEqual(first.z, second.z))
+            {
+                if (TszGeoUtil.IsEqual(first.y, second.y))
+                {
+                    if (TszGeoUtil.IsEqual(first.x, second.x))
+                    {
+                        return 0;
+                    }
+                    return (first.x > second.x) ? 1 : -1;
+                }
+                return (first.y > second.y) ? 1 : -1;
+            }
+            return (first.z > second.z) ? 1 : -1;
+        }
+    }
+
+    public class TszVector
+    {
+        internal xyz mxyz;
+
+        /// <summary>
+        /// Initializes a TszVector object (0.0,0.0,0.0). 
+        /// </summary>
+        public TszVector()
+        {
+            this.x = 0.0;
+            this.y = 0.0;
+            this.z = 0.0;
+        }
+
+        public TszVector(double X, double Y)
+        {
+            this.x = X;
+            this.y = Y;
+            this.z = 0;
+        }
+
+        public TszVector(TszVector pt, double Z)
+        {
+            this.x = pt.x;
+            this.y = pt.y;
+            this.z = Z;
+        }
+
+        /// <summary>
+        /// Initializes a TszVector object (X,Y,Z).
+        /// </summary>
+        /// <param name="X">The x coordinate of the point.</param>
+        /// <param name="Y">The y coordinate of the point.</param>
+        /// <param name="Z">The z coordinate of the point.</param>
+        public TszVector(double X, double Y, double Z)
+        {
+            this.x = X;
+            this.y = Y;
+            this.z = Z;
+        }
+
+        /// <summary>
+        /// Initializes a TszVector object at the coordinates of the pt parameter.
+        /// </summary>
+        /// <param name="pt">A TszVector object from which the coordinjates will be taken from.</param>
+        public TszVector(TszVector pt)
+        {
+            this.x = pt.x;
+            this.y = pt.y;
+            this.z = pt.z;
+        }
+
+        /// <summary>
+        /// The x value of the point.
+        /// </summary>
+        public double x
+        {
+            get { return this.mxyz._x; }
+            set { this.mxyz._x = value; }
+        }
+
+        /// <summary>
+        /// The y value of the point.
+        /// </summary>
+        public double y
+        {
+            get { return this.mxyz._y; }
+            set { this.mxyz._y = value; }
+        }
+
+        /// <summary>
+        /// The z value of the point.
+        /// </summary>
+        public double z
+        {
+            get { return this.mxyz._z; }
+            set { this.mxyz._z = value; }
+        }
+
+        /// <summary>
+        /// X
+        /// </summary>
+        public static TszVector BasisX
+        {
+            get { return new TszVector(1, 0, 0); }
+        }
+
+        /// <summary>
+        /// Y
+        /// </summary>
+        public static TszVector BasisY
+        {
+            get { return new TszVector(0, 1, 0); }
+        }
+
+        /// <summary>
+        /// Z
+        /// </summary>
+        public static TszVector BasisZ
+        {
+            get { return new TszVector(0, 0, 1); }
+        }
+
+        /// <summary>
+        /// Implements the + operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="pt"></param>
+        /// <returns></returns>
+        public static TszVector operator +(TszVector p, TszVector pt)
+        {
+            TszVector point = new TszVector();
+            point.x = p.x + pt.x;
+            point.y = p.y + pt.y;
+            point.z = p.z + pt.z;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the / operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static TszVector operator /(TszVector p, double value)
+        {
+            TszVector point = new TszVector();
+            point.x = p.x/value;
+            point.y = p.y/value;
+            point.z = p.z/value;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the == operator for two gPoints.
+        /// </summary>
+        /// <param name="a"></param>
+        /// <param name="b"></param>
+        /// <returns></returns>
+        public static bool operator ==(TszVector a, TszVector b)
+        {
+            return (ReferenceEquals(a, b) || (((null != a) && (null != b)) && a.Equals(b)));
+        }
+
+        /// <summary>
+        /// Implements the != operator for two gPoints.
+        /// </summary>
+        /// <param name="obj1"></param>
+        /// <param name="obj2"></param>
+        /// <returns></returns>
+        public static bool operator !=(TszVector obj1, TszVector obj2)
+        {
+            return !(obj1 == obj2);
+        }
+
+        /// <summary>
+        /// Implements the * operator for a TszVector with a double value.
+        /// </summary>
+        /// <param name="value"></param>
+        /// <param name="p"></param>
+        /// <returns></returns>
+        public static TszVector operator *(double value, TszVector p)
+        {
+            TszVector point = new TszVector();
+            point.x = p.x*value;
+            point.y = p.y*value;
+            point.z = p.z*value;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the * operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static TszVector operator *(TszVector p, double value)
+        {
+            TszVector point = new TszVector();
+            point.x = p.x*value;
+            point.y = p.y*value;
+            point.z = p.z*value;
+            return point;
+        }
+
+        /// <summary>
+        /// Implements the - operator for two gPoints.
+        /// </summary>
+        /// <param name="p"></param>
+        /// <param name="pt"></param>
+        /// <returns></returns>
+        public static TszVector operator -(TszVector p, TszVector pt)
+        {
+            TszVector point = new TszVector();
+            point.x = p.x - pt.x;
+            point.y = p.y - pt.y;
+            point.z = p.z - pt.z;
+            return point;
+        }
+
+        /// <summary>
+        /// Serves as a hash function for the collection.
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            return ((this.x.GetHashCode() ^ this.y.GetHashCode()) ^ this.z.GetHashCode());
+        }
+
+        /// <summary>
+        /// Checks if the parameter object is equal to this object.
+        /// </summary>
+        /// <param name="obj">An object to be checked if it is equal with this TszVector object.</param>
+        /// <returns>True if the objects are equal.</returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == null)
+            {
+                return false;
+            }
+            TszVector p = obj as TszVector;
+            return this.Equals(p);
+        }
+
+        /// <summary>
+        /// Checks if the parameter TszVector object is equal to this object.
+        /// </summary>
+        /// <param name="p">A TszVector object to be checked if the x,y,z values are the same with this object's values.</param>
+        /// <returns>True if all x,y,z values are equal.</returns>
+        public bool Equals(TszVector p)
+        {
+            if (p == null)
+            {
+                return false;
+            }
+            return (((this.x == p.x) && (this.y == p.y)) && (this.z == p.z));
+        }
+
+        /// <summary>
+        /// Convert this Vector to one unit length.
+        /// </summary>
+        public TszVector Normalize()
+        {
+            double dX = 0;
+            double dY = 0;
+            double dZ = 0;
+            double num = Math.Sqrt(((x*x) + (y*y)) + (z*z));
+            if (TszGeoUtil.AreEqual(num, 0.0, 1E-08))
+            {
+                dX = 0.0;
+                dY = 0.0;
+                dZ = 1.0;
+            }
+            else
+            {
+                dX = x/num;
+                dY = y/num;
+                dZ = z/num;
+                if (TszGeoUtil.AreEqual(dX, 0.0, 1E-08))
+                {
+                    dX = 0.0;
+                }
+                if (TszGeoUtil.AreEqual(dX, 1.0, 1E-08))
+                {
+                    dX = 1.0;
+                }
+                if (TszGeoUtil.AreEqual(dY, 0.0, 1E-08))
+                {
+                    dY = 0.0;
+                }
+                if (TszGeoUtil.AreEqual(dY, 1.0, 1E-08))
+                {
+                    dY = 1.0;
+                }
+                if (TszGeoUtil.AreEqual(dZ, 0.0, 1E-08))
+                {
+                    dZ = 0.0;
+                }
+                if (TszGeoUtil.AreEqual(dZ, 1.0, 1E-08))
+                {
+                    dZ = 1.0;
+                }
+            }
+            return new TszVector(dX, dY, dZ);
+        }
+
+        /// <summary>
+        /// Changes this Vector regarding the crossing operation with another Vector.
+        /// </summary>
+        /// <param name="other">A Vector object required for the operation.</param>
+        public void Cross(TszVector other)
+        {
+            double num = (y*other.z) - (other.y*z);
+            double num2 = (z*other.x) - (other.z*x);
+            double num3 = (x*other.y) - (other.x*y);
+            x = num;
+            y = num2;
+            z = num3;
+        }
+
+        /// <summary>
+        /// Calculates and returns a Vector produced by crossing two other Vectors.
+        /// </summary>
+        /// <param name="v1">First Vector used.</param>
+        /// <param name="v2">Second Vector used.</param>
+        /// <returns>A Vector as a crossing result from the passed two vectors.</returns>
+        public static TszVector CrossProduct(TszVector v1, TszVector v2)
+        {
+            TszVector vector = new TszVector(v1);
+            vector.Cross(v2);
+            return vector;
+        }
+
+        /// <summary>
+        /// Check if the passed TszVector has equal x,y,z values with this object.
+        /// </summary>
+        /// <param name="pt">A TszVector to be checked if it is equal to this object.</param>
+        /// <param name="Equality">A double value representing the equality(for example 0.00001).</param>
+        /// <returns>True if the x,y,z values are equal.</returns>
+        public bool AreEqual(TszVector pt, double Equality)
+        {
+            return ((((pt != null) && TszGeoUtil.AreEqual(this.x, pt.x, Equality)) &&
+                     TszGeoUtil.AreEqual(this.y, pt.y, Equality)) && TszGeoUtil.AreEqual(this.z, pt.z, Equality));
+        }
+
+        /// <summary>
+        /// Returns the distance between this TszVector and the parameter.The z is not taken into consideration.
+        /// </summary>
+        /// <param name="pt">A TszVector needed for the calculation of the distance.</param>
+        /// <returns>The 2D distance between the two points.</returns>
+        public virtual double FindDistance2(TszVector pt)
+        {
+            return Math.Sqrt(((this.x - pt.x)*(this.x - pt.x)) + ((this.y - pt.y)*(this.y - pt.y)));
+        }
+
+        /// <summary>
+        /// Calculates the 2D distance between two gPoints.
+        /// </summary>
+        /// <param name="fromThis">First TszVector needed.</param>
+        /// <param name="toThis">Second TszVector needed.</param>
+        /// <returns>The 2D distance between the two given gPoints.</returns>
+        public static double FindDistance2(TszVector fromThis, TszVector toThis)
+        {
+            return
+                Math.Sqrt(((fromThis.x - toThis.x)*(fromThis.x - toThis.x)) +
+                          ((fromThis.y - toThis.y)*(fromThis.y - toThis.y)));
+        }
+
+        /// <summary>
+        /// Returns the distance between this TszVector and the parameter.
+        /// </summary>
+        /// <param name="other">A TszVector needed for the calculation of the distance.</param>
+        /// <returns>The distance between the two points.</returns>
+        public virtual double Distance3D(TszVector other)
+        {
+            return Math.Sqrt(this.DistanceSquared(other));
+        }
+
+        /// <summary>
+        /// Calculates the distance between two gPoints.
+        /// </summary>
+        /// <param name="fromThis">First TszVector needed.</param>
+        /// <param name="toThis">Second TszVector needed.</param>
+        /// <returns>The distance between the two given gPoints.</returns>
+        public static double Distance3D(TszVector fromThis, TszVector toThis)
+        {
+            return Math.Sqrt(DistanceSquared(fromThis, toThis));
+        }
+
+        /// <summary>
+        /// Returns the square of the distance between two gPoints.
+        /// </summary>
+        /// <param name="other">The other TszVector object.</param>
+        /// <returns>The square of distance between the given TszVector and this one.</returns>
+        public virtual double DistanceSquared(TszVector other)
+        {
+            double num = other.x - this.x;
+            double num2 = other.y - this.y;
+            double num3 = other.z - this.z;
+            return (((num*num) + (num2*num2)) + (num3*num3));
+        }
+
+        /// <summary>
+        /// Calculate the squared distance between two gPoints.
+        /// </summary>
+        /// <param name="fromThis">First TszVector needed.</param>
+        /// <param name="toThis">Second TszVector needed</param>
+        /// <returns>The squared distance between the two given gPoints.</returns>
+        public static double DistanceSquared(TszVector fromThis, TszVector toThis)
+        {
+            double num = toThis.x - fromThis.x;
+            double num2 = toThis.y - fromThis.y;
+            double num3 = toThis.z - fromThis.z;
+            return (((num*num) + (num2*num2)) + (num3*num3));
+        }
+
+        public TszVector Round()
+        {
+            return new TszVector(x.Round(), y.Round(), z.Round());
+        }
+
+        public TszVector NewZ(double dZ)
+        {
+            return new TszVector(x, y, dZ);
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct xyz
+        {
+            internal double _x;
+            internal double _y;
+            internal double _z;
+        }
+    }
+
+    public class VectorComparer : IComparer<TszVector>
+    {
+        /// <summary>
+        /// 左下、右上
+        /// </summary>
+        /// <param name="first"></param>
+        /// <param name="second"></param>
+        /// <returns></returns>
+        int IComparer<TszVector>.Compare(TszVector first, TszVector second)
+        {
+            // first compare z coordinate, then y coordinate, at last x coordinate
+            if (TszGeoUtil.IsEqual(first.z, second.z))
+            {
+                if (TszGeoUtil.IsEqual(first.y, second.y))
+                {
+                    if (TszGeoUtil.IsEqual(first.x, second.x))
+                    {
+                        return 0;
+                    }
+                    return (first.x > second.x) ? 1 : -1;
+                }
+                return (first.y > second.y) ? 1 : -1;
+            }
+            return (first.z > second.z) ? 1 : -1;
+        }
+    }
+}

+ 63 - 0
MBI/SAGA.DotNetUtils/Geometry/TwoPointRelation.cs

@@ -0,0 +1,63 @@
+/////////////////////////////////////////////
+//Copyright (c) 2011, 北京探索者软件公司
+//All rights reserved.       
+//文件名称: 
+//文件描述: 
+//创 建 者: mjy
+//创建日期: 2011-11-02
+//版 本 号:4.0.0.0  
+/////////////////////////////////////////////
+
+using System.Drawing;
+
+namespace SAGA.DotNetUtils.Geometry
+{
+    public class TwoPointRelation
+    {
+        private PointF fix;
+        private PointF other;
+        public TwoPointRelation(PointF fix, PointF other)
+        {
+            this.fix = fix;
+            this.other = other;
+        }
+
+        public RelationOptions RelationGraphics
+        {
+            get
+            {
+                if (other.X >= fix.X)
+                {
+                    if (other.Y >= fix.Y)
+                        return RelationOptions.RightDown;
+                    return RelationOptions.RightUp;
+                }
+                else
+                {
+                    if (other.Y >= fix.Y)
+                        return RelationOptions.LeftDown;
+                    return RelationOptions.LeftUp;
+                }
+            }
+        }
+
+        public RelationOptions RelationCAD
+        {
+            get
+            {
+                if (other.X >= fix.X)
+                {
+                    if (other.Y >= fix.Y)
+                        return RelationOptions.RightUp;
+                    return RelationOptions.RightDown;
+                }
+                else
+                {
+                    if (other.Y >= fix.Y)
+                        return RelationOptions.LeftUp;
+                    return RelationOptions.LeftDown;
+                }
+            }
+        }        
+    }
+}

+ 89 - 0
MBI/SAGA.DotNetUtils/Geometry/VTwoPointRelation.cs

@@ -0,0 +1,89 @@
+/////////////////////////////////////////////
+//Copyright (c) 2011, 北京探索者软件公司
+//All rights reserved.       
+//文件名称: 
+//文件描述: 
+//创 建 者: mjy
+//创建日期: 2011-11-02
+//版 本 号:4.0.0.0  
+/////////////////////////////////////////////
+
+using System;
+using System.Drawing;
+
+namespace SAGA.DotNetUtils.Geometry
+{
+   public class VTwoPointRelation
+    {
+        private PointF fix;
+        private PointF other;
+        public VTwoPointRelation(PointF fix, PointF other)
+        {
+            this.fix = fix;
+            this.other = other;
+        }
+
+        public PointF Fix { get { return fix; } }
+        public PointF Other { get { return other; } }
+        public double Distance
+        {
+            get
+            {
+                return Geometry2D.Dist(fix.ToPointD(), other.ToPointD());
+            }
+        }
+
+        public RelationOptions RelationGraphics
+        {
+            get
+            {
+                if (fix == other)
+                    return RelationOptions.Override;
+                if (other.Y > fix.Y)
+                {
+                    return RelationOptions.Down;
+                }
+                else
+                {
+                    return RelationOptions.Up;
+                }
+            }
+        }
+
+        public RelationOptions RelationCAD
+        {
+            get
+            {
+                if (fix == other)
+                    return RelationOptions.Override;
+                if (other.Y > fix.Y)
+                {
+                    return RelationOptions.Up;
+                }
+                else
+                {
+                    return RelationOptions.Down;
+                }
+            }
+        }
+
+        public PointF VOther
+        {
+            get
+            {
+                return new PointF(fix.X, other.Y);
+            }
+        }
+
+        public double VDistance
+        {
+            get
+            {
+                double d = Math.Abs(other.Y - fix.Y);
+                if (d < 0.000001d)
+                    return 0d;
+                return d;
+            }
+        }
+    }
+}

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

@@ -323,6 +323,16 @@
     <Compile Include="FileOperate\FileStreamOperate.cs" />
     <Compile Include="Extend\IEnumerableExtend.cs" />
     <Compile Include="Extend\IntExt.cs" />
+    <Compile Include="Geometry\Extends.cs" />
+    <Compile Include="Geometry\Geometry2d.cs" />
+    <Compile Include="Geometry\HTwoPointRelation.cs" />
+    <Compile Include="Geometry\OffsetPolyLine.cs" />
+    <Compile Include="Geometry\RelationOptions.cs" />
+    <Compile Include="Geometry\TszGeoUtil.cs" />
+    <Compile Include="Geometry\TszTransform.cs" />
+    <Compile Include="Geometry\TszXYZ.cs" />
+    <Compile Include="Geometry\TwoPointRelation.cs" />
+    <Compile Include="Geometry\VTwoPointRelation.cs" />
     <Compile Include="Hook\ActivityHookImpl.cs" />
     <Compile Include="Hook\IActivityHook.cs" />
     <Compile Include="Hook\KeyBordHook.cs" />

+ 4 - 3
MBI/SAGA.MBI/Calc/ObjectCalc.cs

@@ -165,6 +165,7 @@ namespace SAGA.MBI.Calc
         private static void CalcEquipPartRlt(CalcContext context)
         {
             var familyInstances = context.RevitDoc.GetFamilyInstances();
+            var rspaces = context.RevitDoc.GetSpaces().Where(t => t.IsValidObject).ToList();
             List<FamilyInstance> parts = new List<FamilyInstance>();
             foreach (FamilyInstance fi in familyInstances)
             {
@@ -177,7 +178,7 @@ namespace SAGA.MBI.Calc
                     context.MEquipments.Add(equipment);
 
                     //识别设备所在空间
-                    var space = fi.GetReferenceSpace();
+                    var space = fi.GetReferenceSpace(rspaces);
                     if (space == null) continue;
                     string spaceId = space.GetCloudBIMId();
                     MISpace mSpace = context.MSpaces.FirstOrDefault(t => t.BimID == spaceId);
@@ -197,7 +198,7 @@ namespace SAGA.MBI.Calc
                     context.MBeacons.Add(mode);
 
                     //识别信标所在元空间
-                    var space = fi.GetReferenceSpace();
+                    var space = fi.GetReferenceSpace(rspaces);
                     if (space == null) continue;
                     string spaceId = space.GetCloudBIMId();
                     MISpace mSpace = context.MSpaces.FirstOrDefault(t => t.BimID == spaceId);
@@ -222,7 +223,7 @@ namespace SAGA.MBI.Calc
                 context.MEquipmentParts.Add(equipment);
 
                 //识别设备所在空间
-                var space = fi.GetReferenceSpace();
+                var space = fi.GetReferenceSpace(rspaces);
                 if (space == null) continue;
                 string spaceId = space.GetCloudBIMId();
                 MISpace mSpace = context.MSpaces.FirstOrDefault(t => t.BimID == spaceId);

+ 1 - 115
MBI/SAGA.MBI/DataArrange/DalUploadFloor.cs

@@ -450,121 +450,7 @@ namespace SAGA.MBI.DataArrange
             }
             return list;
         }
-        /// <summary>
-        /// 关闭revit文件
-        /// </summary>
-        /// <param name="uploadFloors"></param>
-        /// <returns></returns>
-        public static ObservableCollection<MTopologyGriph> CloseFloorDoc(ObservableCollection<UploadFloor> uploadFloors)
-        {
-            ObservableCollection<MTopologyGriph> list = new ObservableCollection<MTopologyGriph>();
-            foreach (var uploadFloor in uploadFloors)
-            {
-                uploadFloor.CalcContext?.RevitDoc.CloseDoc();
-            }
-            return list;
-        }
-        /// <summary>
-        /// 处理设备所在空间
-        /// </summary>
-        /// <param name="context"></param>
-        private static void CheckEquipSpaceRlt(CalcContext context)
-        {
-            //设备
-            foreach (MEquipment equip in context.MEquipments)
-            {
-                OperateEquipInSpace(equip, context);
-            }
-            //部件
-            foreach (MEquipmentPart equip in context.MEquipmentParts)
-            {
-                OperateEquipInSpace(equip, context);
-            }
-            //信标
-            foreach (MBeacon mode in context.MBeacons)
-            {
-                OperateRltBeaconinElementSp(mode, context);
-            }
-        }
-        /// <summary>
-        /// 处理设备所在空间
-        /// </summary>
-        /// <param name="mode"></param>
-        /// <param name="context"></param>
-        private static void OperateEquipInSpace(MRevitEquipBase mode, CalcContext context)
-        {
-            //if (mode.Operator == DocumentChangedOperator.None) return;
-            var revitId = mode.BimID.GetBIMID();
-            if (revitId == 0) return;
-            var fi = context.RevitDoc.GetElement(revitId) as FamilyInstance;
-            Autodesk.Revit.DB.Mechanical.Space space = fi?.GetReferenceSpace();
-            if (space == null) return;
-            //查询有没有Space对象
-            string spaceId = space.GetCloudBIMId();
-            var mspace = context.MSpaces.FirstOrDefault(t => t.BimID == spaceId);
-            if (mspace == null) return;
-            switch (mode.Operator)
-            {
-                case DocumentChangedOperator.Add:
-                    context.RltEquipInSpaces.Add(new RltEquipInSpace(mspace, mode) { Operator = DocumentChangedOperator.Add });
-                    break;
-                case DocumentChangedOperator.Delete:
-                    context.RltEquipInSpaces.Add(new RltEquipInSpace(null, mode) { Operator = DocumentChangedOperator.Delete });
-                    break;
-                case DocumentChangedOperator.Modified:
-                    //修改为,先删除,再新建
-                    context.RltEquipInSpaces.Add(new RltEquipInSpace(null, mode) { Operator = DocumentChangedOperator.Delete });
-                    context.RltEquipInSpaces.Add(new RltEquipInSpace(mspace, mode) { Operator = DocumentChangedOperator.Add });
-                    break;
-                case DocumentChangedOperator.None:
-                    //空间更改可能不引起设备修改,所以设备所在元空间关系跟据元空间状态重新计算。
-                    if (mspace.Operator == DocumentChangedOperator.Add ||
-                        mspace.Operator == DocumentChangedOperator.Modified)
-                    {
-                        context.RltEquipInSpaces.Add(new RltEquipInSpace(null, mode) { Operator = DocumentChangedOperator.Delete });
-                        context.RltEquipInSpaces.Add(new RltEquipInSpace(mspace, mode) { Operator = DocumentChangedOperator.Add });
-                    }
-                    else if (mspace.Operator == DocumentChangedOperator.Delete)
-                    {
-                        context.RltEquipInSpaces.Add(new RltEquipInSpace(null, mode) { Operator = DocumentChangedOperator.Delete });
-                    }
-                    break;
-            }
-        }
-
-        /// <summary>
-        /// 信标所在元空间
-        /// </summary>
-        /// <param name="mode"></param>
-        /// <param name="context"></param>
-        private static void OperateRltBeaconinElementSp(MRevitEquipBase mode, CalcContext context)
-        {
-            if (mode.Operator == DocumentChangedOperator.None) return;
-            var revitId = mode.BimID.GetBIMID();
-            var fi = context.RevitDoc.GetElement(revitId) as FamilyInstance;
-            Autodesk.Revit.DB.Mechanical.Space space = fi?.Space;
-            if (space == null) return;
-            //查询有没有Space对象
-            string spaceId = space.GetCloudBIMId();
-            var mspace = context.MSpaces.FirstOrDefault(t => t.BimID == spaceId);
-            if (mspace == null) return;
-            switch (mode.Operator)
-            {
-                case DocumentChangedOperator.Add:
-                    context.RltBeaconinElementSps.Add(new RltBeaconinElementSp(mspace, mode) { Operator = DocumentChangedOperator.Add });
-                    break;
-                case DocumentChangedOperator.Modified:
-                    //修改为,先删除,再新建
-                    context.RltBeaconinElementSps.Add(new RltBeaconinElementSp(null, mode) { Operator = DocumentChangedOperator.Delete });
-                    context.RltBeaconinElementSps.Add(new RltBeaconinElementSp(mspace, mode) { Operator = DocumentChangedOperator.Add });
-                    break;
-                case DocumentChangedOperator.Delete:
-                    context.RltBeaconinElementSps.Add(new RltBeaconinElementSp(null, mode) { Operator = DocumentChangedOperator.Delete });
-                    break;
-            }
-        }
-
-
+       
         /// <summary>
         /// 上传
         /// </summary>

+ 4 - 12
MBI/SAGA.MBI/Extend/ElementExtend.cs

@@ -188,14 +188,13 @@ namespace SAGA.MBI.Tools
         /// </summary>
         /// <param name="fi"></param>
         /// <returns></returns>
-        public static Space GetReferenceSpace(this FamilyInstance fi)
+        public static Space GetReferenceSpace(this FamilyInstance fi, List<Space> spaces = null)
         {
             Space space = fi.Space;
             if (space != null) return space;
-            var spaces = fi.Document.GetSpaces().Where(t => t.IsValidObject).ToList();
-            Space temSpace2 = null;
+            if (spaces == null)
+                spaces = fi.Document.GetSpaces().Where(t => t.IsValidObject).ToList();
             var origin1 = fi.GetLocationPointMBIXYZ();
-            var origin2 = fi.GetBoxCenter();
             foreach (Space tempSpace in spaces)
             {
                 //没有Space属性,取定位点,判断定位点所在空间
@@ -204,16 +203,9 @@ namespace SAGA.MBI.Tools
                     space = tempSpace;
                     break;
                 }
-
-                //还没有找到空间,取Box中心点,判断点所在空间
-                if (temSpace2 != null) continue;
-                if (tempSpace.IsPointInSpace(origin2))
-                {
-                    temSpace2 = tempSpace;
-                }
             }
 
-            return space ?? (temSpace2);
+            return space;
         }
     }
 }

+ 11 - 1
MBI/SAGA.MBI/RequestData/UpLoadFileRequest.cs

@@ -132,8 +132,18 @@ namespace SAGA.MBI.RequestData
             if (state == 2)
                 FloorFileOperate.BakFile(fullPath);
             string key = $"{MBIConst.OssClientFileKey}{cloudName}";
+            
             DownLoadNew:
-            OssClient client = new OssClient(MBIConst.Endpoint, MBIConst.AccessKeyId, MBIConst.AccessKeySecret);
+            OssClient client;
+            if (WebRequestProxy.IsOnline(out ClientConfiguration conf))
+            {
+                client = new OssClient(MBIConst.Endpoint, MBIConst.AccessKeyId, MBIConst.AccessKeySecret, conf);
+            }
+            else
+            {
+                client = new OssClient(MBIConst.Endpoint, MBIConst.AccessKeyId, MBIConst.AccessKeySecret);
+            }
+            
             int timeoutNum = 20;
             long totalLength = 0;
             try

+ 72 - 0
MBI/SAGA.MBI/RequestData/WebRequestProxy.cs

@@ -0,0 +1,72 @@
+/* ==============================================================================
+ * 功能描述:WebRequestProxy  
+ * 创 建 者:Garrett
+ * 创建日期:2019/5/10 17:48:28
+ * ==============================================================================*/
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Threading.Tasks;
+using Aliyun.OSS.Common;
+using SAGA.DotNetUtils;
+using SAGA.DotNetUtils.Extend;
+using SAGA.MBI.FileStream;
+
+namespace SAGA.MBI.RequestData
+{
+    /// <summary>
+    /// WebRequestProxy
+    /// </summary>
+    class WebRequestProxy
+    {
+        /// <summary>
+        /// 判断主机是否在线
+        /// </summary>
+        /// <param name="address"></param>
+        /// <returns></returns>
+        public static bool IsOnline(out ClientConfiguration config)
+        {
+            bool result = false;
+            string address = GetProxyAddress();
+            int port = GetProxyPort();
+            config = null;
+            if (address.IsNullOrEmpty() || port==0)
+                return result;
+            Ping ping=new Ping();
+            PingReply pingReply = ping.Send(address);
+            if (pingReply.Status == IPStatus.Success)
+            {
+                result = true;
+                config=new ClientConfiguration();
+                config.ProxyHost = address;
+                config.ProxyPort = port;
+            }
+            else
+            {
+                result = false;
+                config = null;
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// 获取下载代理地址
+        /// </summary>
+        /// <returns></returns>
+        private static string GetProxyAddress()
+        {
+            return ProjectDirOperate.GetConfigureInfo("ProxyHost");
+        }
+        /// <summary>
+        /// 获取下载代理端口
+        /// </summary>
+        /// <returns></returns>
+        private static int GetProxyPort()
+        {
+            return ProjectDirOperate.GetConfigureInfo("ProxyPort").ToInt();
+        }
+    }
+}

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

@@ -316,6 +316,7 @@
     <Compile Include="RequestData\FileContentTransferUnit.cs" />
     <Compile Include="RequestData\QRCodeRequest.cs" />
     <Compile Include="RequestData\RequestResultUtil.cs" />
+    <Compile Include="RequestData\WebRequestProxy.cs" />
     <Compile Include="RevitExport\SpaceSortUtils.cs" />
     <Compile Include="RevitModelHandle\ParameterDefinitionFactory.cs" />
     <Compile Include="RevitModelHandle\ParameterUtil.cs" />
@@ -394,7 +395,6 @@
       <DependentUpon>WinModeCheckSetting.xaml</DependentUpon>
     </Compile>
     <Compile Include="ToolsData\CorrectLossDuty.cs" />
-    <Compile Include="ToolsData\ExportAllCategory.cs" />
     <Compile Include="ToolsData\ExportAllEquipmentAll.cs" />
     <Compile Include="ToolsData\IToolCommand.cs" />
     <Compile Include="ToolsData\ExportAllDuty.cs" />

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

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Text;
@@ -14,7 +15,9 @@ using Autodesk.Revit.UI;
 using Autodesk.Revit.UI.Selection;
 using SAGA.DotNetUtils;
 using SAGA.DotNetUtils.Extend;
+using SAGA.DotNetUtils.Geometry;
 using SAGA.DotNetUtils.Logger;
+using SAGA.DotNetUtils.Others;
 using SAGA.MBI.Calc;
 using SAGA.MBI.DataArrange;
 using SAGA.MBI.Interaction;
@@ -31,6 +34,121 @@ using Color = Autodesk.Revit.DB.Color;
 
 namespace SAGA.MBI
 {
+    #region 测试命令
+    /// <summary>
+    /// 
+    /// </summary>
+    [Transaction(TransactionMode.Manual)]
+    [Regeneration(RegenerationOption.Manual)]
+    public class EquipInSpaceSpeedTest : ExternalCommand, IExternalCommandAvailability
+    {
+        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+        {
+            try
+            {
+                //var fi = ExternalDataWrapper.Current.UiApp.GetSelectedElement() as FamilyInstance;
+                //var space = fi.GetReferenceSpace();
+                //string str = "",str2="";
+                //while (true)
+                //{
+                //    if (space != null)
+                //    {
+                //        List<XYZ> spaceVertex = space.GetBoundaryVertexes().FirstOrDefault();
+                //        if (spaceVertex == null)
+                //        {
+                //            str = "Boundary 为Null";
+                //            break;
+                //        }
+
+                //        var xyz = fi.GetLocationPointMBIXYZ();
+                //        str = "Geometry Intersection Result:" + xyz.PointInPolygonByRay(spaceVertex);
+
+                //        str2 = "Geometry2D Intersection Result:" + Geometry2D.InSidePolygon(spaceVertex.Count,
+                //                   spaceVertex.Select(t => t.ToPointD()).ToArray(), xyz.ToPointD());
+
+
+
+                //    }
+                //    break;
+
+                //}
+                //MessageShowBase.Infomation($"{str}"+"\r\n"+$"{str2}");
+
+                var doc = commandData.View.Document;
+                var spaces = doc.GetSpaces().Where(t => t.IsValidObject).ToList();
+                var fis = doc.GetFamilyInstances().Where(t => t.IsEquipmentPart() || t.IsEquipment());
+                List<List<List<XYZ>>> spaceVertexes = spaces.Select(t => t.GetBoundaryVertexes()).ToList();
+                List<KeyValuePair<FamilyInstance, XYZ>> keyValuePairs = fis.Select(t => new KeyValuePair<FamilyInstance, XYZ>(t, t.GetLocationPointMBIXYZ())).ToList();
+                List<KeyValuePair<FamilyInstance, XYZ>> keyValuePairs_bak = new List<KeyValuePair<FamilyInstance, XYZ>>();
+                long rtime = 0, gtime = 0;
+                int rcount = 0, gcount = 0;
+                Stopwatch watch = new Stopwatch();
+                #region 使用Revit计算
+                watch.Start();
+                foreach (var pair in keyValuePairs)
+                {
+                    FamilyInstance fi = pair.Key;
+                    var space = fi.GetReferenceSpace(spaces);
+                    if (space != null)
+                    {
+                        rcount++;
+                        keyValuePairs_bak.Add(pair);
+                    }
+                }
+                watch.Stop();
+                rtime = watch.ElapsedMilliseconds;
+
+                #endregion
+
+                #region 使用Geomety计算
+
+                List<List<XYZ>> spaceBorderVertexes = spaceVertexes.Select(t => t.FirstOrDefault()).ToList();
+                watch.Reset();
+                watch.Start();
+
+                foreach (var pair in keyValuePairs)
+                {
+                    XYZ xyz = pair.Value;
+                    double z = xyz.Z;
+                    var point = xyz.ToPointD();
+                    foreach (var spaceVertex in spaceBorderVertexes)
+                    {
+                        if (spaceVertex == null) continue;
+
+                        double minz = spaceVertex.Min(t => t.Z);
+                        double maxz = spaceVertex.Max(t => t.Z);
+                        //if (z.IsBetween(minz, maxz))
+                        {
+                            if(Geometry2D.InSidePolygon(spaceVertex.Count,spaceVertex.Select(t=>t.ToPointD()).ToArray(),point)!=2)
+                            //if (xyz.PointInPolygonByRay(spaceVertex) != -1)
+                            {
+                                gcount++;
+
+                                keyValuePairs_bak.Remove(pair);
+                                break;
+                            }
+                        }
+                    }
+                }
+                watch.Stop();
+                gtime = watch.ElapsedMilliseconds;
+
+                #endregion
+
+                MessageShow.Infomation($"Revit计算耗时{rtime},共识别出{rcount}个空间" + "\r\n" +
+                                       $"Geometry计算耗时{gtime},共识别出{gcount}个空间" + "\r\n" +
+                                       $"{string.Join(",", keyValuePairs_bak.Select(t => t.Key.Id))}");
+            }
+            catch (Exception e)
+            {
+                MessageShow.Show(e);
+                return Result.Cancelled;
+            }
+            return Result.Succeeded;
+        }
+    }
+    #endregion
+
     /// <summary>
     /// 上传当前楼层数据
     /// </summary>

+ 1 - 75
MBI/SAGA.MBI/ToolCommand.cs

@@ -37,47 +37,7 @@ namespace SAGA.MBI
 {
 
     #region 工具
-    /// <summary>
-    /// 隔离立管
-    /// </summary>
-    [Transaction(TransactionMode.Manual)]
-    [Regeneration(RegenerationOption.Manual)]
-    public class VerticalPipeIsolationCommand : ExternalCommand
-    {
-        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
-        {
-            try
-            {
-                var elems = ExternalDataWrapper.Current.UiApp.WindowSelectElement("请框选...",new CommonFilter(t =>
-                {
-                    if (t is Pipe pipe)
-                    {
-                        var line = pipe.GetCurve() as Line;
-                        if (line != null)
-                        {
-                            var connectors = pipe.GetConnectors();
-                            
-                            return connectors.Any(tt=>!tt.IsConnected)&&line.Direction.IsParallel(XYZ.BasisZ);
-                        }
-                    }
-
-                    return false;
-                }));
-                ExternalDataWrapper.Current.UiApp.SetShowElements(elems,true);
-            }
-            catch (Exception e)
-            {
-                MessageShow.Show(e);
-                return Result.Cancelled;
-            }
-            return Result.Succeeded;
-        }
-
-        public override bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
-        {
-            return true;
-        }
-    }
+    
     /// <summary>
     /// 立管对齐
     /// </summary>
@@ -153,40 +113,6 @@ namespace SAGA.MBI
         }
     }
     /// <summary>
-    /// 导出类别
-    /// </summary>
-    [Transaction(TransactionMode.Manual)]
-    [Regeneration(RegenerationOption.Manual)]
-    public class ExportCategoriesCommand : ExternalCommand
-    {
-        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
-        {
-            try
-            {
-
-                var tip = MessageShow.Question("确定要导出所有的族类别?");
-                if (tip)
-                    BllFactory<ExportAllCategory>.Instance.Operate();
-            }
-            catch (Exception e)
-            {
-                MessageShow.Show(e);
-                return Result.Cancelled;
-            }
-            return Result.Succeeded;
-        }
-
-
-        /// <summary>
-        /// Onlys show the dialog when a document is open, as Dockable dialogs are only available
-        /// when a document is open.
-        /// </summary>
-        public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
-        {
-            return true;
-        }
-    }
-    /// <summary>
     /// 报告设备所在空间
     /// </summary>
     [Transaction(TransactionMode.Manual)]

+ 3 - 2
MBI/SAGA.MBI/ToolsData/CheckEquipCategory.cs

@@ -100,6 +100,7 @@ namespace SAGA.MBI.ToolsData
             //        //addContext.MSpaces.Add(mode);
             //    }
             //}
+            var spaces = baseContext.RevitDoc.GetSpaces().Where(t => t.IsValidObject).ToList();
             //检查设备
             foreach (var mode in baseContext.MEquipments)
             {
@@ -124,7 +125,7 @@ namespace SAGA.MBI.ToolsData
                     addContext.MEquipments.Add(equip);
 
                     //识别设备所在空间
-                    var space = fi.GetReferenceSpace();
+                    var space = fi.GetReferenceSpace(spaces);
                     if (space == null) continue;
                     string spaceId = space.GetCloudBIMId();
                     MISpace mSpace = addContext.MSpaces.FirstOrDefault(t => t.BimID == spaceId);
@@ -160,7 +161,7 @@ namespace SAGA.MBI.ToolsData
                     DalUploadFloor.SetSavePropertyValue(equipment, mode);
                     addContext.MEquipmentParts.Add(equipment);
                     //识别设备所在空间
-                    var space = fi.GetReferenceSpace();
+                    var space = fi.GetReferenceSpace(spaces);
                     if (space == null) continue;
                     string spaceId = space.GetCloudBIMId();
                     MISpace mSpace = addContext.MSpaces.FirstOrDefault(t => t.BimID == spaceId);

+ 5 - 3
MBI/SAGA.MBI/ToolsData/CheckEquipInSpace.cs

@@ -58,13 +58,14 @@ namespace SAGA.MBI.ToolsData
             context.OpenDocument();
             var document = context.RevitDoc;
             var spaces = context.MSpaces;
+            var rspaces = context.RevitDoc.GetSpaces().Where(t => t.IsValidObject).ToList(); 
             foreach (var equipment in context.MEquipments)
             {
                 var bimId = equipment.BimID;
                 FamilyInstance fi=document.GetElement(bimId.GetBIMID()) as FamilyInstance;
                 if (fi != null)
                 {
-                    var space = fi.GetReferenceSpace();
+                    var space = fi.GetReferenceSpace(rspaces);
                     if (space != null)
                     {
                         var spaceBimid = space.GetCloudBIMId();
@@ -111,6 +112,7 @@ namespace SAGA.MBI.ToolsData
         private static void CalcEquipPartRlt(CalcContext context)
         {
             var linkElements = context.RevitDoc.GetFamilyInstances();
+            var rspaces = context.RevitDoc.GetSpaces();
             //过滤出的所有实体
             foreach (FamilyInstance fi in linkElements)
             {
@@ -121,7 +123,7 @@ namespace SAGA.MBI.ToolsData
 
 
                     //识别设备所在空间
-                    var space = fi.GetReferenceSpace();
+                    var space = fi.GetReferenceSpace(rspaces);
                     if (space == null)
                     {
                         string familyName = fi.GetFamily().Name;
@@ -141,7 +143,7 @@ namespace SAGA.MBI.ToolsData
                     context.MEquipmentParts.Add(part);
 
                     //识别设备所在空间
-                    var space = fi.GetReferenceSpace();
+                    var space = fi.GetReferenceSpace(rspaces);
                     if (space == null)
                     {
                         string familyName = fi.GetFamily().Name;

+ 5 - 3
MBI/SAGA.MBI/ToolsData/ModeCheck/EquipmentInSpaceCheck.cs

@@ -9,6 +9,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Autodesk.Revit.DB;
+using Autodesk.Revit.DB.Mechanical;
 using NPOI.SS.UserModel;
 using SAGA.DotNetUtils.Others;
 using SAGA.MBI.DataArrange;
@@ -53,9 +54,10 @@ namespace SAGA.MBI.ToolsData.ModeCheck
                 var document = signResult.RDocument;
                 var elements = document.GetFamilyInstances();
                 var parts = elements.Where(t => t.IsEquipment()|| t.IsEquipmentPart());
+                var rspaces = document.GetSpaces().Where(t => t.IsValidObject).ToList();
                 foreach (FamilyInstance fi in parts)
                 {
-                    var result = GetCheckResult(fi);
+                    var result = GetCheckResult(fi,rspaces);
                     result.RBase = signResult;
                     Results.Add(result);
                 }
@@ -68,12 +70,12 @@ namespace SAGA.MBI.ToolsData.ModeCheck
         /// </summary>
         /// <param name="fi"></param>
         /// <returns></returns>
-        private ModeCheckResultBase GetCheckResult(FamilyInstance fi)
+        private ModeCheckResultBase GetCheckResult(FamilyInstance fi,List<Space> spaces)
         {
             var result = new EquipmentInSpaceCheckResult();
             result.FamilyName = fi.GetFamily().Name;
             result.Id = fi.Id.ToString();
-            var space = fi.GetReferenceSpace();
+            var space = fi.GetReferenceSpace(spaces);
             if (space == null)
             {
                 result.IsRight = false;

+ 77 - 0
MBI/SAGA.Revit.sln

@@ -59,6 +59,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{33B095DB-1
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{C14E2157-5E86-488A-89C9-31FB07D98D3C}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestCommand", "TestCommand\TestCommand.csproj", "{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ToolCommand", "ToolCommand\ToolCommand.csproj", "{5F2C216B-F298-4D86-A768-900BFFFEA91F}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -852,6 +856,78 @@ Global
 		{C14E2157-5E86-488A-89C9-31FB07D98D3C}.RR17|x64.Build.0 = RR17|Any CPU
 		{C14E2157-5E86-488A-89C9-31FB07D98D3C}.RR17|x86.ActiveCfg = RR17|Any CPU
 		{C14E2157-5E86-488A-89C9-31FB07D98D3C}.RR17|x86.Build.0 = RR17|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Debug|x64.Build.0 = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Debug|x86.Build.0 = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R16|Any CPU.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R16|Any CPU.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R16|x64.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R16|x64.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R16|x86.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R16|x86.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R17|Any CPU.ActiveCfg = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R17|Any CPU.Build.0 = Debug|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R17|x64.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R17|x64.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R17|x86.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R17|x86.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R18|Any CPU.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R18|Any CPU.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R18|x64.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R18|x64.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R18|x86.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.R18|x86.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Release|x64.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Release|x64.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Release|x86.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.Release|x86.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.RR17|Any CPU.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.RR17|Any CPU.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.RR17|x64.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.RR17|x64.Build.0 = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.RR17|x86.ActiveCfg = Release|Any CPU
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3}.RR17|x86.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Debug|x64.Build.0 = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Debug|x86.Build.0 = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R16|Any CPU.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R16|Any CPU.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R16|x64.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R16|x64.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R16|x86.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R16|x86.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R17|Any CPU.ActiveCfg = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R17|Any CPU.Build.0 = Debug|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R17|x64.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R17|x64.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R17|x86.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R17|x86.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R18|Any CPU.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R18|Any CPU.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R18|x64.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R18|x64.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R18|x86.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.R18|x86.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Release|x64.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Release|x64.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Release|x86.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.Release|x86.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.RR17|Any CPU.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.RR17|Any CPU.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.RR17|x64.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.RR17|x64.Build.0 = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.RR17|x86.ActiveCfg = Release|Any CPU
+		{5F2C216B-F298-4D86-A768-900BFFFEA91F}.RR17|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -861,6 +937,7 @@ Global
 		{1A6202BA-6646-48D1-8F93-F55ED4CFF075} = {6B218122-CAE7-4A42-B73F-AF24B065D823}
 		{EEBDB1AA-C80B-4F44-89EB-FB9D7DC2B1AE} = {6B218122-CAE7-4A42-B73F-AF24B065D823}
 		{C14E2157-5E86-488A-89C9-31FB07D98D3C} = {33B095DB-1BBF-49CE-8D5D-8128D017D382}
+		{F3C60916-7F3E-45E5-A695-1ECF408AF7D3} = {33B095DB-1BBF-49CE-8D5D-8128D017D382}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {4FA684AA-776F-4C7E-BB48-9587186AC17A}

+ 16 - 2
MBI/SAGA.RevitUtils/Extends/XYZExtend.cs

@@ -1,10 +1,12 @@
 using System;
 using System.Collections.Generic;
+using System.Drawing;
 using System.Linq;
 using System.Text.RegularExpressions;
 using Autodesk.Revit.DB;
 using SAGA.DotNetUtils;
 using SAGA.DotNetUtils.Extend;
+using SAGA.DotNetUtils.Geometry;
 using SAGA.RevitUtils.Infrastructure;
 using SAGA.RevitUtils.Utils;
 using Point = System.Windows.Point;
@@ -232,6 +234,10 @@ namespace SAGA.RevitUtils.Extends
             if (pt == null) return default(Point);
             return new Point(pt.X,pt.Y);
         }
+        public static Geometry2D.PointD ToPointD(this XYZ pt)
+        {
+            return new Geometry2D.PointD(pt.X, pt.Y);
+        }
 
         /// <summary>
         /// 转2DPoint
@@ -1674,7 +1680,11 @@ namespace SAGA.RevitUtils.Extends
         /// </summary>
         /// <param name="inputPoint"></param>
         /// <param name="lines"></param>
-        /// <returns></returns>
+        /// <returns>
+        ///  如果点在多边形内:   返回1 
+        ///  如果点在多边形边上: 返回0
+        ///  如果点在多边形外:	返回-1
+        /// </returns>
         public static int PointInPolygonByRay(this XYZ inputPoint, List<Line> lines)
         {
             #region 描述
@@ -1796,7 +1806,11 @@ namespace SAGA.RevitUtils.Extends
         /// </summary>
         /// <param name="inputPoint"></param>
         /// <param name="points"></param>
-        /// <returns></returns>
+        /// <returns>
+        ///  如果点在多边形内:   返回1 
+        ///  如果点在多边形边上: 返回0
+        ///  如果点在多边形外:	返回-1
+        /// </returns>
         public static int PointInPolygonByRay(this XYZ inputPoint, List<XYZ> points)
         {
             #region 老方法

+ 159 - 0
MBI/ToolCommand/Command.cs

@@ -0,0 +1,159 @@
+using Autodesk.Revit.Attributes;
+using Autodesk.Revit.DB;
+using Autodesk.Revit.DB.Structure;
+using Autodesk.Revit.UI;
+using SAGA.DotNetUtils;
+using SAGA.DotNetUtils.Extend;
+using SAGA.DotNetUtils.Others;
+using SAGA.RevitUtils;
+using SAGA.RevitUtils.Extends;
+using System;
+using System.IO;
+
+namespace ToolCommand
+{
+    /// <summary>
+    /// 批量删除无用的空间
+    /// </summary>
+    [Transaction(TransactionMode.Manual)]
+    [Regeneration(RegenerationOption.Manual)]
+    public class DeleteZeroSpaceCommand : ExternalCommand
+    {
+        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+        {
+            try
+            {
+                int count = 0;
+                bool tip = MessageShowBase.Question("确定要删除本层周长为零的空间?\r\n是:修正本楼层\r\n否:取消修正。");
+                if (tip)
+                {
+                    count = DelZeroSpace.Operate();
+                    MessageShowBase.Infomation($"此次操作共删除{count}个空间");
+                }
+            }
+            catch (Exception e)
+            {
+                MessageShow.Show(e);
+                return Result.Cancelled;
+            }
+            return Result.Succeeded;
+        }
+    }
+    /// <summary>
+    /// 导出类别
+    /// </summary>
+    [Transaction(TransactionMode.Manual)]
+    [Regeneration(RegenerationOption.Manual)]
+    public class ExportCategoriesCommand : ExternalCommand
+    {
+        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+        {
+            try
+            {
+
+                var tip = MessageShow.Question("确定要导出所有的族类别?");
+                if (tip)
+                {
+                    ExportAllCategory export = new ExportAllCategory();
+                    export.Operate();
+                }
+            }
+            catch (Exception e)
+            {
+                MessageShow.Show(e);
+                return Result.Cancelled;
+            }
+            return Result.Succeeded;
+        }
+
+
+        /// <summary>
+        /// Onlys show the dialog when a document is open, as Dockable dialogs are only available
+        /// when a document is open.
+        /// </summary>
+        public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
+        {
+            return true;
+        }
+    }
+
+    #region 浏览坐标
+    [Transaction(TransactionMode.Manual)]
+    [Regeneration(RegenerationOption.Manual)]
+    public class FocusLocationCommand : ExternalCommand, IExternalCommandAvailability
+    {
+        public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
+        {
+            var uiApp = commandData.Application;
+            var uiDoc = uiApp.ActiveUIDocument;
+            var doc = uiDoc.Document;
+
+            do
+            {
+                WinLocation win = new WinLocation();
+                if (win.ShowDialog() == true)
+                {
+                    string location = win.Location;
+                    if (ObjectExtend.IsNotNullEmpty(location))
+                    {
+                        XYZ xyz = ConvertToXyz(location);
+                        if (xyz == null)
+                        {
+                            MessageShow.Infomation("Location格式异常");
+                            break;
+                        }
+                        if (win.IsMetricSystem)
+                        {
+                            xyz = xyz.ConvertToApi();
+                        }
+                        PlaceHolder(doc, xyz);
+                    }
+                }
+            } while (false);
+            
+            return Result.Succeeded;
+        }
+
+        private XYZ ConvertToXyz(string str)
+        {
+            XYZ xyz = null;
+            var strs = str.Replace('(',' ').Replace(')',' ').SplitRemoveEmpty(",");
+            if (strs.Length == 3)
+            {
+                xyz = new XYZ(strs[0].ToDouble(), strs[1].ToDouble(), strs[2].ToDouble());
+            }
+
+            return xyz;
+        }
+        /// <summary>
+        /// 创建占位符
+        /// </summary>
+        /// <param name="doc"></param>
+        /// <param name="xyz"></param>
+        private void PlaceHolder(Document doc, XYZ xyz)
+        {
+            using (Transaction trans = new Transaction(doc, "创建信标"))
+            {
+                trans.Start();
+                try
+                {
+                    string familyFile = Path.Combine(AppBaseInfo.FamilyPath, "坐标箭头.rfa");
+                    FamilySymbol fs = doc.GetFamilySymbol(familyFile, BuiltInCategory.OST_GenericModel);
+                    var fi = doc.Create.NewFamilyInstance(xyz, fs, StructuralType.NonStructural);
+                    doc.Regenerate();
+                    trans.Commit();
+                    ExternalDataWrapper.Current.UiApp.SetShowElements(fi);
+                }
+                catch (Exception e)
+                {
+                    trans.RollBack();
+                    MessageShow.Show(e);
+                }
+            }
+        }
+
+        #endregion
+
+
+    }
+}

+ 58 - 0
MBI/ToolCommand/DelZeroSpace.cs

@@ -0,0 +1,58 @@
+/* ==============================================================================
+ * 功能描述:删除周长为零的空间
+ * 创 建 者:Garrett
+ * 创建日期:2018/7/12 14:25:17
+ * ==============================================================================*/
+
+using System;
+using System.Linq;
+using Autodesk.Revit.DB;
+using SAGA.DotNetUtils.Others;
+using SAGA.RevitUtils.Extends;
+
+namespace ToolCommand
+{
+    /// <summary>
+    /// CheckEquipCategory
+    /// </summary>
+    public class DelZeroSpace
+    {
+        /// <summary>
+        /// 检查并处理
+        /// </summary>
+        /// <param name="floor"></param>
+        /// <returns></returns>
+        public static int Operate()
+        {
+            int count = 0;
+            try
+            {
+                var doc = ExternalDataWrapper.Current.Doc;
+                using (Transaction trans = new Transaction(doc, "删除"))
+                {
+                    trans.Start();
+                    try
+                    {
+                        var spaces = doc.GetSpaces().Where(t => t.IsDeleteSpace()).ToList();
+                        count = spaces.Count;
+                        doc.Delete(spaces.Select(t => t.Id).ToList());
+                        trans.Commit();
+                    }
+                    catch (Exception)
+                    {
+                        trans.RollBack();
+
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                MessageShowBase.Show(e);
+            }
+            finally
+            {
+            }
+            return count;
+        }
+    }
+}

+ 3 - 8
MBI/SAGA.MBI/ToolsData/ExportAllCategory.cs

@@ -3,28 +3,23 @@
  * 创 建 者:Garrett
  * 创建日期:2018/10/11 8:58:18
  * ==============================================================================*/
+
 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;
 using Microsoft.Win32;
 using NPOI.SS.UserModel;
 using NPOI.XSSF.UserModel;
 using SAGA.DotNetUtils.Others;
-using SAGA.MBI.Calc;
 using SAGA.RevitUtils.Extends;
-using CellType = Autodesk.Revit.DB.CellType;
 
-namespace SAGA.MBI.ToolsData
+namespace ToolCommand
 {
     /// <summary>
     /// ExportAllCategory
     /// </summary>
-    class ExportAllCategory : IToolCommand
+    class ExportAllCategory
     {
         public void Operate()
         {

+ 36 - 0
MBI/ToolCommand/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("ToolCommand")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ToolCommand")]
+[assembly: AssemblyCopyright("Copyright ©  2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("5f2c216b-f298-4d86-a768-900bfffea91f")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 96 - 0
MBI/ToolCommand/ToolCommand.csproj

@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{5F2C216B-F298-4D86-A768-900BFFFEA91F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ToolCommand</RootNamespace>
+    <AssemblyName>ToolCommand</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\OutputDll\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\OutputDll\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\packages\NPOI.2.4.1\lib\net45\NPOI.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OOXML, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\packages\NPOI.2.4.1\lib\net45\NPOI.OOXML.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OpenXml4Net, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXml4Net.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OpenXmlFormats, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXmlFormats.dll</HintPath>
+    </Reference>
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+    <Reference Include="RevitAPI">
+      <HintPath>..\..\..\ServiceMBI\Dlls\RevitRefDll\RevitAPI.dll</HintPath>
+    </Reference>
+    <Reference Include="RevitAPIUI">
+      <HintPath>..\..\..\ServiceMBI\Dlls\RevitRefDll\RevitAPIUI.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xaml" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Command.cs" />
+    <Compile Include="DelZeroSpace.cs" />
+    <Compile Include="ExportAllCategory.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="WinLocation.xaml.cs">
+      <DependentUpon>WinLocation.xaml</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\SAGA.DotNetUtils\SAGA.DotNetUtils.csproj">
+      <Project>{07b73c98-dcb0-4782-81fa-f50a30b563ab}</Project>
+      <Name>SAGA.DotNetUtils</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\SAGA.RevitUtils\SAGA.RevitUtils.csproj">
+      <Project>{d6201677-b7e4-495a-81ab-33c5837121e6}</Project>
+      <Name>SAGA.RevitUtils</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Page Include="WinLocation.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 16 - 0
MBI/ToolCommand/WinLocation.xaml

@@ -0,0 +1,16 @@
+<Window x:Class="ToolCommand.WinLocation"
+             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"
+        mc:Ignorable="d" Title="请输入坐标"
+        Width="308.212" Height="100">
+    <Grid>
+        <Canvas>
+            <TextBox Text="" Height="24" Width="300" Name="txtLocation"></TextBox>
+            <Button Canvas.Left="50" Content="公制" Height="24" Width="80" Click="ButtonBase_OnClick" Tag="0" Canvas.Top="25"></Button>
+            <Button Canvas.Right="50" Content="英制" Height="24" Width="80" Click="ButtonBase_OnClick" Tag="1" Canvas.Top="25"></Button>
+        </Canvas>
+    </Grid>
+
+</Window>

+ 33 - 0
MBI/ToolCommand/WinLocation.xaml.cs

@@ -0,0 +1,33 @@
+using System.Windows;
+using System.Windows.Controls;
+using SAGA.DotNetUtils;
+
+namespace ToolCommand
+{
+    /// <summary>
+    /// WinLocation.xaml 的交互逻辑
+    /// </summary>
+    public partial class WinLocation
+    {
+        public WinLocation()
+        {
+            InitializeComponent();
+        }
+
+        public string Location
+        {
+            get
+            {
+                return txtLocation.Text;
+            }
+        }
+        public bool IsMetricSystem { get; set; }
+        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
+        {
+            var button = sender as Button;
+            if (button != null)
+                IsMetricSystem = button.Tag.ToInt() == 0;
+            this.DialogResult = true;
+        }
+    }
+}

+ 5 - 0
MBI/ToolCommand/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NPOI" version="2.4.1" targetFramework="net461" />
+  <package id="SharpZipLib" version="1.0.0" targetFramework="net461" />
+</packages>