按交点分组任意数量的多边形 - C#

时间:2017-03-19 16:26:55

标签: c# linq

我有多个多边形列表,每个多边形代表一个物理对象。例如:

List<CurveLoop> A可以代表一个带孔的矩形。此列表中的一条曲线是矩形的轮廓,另一条曲线是孔。

我想要一个返回列表列表的方法,其中每个列表包含所有相交的对象。

我已经有一个方法可以返回两个对象是否相交:

bool _CurveLoopsIntersect(List<CurveLoop> curveLoopsA, List<CurveLoop> curveLoopsB) {...}

如果两个列表中的任何两条曲线都接触,

将返回true。

以下是我到目前为止的代码,但它只给了我一次通过。我想我需要多次传递,所以如果对象A和B相交,而B和C相交,那么它们将形成集合{A,B,C}。我需要任意数量的通道,有时对象根本不会相交,或者是不同集合的一部分,例如{A,B,C}和{D,E}和{F}。

public List<CurveLoop> _MergeCurveLoops(List<List<CurveLoop>> elementCurveLoops, View view)
{
    // ...
    // Preprocessing

    var listOfLists = new List<List<CurveLoop>>();
    foreach (var elementCurveLoop in elementCurveLoops)
    {
        var newList = elementCurveLoops.FindAll(x => _CurveLoopsIntersect(x, elementCurveLoop));
        listOfLists.Add(newList);
    }
}


private bool _CurveLoopsIntersect(List<CurveLoop> curveLoopsA, List<CurveLoop> curveLoopsB)
{
    foreach (var curveLoopA in curveLoopsA)
    {
        foreach (var curveA in curveLoopA)
        {
             foreach (var curveLoopB in curveLoopsB)
             {
                 foreach (var curveB in curveLoopB)
                     {
                     var result = curveA.Intersect(curveB);

                     if (result == SetComparisonResult.Overlap ||
                         result == SetComparisonResult.Subset ||
                         result == SetComparisonResult.Superset ||
                         result == SetComparisonResult.Equal)
                     {
                         return true;
                     }
                 }
             }
         }
     }
     return false;
}

2 个答案:

答案 0 :(得分:2)

这可以使用像这个psuedu

这样的代码来实现
import scalaz._
import Scalaz._

type EitherTH[F[_], A] = EitherT[F, Throwable,A]
type StateTH[F[_], A] = StateT[F, String, A]
type StateTList[A] = StateTH[List, A]
type EitherTStateTList[A] = EitherTH[StateTList, A]
val lst = List(1,2,3,4)

def checkNum(x:Int)(implicit ms:MonadState[EitherTStateTList, Int]) = if ((x%2)==0) {
  put(s"Error: $x")
  -\/(new Throwable())
}  else {
   put("")
   \/-(x)
}  

val prg = for {
  x <- lst.liftM[StateTH].liftM[EitherTH]
  // y <- checkNum(x).liftM[EitherTH]
} yield y 

prg.run("")

}

答案 1 :(得分:0)

谢谢,你让我朝着正确的方向前进。你是对的,使用Set是正确的方法。我将一个集合与递归函数结合使用(类似于你的while循环)。

我写的代码如下:

    static List<Polygon> _RecursiveMergePolygons(List<Polygon> polygons, View view)
    {
        HashSet<Polygon> initialSet = new HashSet<Polygon>(polygons);

        HashSet<Polygon> finalSet = new HashSet<Polygon>(polygons);

        foreach (var polygon in initialSet)
        {
            // Should always return at least 1 instance
            var polys = polygons.FindAll(x => _PolygonsIntersect(x, polygon));

            // if it's greater than 1, then merge them and restart the recursion, otherwise continue
            if (polys.Count > 1)
            {
                foreach (var poly in polys)
                {
                    finalSet.Remove(poly);
                }
                var mergedPolygon = new Polygon(polys, view);
                finalSet.Add(mergedPolygon);
                break;
            }
        }
        if (finalSet.Count == initialSet.Count)
        {
            return finalSet.ToList();
        }
        return _RecursiveMergePolygons(finalSet.ToList(), view);
    }