V
V
Valery Osipov2012-08-10 12:01:57
Algorithms
Valery Osipov, 2012-08-10 12:01:57

How to merge an arbitrary set of polygons?

There are several polygons that can be combined into one.
They look something like this: image

Polygons are selected by the operator, so that the polygons are selected in random order - my main problem is the problem of determining the next section when merging

For two polygons I wrote the following code
public List<Point2d> CombinePolylinePoints(List<Point2d> points1, List<Point2d> points2)
{
  var borderPoints = new List<Point2d>();
  for (int i = 0; i < points1.Count; i++)
  {
    if (points2.Contains(points1[i]))
    {
      Debug.WriteLine("Точка с индексом " + i + " - граничная");
      borderPoints.Add(points1[i]);
    }
  }
  if (borderPoints.Count < 2)
    return new List<Point2d>();
  // проходим по первому полигону?
  var goingFirstParcel = true;
  int iFirst = 0;
  int iSecond = 0;
  Point2d nextPoint = default(Point2d);
  var points = new List<Point2d>();
  while (nextPoint != points1[0])
  {

    if (goingFirstParcel)
    {
      Debug.WriteLine("Идем по первому участку..");
      var currPoint = points1[iFirst];
      points.Add(currPoint);
      if (borderPoints.Any(p => p.IsEqualTo(currPoint, Tolerance.Global)))
      {
        Debug.WriteLine("Текущая точка - граничная. Переходим на второй участок");
        goingFirstParcel = false;

        iSecond = points2.IndexOf(currPoint);
        if (iSecond == -1)
        {
          MessageBox.Show("IndexOf returned 0");
          return null;
        }
        iSecond++;
        if (iSecond >= points2.Count)
          iSecond = 0;
        Debug.WriteLine("iSecond = " + iSecond);
        nextPoint = points2[iSecond];
        continue;
      }
      iFirst++;
      if (iFirst >= points1.Count) iFirst = 0;
      nextPoint = points1[iFirst];
    }
    else if (!goingFirstParcel)
    {
      Debug.WriteLine("Идем по второму участку..");
      var currPoint = points2[iSecond];
      points.Add(currPoint);
      if (borderPoints.Any(p => p.IsEqualTo(currPoint, Tolerance.Global)))
      {
        Debug.WriteLine("Текущая точка - граничная. Переходим на первый участок");
        goingFirstParcel = true;
        iFirst = points1.IndexOf(currPoint);
        if (iFirst == -1)
        {
          MessageBox.Show("IndexOf iFirst returned 0");
          return null;
        }
        iFirst++;
        if (iFirst >= points1.Count)
          iFirst = 0;
        Debug.WriteLine("iFirst = " + iFirst);
        nextPoint = points1[iFirst];
        continue;
      }
      iSecond++;
      if (iSecond >= points2.Count) iSecond = 0;
      nextPoint = points2[iSecond];
    }
  }
  return points;
}


In short:
  1. looking for boundary points
  2. we go along the first section, adding all the points to the list
  3. if the current point is a boundary point, go to the next point of the second section
  4. go to step 2 until the next point becomes the first point of the first section

But for an arbitrary set of polygons, it is impossible to write - on some test data, reaching a fork (a point common to 3 or more sections), the algorithm takes the wrong path and loops on it.

Question: how to choose which polygon to go to at the fork?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
T
TheEternal, 2012-08-10
@TheEternal

Recursively won't work?
We take an arbitrary polygon and any that is adjacent to it. We combine them according to the above algorithm.
We repeat.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question