Browse Source

xls:环形空间相交判断

xulisong 6 years ago
parent
commit
bb3bfb6e77

+ 55 - 0
MBI/SAGA.DotNetUtils/Extend/ListExtension.cs

@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:ListExtension
+ * 作者:xulisong
+ * 创建时间: 2019/4/30 13:22:51
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SAGA.DotNetUtils.Extend
+{
+    public static class ListExtension
+    {
+        public static List<List<T>> SplitBlock<T>(this List<T> source, int blcokNum)
+        {
+            if (blcokNum < 1)
+            {
+                throw new Exception($"{nameof(blcokNum)}必须大于0");
+            }
+            List<List<T>> result = new List<List<T>>();
+            var group = source.Count / Math.Abs(blcokNum);
+            var modValue = source.Count % Math.Abs(blcokNum);
+
+            for (int i = 0; i < group; i++)
+            {
+                result.Add(new List<T>(source.GetRange(blcokNum * i, blcokNum)));
+            }
+            List<T> useLast = null;
+            if (modValue < (int)Math.Ceiling(blcokNum / 2d))
+            {
+                var last = result.LastOrDefault();
+                if (last == null)
+                {
+                    last = new List<T>();
+                    result.Add(last);
+                }
+                useLast = last;
+            }
+            else
+            {
+                var newList = new List<T>();
+                result.Add(newList);
+                useLast = newList;
+            }
+            useLast.AddRange(source.GetRange(group * blcokNum, modValue));
+            return result;
+
+        }
+    }
+}
+

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

@@ -316,6 +316,7 @@
     <Compile Include="Extend\FilePathExt.cs" />
     <Compile Include="Extend\IEnumerableExtensions.cs" />
     <Compile Include="Extend\JObjectExt.cs" />
+    <Compile Include="Extend\ListExtension.cs" />
     <Compile Include="Extend\ObjectExtend.cs" />
     <Compile Include="Extend\ObservableCollectionExtension.cs" />
     <Compile Include="Extend\PropertyInfoExtend.cs" />

+ 15 - 4
MBI/SAGA.GplotManage/RelationManager/RelationUploader.cs

@@ -7,6 +7,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using SAGA.DotNetUtils.Extend;
 
 namespace SAGA.GplotManage
 {
@@ -72,10 +73,20 @@ namespace SAGA.GplotManage
             #endregion
             if (realtionItems!=null&&realtionItems.Any())
             {
-                var jarry = JArray.FromObject(realtionItems);
-                JObject jobject = new JObject();
-                jobject.Add("criterias", jarry);
-                var result=RelationRequest.AddRelation(jobject);
+                var blocks = realtionItems.SplitBlock(1000);
+                foreach (var block in blocks)
+                {
+                    //var jarry = JArray.FromObject(realtionItems);
+                    var jarry = JArray.FromObject(block);
+                    JObject jobject = new JObject();
+                    jobject.Add("criterias", jarry);
+                    var result = RelationRequest.AddRelation(jobject);
+                    if (!result)
+                    {
+                        throw new Exception("创建关系失败");
+                    }
+                }
+               
             }
 
         }

+ 42 - 13
MBI/SAGA.GplotManage/TopologyApplicationCommand.cs

@@ -20,6 +20,7 @@ using SAGA.GplotManage.TopologyApplication;
 using SAGA.GplotRelationComputerManage;
 using SAGA.RevitUtils;
 using SAGA.RevitUtils.Extends;
