C#: Является ли набо линий замкнутым или простой способ проверки «На полигон»

Сегодня я решил рассказать о такой задачи как проверка набора линий на замкнутость. Другими словами задачу можно описать как «Образует ли заданный набор линий полигон».

Для решения данной задачи нужно сделать небольшое упрощение в виде создания класса Линия. Он будет содержать всего два атрибута — начальная и конечная точка.

class Line
{
  public readonly Point Start;
  public readonly Point End;

  public Line(Point start, Point end)
  {
     this.Start = start;
     this.End = end;
  }
}

Так как проверять нам нужно будет набор линий, то их представим в виде списка.

class Lines: List<Line> { }

Так как на полигон нужно проверять набор линий, то функцию проверки можно записать прямо в классе Lines. Точнее этих функций будет две.

class Lines: List<Line> {
  public bool IsPolygon()
  {
     //Для образования полигона нужно минимум три линии
     if (this.Count < 3)
     {
       return false;
     }
     //Массив флагов, для хранения уже просмотренных линий
     bool[] flags = new bool[this.Count];
     for(int i = 0; i < flags.Length; ++i)
     {
       flags[i] = false;
     }
     this.IsPolygon(0, ref flags, this[0].Start);
     for(int i = 0; i < flags.Length; ++i)
     {
       if(flags[i] == false) 
       {
          //Не полигон если хотя бы один флаг не true
          return false;  
       }
     }
     return true;
  }
  private void IsPolygon(int first, ref bool[] flags, Point start)
  {
    flags[first] = true;
    for(int i = 0; i < flags.Length; ++i)
    {
      if(flags[i] == false) { break; }
      if(i == flags.Length - 1) 
      {
        flags[first] = this[first].End.Equals(start) || 
                       this[first].Start.Equals(start);
        return;
      }
    }
    for (int i = 0; i < this.Count; ++i)
    {
      //Если точка не проверялась и она является продолжением
      //рассматриваемой линии 
      if (!flags[i] &&
          (this[first].End.Equals(this[i].Start) ||
           this[first].End.Equals(this[i].End)
          ))
      {
         this.IsPolygon(i, ref flags, start);
      }
    }
  }
}

Собственно и все. Однако у данной проверки есть одно, но. На самом деле функция проверит наличие хотя бы одного замкнутого контура из линий. Чтобы избежать этого, нужно убрать проверку на то что конец рассматриваемой точки, может совпасть с концом текущей точки:

this[first].End.Equals(this[i].End)

А также нужно иметь четкую структуру в которой линия четко задается не только двумя точками, но и каждая точка является той, в рамках какого атрибута она сохранена в объекте линии.

Запись опубликована в рубрике C# с метками , , , , , , , . Добавьте в закладки постоянную ссылку.