+using SAGA.RevitUtils.Utils;
 
 namespace SAGA.GplotManage
 {
@@ -60,25 +61,53 @@ namespace SAGA.GplotManage
 
         public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
         {
-            //MessageShow.Infomation(Thread.CurrentThread.ManagedThreadId.ToString());
-            ComputerSpaceItem space1 =
-                new ComputerSpaceItem(ExternalDataWrapper.Current.Doc.GetElement(960127) as Space);
-            ComputerSpaceItem space2 =
-                new ComputerSpaceItem(ExternalDataWrapper.Current.Doc.GetElement(961500) as Space);
-            if (ClosedIntersect(space1.ZeroCurves, space2.ZeroCurves))
-            {
 
+            if (!MessageShowBase.Confirm("确定执行所选命令"))
+            {
+                return Result.Succeeded;
             }
+            SpaceAirSupplyHandler.ShellExecute();
+            MessageShow.Infomation("完成");
+            return Result.Succeeded;
+        }
 
-            //if (!MessageShowBase.Confirm("确定执行所选命令"))
+       
+    }
+
+    public class Test
+    {
+        public static void TestSpace()
+        {
+            var useDocument = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(
+                @"D:\线上项目\Pj4201050001\Bd4201050001a2412bfbd10d11e8a471a5ff43d8e564\Fl4201050001afd0f3e3dce811e8a553f5b22da96b1b.rvt");
+            ComputerSpaceItem space1 =
+                new ComputerSpaceItem(useDocument.Document.GetElement(964793) as Space);
+            ComputerSpaceItem spaceT3 =
+                new ComputerSpaceItem(useDocument.Document.GetElement(964781) as Space);
+            ComputerSpaceItem spaceT4 =
+                new ComputerSpaceItem(useDocument.Document.GetElement(964782) as Space);
+            ComputerSpaceItem spaceT5 =
+                new ComputerSpaceItem(useDocument.Document.GetElement(964987) as Space);
+            //九层数据
+            useDocument = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(
+                @"D:\线上项目\Pj4201050001\Bd4201050001a2412bfbd10d11e8a471a5ff43d8e564\Fl42010500016dc07b43dcf111e8a553e7c23f5c005c.rvt");
+            ComputerSpaceItem space2 =
+                new ComputerSpaceItem(useDocument.Document.GetElement(961500) as Space);
+            ComputerSpaceItem space9LT4 =
+                new ComputerSpaceItem(useDocument.Document.GetElement(960076) as Space);
+            //if (ClosedIntersect(space1.ZeroCurves, space2.ZeroCurves))
             //{
-            //    return Result.Succeeded;
+
             //}
-            //SpaceAirSupplyHandler.ShellExecute();
-            //MessageShow.Infomation("完成");
-            return Result.Succeeded;
+            //false
+            var result1 = PolygonUtil.IsIntersection(space2.Annular, space1.Annular);
+            //false
+            var result2 = PolygonUtil.IsIntersection(space9LT4.Annular, spaceT3.Annular);
+            //true
+            var result3 = PolygonUtil.IsIntersection(space9LT4.Annular, spaceT4.Annular);
+            //false
+            var result4 = PolygonUtil.IsIntersection(space9LT4.Annular, spaceT5.Annular);
         }
-
         public bool ClosedIntersect(List<Curve> closed1, List<Curve> closed2)
         {
             //判断所有的线是否有相交

+ 61 - 1
MBI/SAGA.GplotRelationComputerManage/SpaceRelation/ComputerSpaceItem.cs

@@ -15,6 +15,7 @@ using Autodesk.Revit.DB.Mechanical;
 using SAGA.DotNetUtils.Extend;
 using SAGA.RevitUtils;
 using SAGA.RevitUtils.Extends;
+using SAGA.RevitUtils.Utils;
 
 namespace SAGA.GplotRelationComputerManage
 {
@@ -32,11 +33,70 @@ namespace SAGA.GplotRelationComputerManage
             var seg = mySegments.FirstOrDefault();
             if (seg != null)
             {
-                this.OriginCurves = mySegments[0].Select(s => s.GetCurve()).ToList();
+                this.OriginCurves = seg.Select(s => s.GetCurve()).ToList();
             
             }
             this.ZeroCurves = TransfomCurvesToZero(OriginCurves);
+            Annular = InitAnnular(mySegments);
+
+        }
+
+        #region 存储逆时针多边形
+        //private Annular m_Annular;
+        /// <summary>
+        /// 轮廓环形
+        /// </summary>
+        public Annular Annular { get; set; }
+
+        private Annular InitAnnular(IList<IList<BoundarySegment>> segmentsList)
+        {
+            Annular annumlar = null;
+            for (int i = 0; i < segmentsList.Count; i++)
+            {
+                var currentSegments = segmentsList[i];
+                bool useSegments = false;
+                var usePoints = new List<XYZ>();
+                foreach (var boundarySegment in currentSegments)
+                {
+                    if (!useSegments && !(this.Space.Document.GetElement(boundarySegment.ElementId) is FamilyInstance))
+                    {
+                        //如果边框都是由柱子组成,则不进行存储
+                        useSegments = true;
+                    }
+                    var curve = boundarySegment.GetCurve();
+                    var tempPoints = curve.Tessellate();
+                    //取出除最后一点外的所有点
+                    for (int j = 0; j < tempPoints.Count-1; j++)
+                    {
+                        usePoints.Add(tempPoints[j].NewZ(0));
+                    }
+                }
+                if (!useSegments)
+                    continue;
+                if (i == 0)
+                {
+                    #region 外轮廓处理,默认逆时针
+
+                    annumlar = new Annular(new Polygon(usePoints));
+
+                    #endregion
+                }
+                else
+                {
+                    #region 内轮廓处理,默认顺时针。转成逆时针
+
+                    if (annumlar != null)
+                    {
+                        usePoints.Reverse();
+                        annumlar.InPolygons.Add(new Polygon(usePoints));
+                    }
+                    #endregion
+                }
+            }
+            return annumlar;
         }
+        #endregion
+
         public Space Space { get; private set; }
         /// <summary>
         /// bimId

+ 6 - 3
MBI/SAGA.GplotRelationComputerManage/SpaceRelation/FloorSpaceItems.cs

@@ -20,6 +20,7 @@ using SAGA.MBI.Model;
 using SAGA.Models;
 using SAGA.RevitUtils;
 using SAGA.RevitUtils.Extends;
+using SAGA.RevitUtils.Utils;
 
 namespace SAGA.GplotRelationComputerManage
 {
@@ -575,11 +576,13 @@ namespace SAGA.GplotRelationComputerManage
             {
                 return result;
             }
-            if (aFSpace.BimId == "Fl42010500016dc07b43dcf111e8a553e7c23f5c005c:961500" && bSpace.BimId == "Fl4201050001afd0f3e3dce811e8a553f5b22da96b1b:964782")
+
+            if (aFSpace.Annular == null || bSpace.Annular == null)
             {
-                MessageShow.Infomation("端点");
+                return result;
             }
-            if (ClosedIntersect(aFSpace.ZeroCurves, bSpace.ZeroCurves))
+            //if (ClosedIntersect(aFSpace.ZeroCurves, bSpace.ZeroCurves))
+            if (PolygonUtil.IsIntersection(aFSpace.Annular, bSpace.Annular))
             {
                 result = AdjanceElementType.Vertical;
                 if (SpaceComputerManager.IsCrossFunType(aFSpace.FuncType) && SpaceComputerManager.IsCrossFunType(bSpace.FuncType))

+ 133 - 14
MBI/SAGA.RevitUtils/Extends/XYZExtend.cs

@@ -6,6 +6,7 @@ using Autodesk.Revit.DB;
 using SAGA.DotNetUtils;
 using SAGA.DotNetUtils.Extend;
 using SAGA.RevitUtils.Infrastructure;
+using SAGA.RevitUtils.Utils;
 using Point = System.Windows.Point;
 
 namespace SAGA.RevitUtils.Extends
@@ -1570,11 +1571,14 @@ namespace SAGA.RevitUtils.Extends
         /// <returns></returns>
         public static bool PointInPolygon(this XYZ pt, IList<Curve> listProfile)
         {
-            if (!pt.PointInPoly1(listProfile))
-            {
-                return pt.PointInPoly2(listProfile.ToList<Curve>());
-            }
-            return true;
+            var flag = true;
+            //if (!pt.PointInPoly1(listProfile))
+            //{
+            //    flag = pt.PointInPoly2(listProfile.ToList<Curve>());
+            //}
+            //点在边框上,也要判定为在多边形内部
+            flag = pt.PointInPolygonByRay(listProfile.OfType<Line>().ToList())>=0;
+            return flag;
         }
 
         /// <summary>
@@ -1664,22 +1668,137 @@ namespace SAGA.RevitUtils.Extends
             }
             return true;
         }
+
         /// <summary>
-        /// (1,2,3)转化为XYZ
+        /// 通过射线法判断点是否在封闭区域内
         /// </summary>
-        /// <param name="str"></param>
+        /// <param name="inputPoint"></param>
+        /// <param name="lines"></param>
         /// <returns></returns>
-        public static XYZ StrToXyz(this string str)
+        public static int PointInPolygonByRay(this XYZ inputPoint, List<Line> lines)
         {
-            XYZ xyz = null;
-            Regex regex = new Regex(@"\((-?\d+\.?\d+),\s*(-?\d+\.?\d+),\s*(-?\d+\.?\d+)\)");
-            var matches = regex.Match(str);
+            #region 描述
+            /*
+             * 判断点是否在直线所围成的区域内;
+             * 结果三种,-1,在外侧;0,在边上,1,在多边形内
+             * 判断焦点奇偶
+             * 如果交点是线段的端点,则记录这个点的信息,同一个交点算一次焦点。
+             * 如果线段恰巧和射线共线,如果点在射线中,则记录一个点。否则该记录几个点,就记录几个点;
+             * 这个不考虑阿拉伯数字⑧字形这种种,轮廓线有非端点相交情况,这种情况需要记录焦点的具体值
+             */
+            #endregion
+            //以给定点,向x正方向做射线
+            //线段端点在射线上的集合
+            List<XYZ> points = new List<XYZ>();
+            //默认是偶数
+            bool isEven = true;
+            double baseX = inputPoint.X;
+            double baseY = inputPoint.Y;
+            foreach (var line in lines)
+            {
+                var start = line.StartPoint();
+                var end = line.EndPoint();
+                if (start.IsEqual(inputPoint) || end.IsEqual(inputPoint))
+                {
+                    return 0;
+                }
+                //判断给定线的端点是否在射线两侧,利用水平线的性质
+                if ((start.Y.IsLessEq(baseY) && baseY.IsLessEq(end.Y)) || (end.Y.IsLessEq(baseY) && baseY.IsLessEq(start.Y)))
+                {
+                    double minX = Math.Min(start.X, end.X);
+                    double maxX = Math.Min(start.X, end.X);
+                    if (start.Y.IsEqual(end.Y))
+                    {
+                        #region 与给定射线共线处理                 
+                        //给定线段与射线平行
+                        if (minX.IsLessEq(baseX) && baseX.IsLessEq(maxX))
+                        {
+                            return 0;
+                        }
+                        else if (baseX.IsLess(minX))
+                        {
+                            //凸字形形状
+                            //记录射线的两个交点
+                            points.Add(start);
+                            points.Add(end);
+                            #region 与射线共线处理
+                            List<Line> useLines = new List<Line>(lines);
+                            useLines.Remove(line);
+                            var extendStart = LineUtil.GetFirstPoint(useLines, start, p => !p.Y.IsEqual(start.Y));
+                            var extendEnd = LineUtil.GetFirstPoint(useLines, end, p => !p.Y.IsEqual(end.Y));
+                            if (extendStart.Y.IsLess(baseY) == extendEnd.Y.IsThan(baseY))
+                            {
+                                if (!extendStart.Y.IsEqual(baseY) && !extendEnd.Y.IsEqual(baseY))
+                                {
+                                    isEven = !isEven;
+                                }
+                            } 
+                            #endregion
+                        }
+                        #endregion
+                    }
+                    else if (baseX.IsLessEq(maxX))
+                    {
+                        //当给定线,小于等于线最大坐标时,才有可能相交                      
+                        /*
+                         * p1(x1,x2)  vecter(xv,yv)
+                         * x1+xv*c=x
+                         * y1+yv*c=y
+                         * 求出c,带入公式1
+                         */
+                        double c = (baseY - start.Y) / (end.Y - start.Y);
+                        double useX = start.X + c * (end.X - start.X);
+                        if (useX.IsEqual(baseX))
+                        {
+                            //给定点,在线上
+                            return 0;
+                        }
+                        if (baseX.IsLessEq(useX))
+                        {
+                            //这种情况下肯定相交
+                            var intersectionPoint = new XYZ(useX, baseY,0);
+                            if (start.IsEqual(intersectionPoint))
+                            {
+                                points.Add(start);
+                            }
+                            else if (end.IsEqual(intersectionPoint))
+                            {
+                                points.Add(end);
+                            }
+                            else
+                            {
+                                isEven = !isEven;
+                            }
+                        }
+                    }
 
-            if (matches.Success)
+                }
+            }
+            //整理通过的端点
+            var validPoints = points.Distinct(new XyzEqualComparer());
+            if (validPoints.Count() % 2 == 1)
+            {
+                isEven = !isEven;
+            }
+            return isEven ? -1 : 1;
+        }
+
+        /// <summary>
+        /// 通过射线法判断点是否在封闭区域内
+        /// </summary>
+        /// <param name="inputPoint"></param>
+        /// <param name="points"></param>
+        /// <returns></returns>
+        public static int PointInPolygonByRay(this XYZ inputPoint, List<XYZ> points)
+        {
+            List<Line> lines = new List<Line>();
+            for (int i = 0; i < points.Count; i++)
             {
-                xyz= new XYZ((matches.Groups[0].Value).ToDouble(), (matches.Groups[1].Value).ToDouble(), (matches.Groups[2].Value).ToDouble());
+                var start = points[i];
+                var end = points[(i + 1) % points.Count];
+                lines.Add(Line.CreateBound(start, end));
             }
-            return xyz;
+            return PointInPolygonByRay(inputPoint, lines);
         }
     }
 }

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

@@ -302,6 +302,13 @@
     <Compile Include="RevitHelper.cs" />
     <Compile Include="Service\IInputService.cs" />
     <Compile Include="StatisticsWireInfor.cs" />
+    <Compile Include="Utils\Annular.cs" />
+    <Compile Include="Utils\AxisRange.cs" />
+    <Compile Include="Utils\LineUtil.cs" />
+    <Compile Include="Utils\OutlineUtil.cs" />
+    <Compile Include="Utils\Polygon.cs" />
+    <Compile Include="Utils\PolygonUtil.cs" />
+    <Compile Include="Utils\VectorUtil.cs" />
     <Compile Include="Version\DocumentVersionManager.cs" />
     <Compile Include="Windows\CommandInfo.cs" />
     <Compile Include="Windows\CommandQueue.cs" />

+ 36 - 0
MBI/SAGA.RevitUtils/Utils/Annular.cs

@@ -0,0 +1,36 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:Annular
+ * 作者:xulisong
+ * 创建时间: 2019/4/30 10:37:30
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SAGA.RevitUtils.Utils
+{
+    /// <summary>
+    /// 环状结构
+    /// </summary>
+    public class Annular
+    {
+        public Annular(Polygon outPolygon)
+        {
+            OutPolygon = outPolygon;
+            InPolygons = new List<Polygon>();
+        }
+        /// <summary>
+        /// 外轮廓
+        /// </summary>
+        public Polygon OutPolygon { get; private set; }
+
+        /// <summary>
+        /// 内轮廓集合(外部可修改,现在暂时不做限定)
+        /// </summary>
+        public List<Polygon> InPolygons { get; private set; }
+    }
+}

+ 60 - 0
MBI/SAGA.RevitUtils/Utils/AxisRange.cs

@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:AxisRange
+ * 作者:xulisong
+ * 创建时间: 2019/4/29 17:45:45
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SAGA.DotNetUtils.Extend;
+
+namespace SAGA.RevitUtils.Utils
+{
+    /// <summary>
+    /// 轴数据范围
+    /// </summary>
+    public class AxisRange
+    {
+        /*
+         * 以后有时间续写
+         */
+        public AxisRange(double min, double max)
+        {
+            Min = min;
+            Max = max;
+        }
+        public double Max { get; private set; }
+        public double Min { get; private set; }
+
+        /// <summary>
+        /// 检测两个range是否相交
+        /// </summary>
+        /// <param name="range"></param>
+        /// <returns>-1,无重叠;0,端点相邻。1有重叠</returns>
+        public int IntersectionTest(AxisRange range)
+        {
+            var length1 = Math.Abs(Max - Min);
+            var length2 = Math.Abs(range.Max - range.Min);
+            List<double> values = new List<double>() { Max, Min, range.Max, range.Min };
+            values.Sort();
+            var totalLength = Math.Abs(values[values.Count - 1] - values[0]);
+            var splitTotal = length1 + length2;
+            if (totalLength.IsEqual(splitTotal))
+            {
+                return 0;
+            }
+            else if (totalLength.IsThan(splitTotal))
+            {
+                return -1;
+            }
+            else
+            {
+                return 1;
+            }
+        }
+    }
+}

+ 85 - 0
MBI/SAGA.RevitUtils/Utils/LineUtil.cs

@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:LineUtil
+ * 作者:xulisong
+ * 创建时间: 2019/4/29 8:49:52
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SAGA.RevitUtils.Extends;
+
+namespace SAGA.RevitUtils.Utils
+{
+    public static class LineUtil
+    {
+        /// <summary>
+        /// 获取点在当前线的位置
+        /// </summary>
+        /// <param name="line"></param>
+        /// <param name="point"></param>
+        /// <returns>-1不在线上,0在开始点,1在结束点</returns>
+        public static int GetPosition(Line line, XYZ point)
+        {
+            if (line.StartPoint().IsEqual(point))
+            {
+                return 0;
+            }
+            else if (line.EndPoint().IsEqual(point))
+            {
+                return 1;
+            }
+            else
+            {
+                return -1;
+            }
+        }
+
+        /// <summary>
+        /// 获取第一个满足条件的点,如果没有找到返回本身
+        /// </summary>
+        /// <param name="lines"></param>
+        /// <param name="start"></param>
+        /// <param name="breakCondition"></param>
+        /// <returns></returns>
+        public static XYZ GetFirstPoint(List<Line> lines, XYZ start, Func<XYZ, bool> breakCondition)
+        {
+            List<Line> useLines = new List<Line>();
+            var usePoint = start;
+            bool isFind = false;
+            do
+            {
+                isFind = false;
+                for (int i = 0; i < lines.Count; i++)
+                {
+                    var tempLine = lines[i];
+                    if (useLines.Any(e => e == tempLine))
+                    {
+                        continue;
+                    }
+                    var flag = LineUtil.GetPosition(tempLine, usePoint);
+                    if (flag == -1)
+                    {
+                        continue;
+                    }
+                    isFind = true;
+                    if (flag == 0)
+                    {
+                        usePoint = tempLine.EndPoint();
+                    }
+                    else if (flag == 1)
+                    {
+                        usePoint = tempLine.StartPoint();
+                    }
+                    useLines.Add(tempLine);
+                    break;
+                }
+            } while (isFind && !breakCondition(usePoint));
+            return usePoint;
+        }
+    }
+}

+ 66 - 0
MBI/SAGA.RevitUtils/Utils/OutlineUtil.cs

@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:OutlineUtil
+ * 作者:xulisong
+ * 创建时间: 2019/4/30 10:32:48
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SAGA.DotNetUtils.Extend;
+
+namespace SAGA.RevitUtils.Utils
+{
+    public class OutlineUtil
+    {
+        /// <summary>
+        /// 创建二维包围盒
+        /// </summary>
+        /// <param name="points"></param>
+        /// <returns></returns>
+        public static Outline CreateBox(List<XYZ> points)
+        {
+            double minX = 0, minY = 0, maxX = 0, maxY = 0;
+            for (int i = 0; i < points.Count - 1; i++)
+            {
+                var usePoint = points[i];
+                if (i == 0)
+                {
+                    #region 初始基准
+                    minX = usePoint.X;
+                    maxX = usePoint.X;
+                    minY = usePoint.Y;
+                    maxY = usePoint.Y;
+                    #endregion
+                }
+                else
+                {
+                    #region 核心处理
+                    if (usePoint.X.IsLess(minX))
+                    {
+                        minX = usePoint.X;
+                    }
+                    else if (usePoint.X.IsThan(maxX))
+                    {
+                        maxX = usePoint.X;
+                    }
+
+                    if (usePoint.Y.IsLess(minY))
+                    {
+                        minY = usePoint.Y;
+                    }
+                    else if (usePoint.Y.IsThan(maxY))
+                    {
+                        maxY = usePoint.Y;
+                    }
+                    #endregion
+                }
+            }
+            return new Outline(new XYZ(minX, minY,0), new XYZ(maxX, maxY, 0));
+        }
+    }
+}

+ 86 - 0
MBI/SAGA.RevitUtils/Utils/Polygon.cs

@@ -0,0 +1,86 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:Polygon
+ * 作者:xulisong
+ * 创建时间: 2019/4/29 17:37:09
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Autodesk.Revit.DB;
+using SAGA.RevitUtils.Extends;
+
+namespace SAGA.RevitUtils.Utils
+{
+    public class Polygon : IEnumerable<XYZ>
+    {
+        private List<XYZ> m_Points;
+        public Polygon(List<XYZ> points)
+        {
+            if (points.Count < 3)
+            {
+                throw new ArgumentException($"{nameof(points)}数量不能小于3");
+            }
+            m_Points = (points ?? new List<XYZ>()).Select(xyz=>xyz.NewZ()).ToList();
+            Points = new ReadOnlyCollection<XYZ>(m_Points);
+        }
+        /// <summary>
+        /// 关联逆时针点(最后一个点和第一个点封闭)
+        /// </summary>
+        public ReadOnlyCollection<XYZ> Points { get; private set; }
+
+        #region 实现遍历方法
+        public IEnumerator<XYZ> GetEnumerator()
+        {
+            return ((IEnumerable<XYZ>)m_Points).GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return ((IEnumerable<XYZ>)m_Points).GetEnumerator();
+        }
+        #endregion
+
+        #region 子凸多边形
+        private ReadOnlyCollection<Polygon> m_ChildrenConvexPolygons;
+        /// <summary>
+        /// 分解的子凸多边形
+        /// </summary>
+        public ReadOnlyCollection<Polygon> ChildrenConvexPolygons
+        {
+            get
+            {
+                if (m_ChildrenConvexPolygons == null)
+                {
+                    var polygons = PolygonUtil.SplitToConvexPolygons(this);
+                    m_ChildrenConvexPolygons = new ReadOnlyCollection<Polygon>(polygons);
+                }
+                return m_ChildrenConvexPolygons;
+            }
+        }
+        #endregion
+
+        private Outline m_Box;
+        /// <summary>
+        /// 多边形包围盒
+        /// </summary>
+        public Outline Box
+        {
+            get
+            {
+                if (m_Box == null)
+                {
+                    m_Box = OutlineUtil.CreateBox(this.m_Points);
+                }
+
+                return m_Box;
+            }
+        }
+       
+    }
+}

+ 269 - 0
MBI/SAGA.RevitUtils/Utils/PolygonUtil.cs

@@ -0,0 +1,269 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:PolygonUtil
+ * 作者:xulisong
+ * 创建时间: 2019/4/29 17:36:49
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Autodesk.Revit.DB;
+using SAGA.DotNetUtils.Extend;
+using SAGA.RevitUtils.Extends;
+
+namespace SAGA.RevitUtils.Utils
+{
+    /// <summary>
+    /// 多边形相关算法
+    /// </summary>
+    public class PolygonUtil
+    {
+        public static List<Polygon> SplitToConvexPolygons(Polygon polygon)
+        {
+            List<Polygon> polygons = new List<Polygon>();
+            List<Polygon> tempPolygons = new List<Polygon>() { polygon };
+            for (int i = 0; i < tempPolygons.Count; i++)
+            {
+                var childPolygons = SplitPolygons(tempPolygons[i]);
+                if (childPolygons.Count == 1)
+                {
+                    polygons.AddRange(childPolygons);
+                }
+                else
+                {
+                    tempPolygons.AddRange(childPolygons);
+                }
+            }
+            return polygons;
+        }
+        /// <summary>
+        /// 分割多边形
+        /// </summary>
+        /// <param name="polygon"></param>
+        /// <returns>如果是凹多边形,则返回多个。如果是凸多边形则返回一个本身</returns>
+        private static List<Polygon> SplitPolygons(Polygon polygon)
+        {
+            /*
+             * 循环末尾最后一条边需不需要判定。应该可以忽略
+             */
+            if (polygon.Points.Count == 3)
+            {
+                return new List<Polygon>() { polygon };
+            }
+            var basePoints = polygon.Points;
+            #region 找到多边形中,y值最小的点
+            var bottomPoint = basePoints[0];
+            var bottomPointIndex = 0;
+            for (int i = 1; i < basePoints.Count; i++)
+            {
+                var usePoint = basePoints[i];
+                if (usePoint.Y.IsLess(bottomPoint.Y))
+                {
+                    bottomPoint = usePoint;
+                    bottomPointIndex = i;
+                }
+            }
+            #endregion
+            var totalPoint = basePoints.Count;
+            #region 整理新的集合,以y值最小点为起点遍历
+            List<XYZ> newPoints = new List<XYZ>();
+            for (int i = 0; i < totalPoint; i++)
+            {
+                var useIndex = (bottomPointIndex + i) % totalPoint;
+                newPoints.Add(basePoints[useIndex]);
+            }
+            #endregion
+
+            for (int i = 0; i < totalPoint - 1; i++)
+            {
+                var start = newPoints[i];
+                var end = newPoints[i + 1];
+                var baseVector = end - start;
+                bool needSplit = false;
+                int splitStart = -1, splitEnd = -1;
+                for (int num = 0; num < totalPoint - 2; num++)
+                {
+                    var useIndex = (i + 2 + num) % totalPoint;
+                    var judgePoint = newPoints[useIndex];
+                    var refVector = judgePoint - end;
+                    //三维立面,判断叉乘的正负,比较叉乘结果的Z值
+                    if (!needSplit && baseVector.CrossProduct( refVector).Z.IsLess(0))
+                    {
+                        //出现拐点,分割多边形.使用拐点加上拐点前后构成一个三角形
+                        needSplit = true;
+                        splitStart = (useIndex - 1);
+                        if (splitStart < 0)
+                        {
+                            splitStart = totalPoint - 1;
+                        }
+                        continue;
+                    }
+                    if (needSplit && baseVector.CrossProduct(refVector).Z.IsThanEq(0))
+                    {
+                        splitEnd = useIndex;
+                        break;
+                    }
+                }
+                if (needSplit)
+                {
+                    List<XYZ> aPoints = new List<XYZ>();
+                    List<XYZ> bPoints = new List<XYZ>();
+                    if (splitEnd == -1)
+                    {
+                        splitEnd = (splitStart + 2) % totalPoint;
+                    }
+                    if (splitEnd < splitStart)
+                    {
+                        splitEnd += totalPoint;
+                    }
+                    int num = Math.Abs(splitEnd - splitStart) + 1;
+                    for (int index = 0; index < num; index++)
+                    {
+                        aPoints.Add(newPoints[(splitStart + index) % totalPoint]);
+                    }
+                    for (int index = 0; index < (totalPoint - num + 2); index++)
+                    {
+                        bPoints.Add(newPoints[(splitEnd + index) % totalPoint]);
+                    }
+                    List<Polygon> polygons = new List<Polygon>();
+                    polygons.Add(new Polygon(aPoints));
+                    polygons.Add(new Polygon(bPoints));
+                    return polygons;
+                }
+            }
+            return new List<Polygon>() { polygon };
+        }
+        /// <summary>
+        /// 判断两个凸多边形是否相交
+        /// </summary>
+        /// <param name="polygon1"></param>
+        /// <param name="polygon2"></param>
+        /// <returns></returns>
+        public static bool IsConvexIntersection(Polygon polygon1, Polygon polygon2)
+        {
+            /*
+             * 分离轴方法;
+             * 以两个多边形的边的法线为轴做投影。
+             * 如果存在一条轴中投影没有重叠,则两个凸多边形不相交
+             */
+            List<XYZ> useVectors = new List<XYZ>();
+            List<List<XYZ>> pointsCollection = new List<List<XYZ>>()
+                {polygon1.Points.ToList(), polygon2.Points.ToList()};
+            foreach (var points in pointsCollection)
+            {
+                for (int i = 0; i < points.Count; i++)
+                {
+                    var start = points[i];
+                    var end = points[(i + 1) % points.Count];
+                    var baseDirection = end - start;
+                    if (baseDirection.GetLength().IsZero())
+                    {
+                        continue;
+                    }
+                    baseDirection.Normalize();
+                    var crossDirection = new XYZ(baseDirection.Y, -baseDirection.X,0);
+                    if (useVectors.Any(v => VectorUtil.IsParallel(v, crossDirection)))
+                    {
+                        continue;
+                    }
+                    //到指定轴的投影区域
+                    var range1 = VectorUtil.CalcProjectRange(crossDirection, pointsCollection[0]);
+                    var range2 = VectorUtil.CalcProjectRange(crossDirection, pointsCollection[1]);
+                    //大于0,才算有重叠
+                    useVectors.Add(crossDirection);
+                    if (range1.IntersectionTest(range2) < 1)
+                    {
+                        //如果存在分离轴,则图形不相交
+                        return false;
+                    }
+
+                }
+            }
+
+            return true;
+        }
+
+
+        /// <summary>
+        /// 判断两个多边形是否相交
+        /// </summary>
+        /// <param name="polygon1"></param>
+        /// <param name="polygon2"></param>
+        /// <returns></returns>
+        public static bool IsIntersection(Polygon polygon1, Polygon polygon2)
+        {
+            if (!polygon1.Box.Intersects(polygon2.Box, 0))
+            {
+                return false;
+            }
+            /*
+             * 分离轴方法
+             */
+            var polygonCollection1 = polygon1.ChildrenConvexPolygons;// SplitToConvexPolygons(polygon1);
+            var polygonCollection2 = polygon2.ChildrenConvexPolygons;//SplitToConvexPolygons(polygon2);
+            foreach (var outPolygon in polygonCollection1)
+            {
+                foreach (var inPolygon in polygonCollection2)
+                {
+                    if (IsConvexIntersection(outPolygon, inPolygon))
+                    {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// 判断annular1,是否在annular2的内轮廓中
+        /// </summary>
+        /// <param name="annular1"></param>
+        /// <param name="annular2"></param>
+        /// <returns></returns>
+        public static bool IsInInnerPolygon(Annular annular1, Annular annular2)
+        {
+            var out1 = annular1.OutPolygon;
+            var inPolygon2 = annular2.InPolygons;
+            foreach (var polygon in inPolygon2)
+            {
+                if (IsIntersection(polygon, out1))
+                {
+                    var pointList = polygon.ToList();
+                    if (out1.All(p => p.PointInPolygonByRay(pointList) > -1))
+                    {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        /// <summary>
+        /// 判断两个多边形是否相交
+        /// </summary>
+        /// <param name="annular1"></param>
+        /// <param name="annular2"></param>
+        /// <returns></returns>
+        public static bool IsIntersection(Annular annular1, Annular annular2)
+        {
+            /*
+             * 分离轴方法
+             */
+            var out1 = annular1.OutPolygon;
+            var out2 = annular2.OutPolygon;
+            if (IsIntersection(out1, out2))
+            {
+                //如果相交,检测内轮廓关系,判断是否真实相交
+                if (IsInInnerPolygon(annular1, annular2) || IsInInnerPolygon(annular2, annular1))
+                {
+                    return false;
+                }
+                return true;
+            }
+            return false;
+        }
+    }
+}

+ 67 - 0
MBI/SAGA.RevitUtils/Utils/VectorUtil.cs

@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ * 功能描述:VectorUtil
+ * 作者:xulisong
+ * 创建时间: 2019/4/29 17:45:02
+ * 版本号:v1.0
+ *  -------------------------------------------------------------------------*/
+
+using Autodesk.Revit.DB;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using SAGA.DotNetUtils.Extend;
+using Point = Autodesk.Revit.DB.Point;
+
+namespace SAGA.RevitUtils.Utils
+{
+    public class VectorUtil
+    {
+        public static bool IsParallel(XYZ vector1, XYZ vector2)
+        {
+            return vector1.CrossProduct(vector2).GetLength().IsZero();
+        }
+        /// <summary>
+        /// 计算点集合到基础向量的投影区域
+        /// </summary>
+        /// <param name="vector"></param>
+        /// <param name="points"></param>
+        /// <returns>Item1为最大值,Item2为最小值</returns>
+        public static AxisRange CalcProjectRange(XYZ vector, List<XYZ> points)
+        {
+            if (points == null || !points.Any())
+            {
+                throw new ArgumentException($"{nameof(points)}必须包含点");
+            }
+
+            if (vector.GetLength().IsZero())
+            {
+                throw new ArgumentException($"{nameof(vector)}基准向量不能为零向量");
+            }
+            if (!vector.GetLength().IsEqual(1))
+            {
+                vector.Normalize();
+            }
+
+            double min = double.MaxValue, max = double.MinValue;
+            for (int i = 0; i < points.Count; i++)
+            {
+                var usePoint = points[i];
+                var useVector = usePoint - new XYZ(0, 0,0);
+                var dotValue = useVector.DotProduct(vector);
+                if (dotValue.IsLess(min))
+                {
+                    min = dotValue;
+                }
+                if (dotValue.IsThan(max))
+                {
+                    max = dotValue;
+                }
+            }
+
+            return new AxisRange(min, max);
+        }
+    }
+}