Advertisement
teaowl

Sweep line algorithm

Jun 12th, 2018
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.84 KB | None | 0 0
  1. using SegmentsAlgorythm;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7.  
  8. namespace OutlineAlgorithm
  9. {
  10.     public class NewOutlineProcessor
  11.     {
  12.         private List<Outline> outlines = new List<Outline>();
  13.  
  14.         private List<Segment> prioritySet = new List<Segment>();
  15.  
  16.         private EventComparator eventComparator = new EventComparator();
  17.         private ByStartComparator byStartComparator = new ByStartComparator();
  18.  
  19.         public async Task addElement(Segment segment)
  20.         {
  21.             prioritySet.Add(segment);
  22.             //перераспределяем отрезки на числовой прямой
  23.             //p.s.Встроенные алгоритмы отлично оптимизированы - почти отсортированный массив пересортируется очень быстро
  24.             //p.p.s.как ни велик соблазн положить сортировку в отдельный поток, без синхронизации нельзя
  25.             prioritySet.Sort(byStartComparator);
  26.             await FindOutline();
  27.             Console.WriteLine("---Priority Set---");
  28.             foreach (Segment seg in prioritySet)
  29.             {
  30.                 Console.WriteLine(seg);
  31.             }
  32.             Console.WriteLine("---Result Set---");
  33.             foreach (Outline outline in outlines)
  34.             {
  35.                 Console.WriteLine(outline);
  36.             }
  37.  
  38.         }
  39.  
  40.         private Task FindOutline()
  41.         {
  42.             return Task.Run(() =>
  43.             {
  44.                 List<SweepLineEvent> activeSet = new List<SweepLineEvent>();
  45.                 //обыскивать активный набор
  46.                 foreach (Segment segment in prioritySet)
  47.                 {  
  48.                     //добавление события - хороший момент для анализа, как и удаление
  49.                     SweepLineEvent segmentStartEvent;
  50.                     segmentStartEvent.POI = segment.start;
  51.                     segmentStartEvent.parent = segment;
  52.                     segmentStartEvent.TYPE = SweepLineEvent.START;
  53.  
  54.                     SweepLineEvent segmentEndEvent;
  55.                     segmentEndEvent.POI = segment.end;
  56.                     segmentEndEvent.parent = segment;
  57.                     segmentEndEvent.TYPE = SweepLineEvent.END;
  58.  
  59.                     activeSet.Add(segmentEndEvent);
  60.                     activeSet.Add(segmentStartEvent);
  61.                     activeSet.Sort(eventComparator);
  62.                     Console.WriteLine("---Active Set---");
  63.                     foreach (SweepLineEvent seg in activeSet)
  64.                     {
  65.                         Console.WriteLine(seg);
  66.                     }
  67.                     Console.WriteLine("---Sweep line cycle---");
  68.                     for (int i = 0; i < activeSet.Count; i++)
  69.                     {
  70.                         for (int j = 0; j < activeSet.Count; j++)
  71.                         {
  72.                             Console.WriteLine("Count = "+ activeSet.Count);
  73.                             Console.WriteLine("Точка интереса " + activeSet[i].POI + " рассматривается..");
  74.                             if (Math.Abs(activeSet[i].POI.X - activeSet[j].POI.X) < 0.001f && i>1)
  75.                             {
  76.                                 //если равен х, то равен и у
  77.                                 if (activeSet[i].POI.Y == activeSet[j].POI.Y)
  78.                                 {
  79.                                     AddOutline(activeSet[i].parent, activeSet[j].parent);
  80.                                     Console.WriteLine("Новый контур обрабатывается..");
  81.                                 }
  82.                             }
  83.                             //если это конец отрезка, значит, он ушёл из зоны видимости, ведь все события отсортированы
  84.                             //p.s. последний не считается - ситуация может изменится на следующей итерации
  85.                             bool isTheEnd = activeSet[i].TYPE == SweepLineEvent.END;
  86.                             if (isTheEnd && i!=activeSet.Count-1)
  87.                             {
  88.                                 Console.WriteLine("Заметающая прямая больше не пересекает отрезок " + activeSet[i].parent);
  89.                                 activeSet.RemoveAll(e => e.parent.Equals(activeSet[i].parent));
  90.                             }
  91.                         }
  92.                     }
  93.                 }
  94.             });
  95.         }
  96.  
  97.         private void AddOutline(Segment segment, Segment foundedSegment)
  98.  
  99.         {
  100.             //исследование в уже существующем контуре
  101.             Console.WriteLine("---исследование в уже существующем контуре---");
  102.             Outline first = searchInOtherOutlines(segment);
  103.             Outline second = searchInOtherOutlines(foundedSegment);
  104.             //если отрезки состоят в одном и том же непустом контуре, значит, ничего делать не нужно
  105.             if (first != null && first == second)
  106.             {
  107.                 Console.WriteLine("Контур уже существует");
  108.                 return;
  109.             }
  110.                 //первый есть..
  111.                 if (first != null)
  112.             {
  113.                 Console.WriteLine("отрезок " + segment + " уже есть в контурах..");
  114.                 //..а второго нет(наиболее распространённая ситуация)
  115.                 if (second == null)
  116.                 {
  117.                     Console.WriteLine("а отрезка " + foundedSegment + " в контурах ещё нет, добавляем...");
  118.                     first.Add(foundedSegment);
  119.                     Console.WriteLine("итоговый контур: " + first);
  120.                 }
  121.                 else
  122.                 {
  123.                     //..или и второй есть
  124.                     Console.WriteLine("отрезок " + foundedSegment + " тоже..");
  125.                     Console.WriteLine("оба есть в контурах! ");
  126.                     Console.WriteLine("все проверки считаются проваленными...");
  127.                 }
  128.             }
  129.             //..или нет первого
  130.             else
  131.             {
  132.                 Console.WriteLine("отрезка " + segment + " нет в контурах..");
  133.                 //..но есть второй..
  134.                 if (second != null)
  135.                 {
  136.                     Console.WriteLine("но " + foundedSegment + " есть, добавим первый к нему..");
  137.                     second.Add(segment);
  138.                     Console.WriteLine("итоговый контур " + second);
  139.                 }
  140.                 //..или обоих нет
  141.                 else
  142.                 {
  143.                     Console.WriteLine("отрезка " + foundedSegment + " тоже");
  144.                     Outline newOutline = new Outline(segment, foundedSegment);
  145.                     outlines.Add(newOutline);
  146.                     Console.WriteLine("так как совпадение всё же обнаружено, создаётся новый контур: " + newOutline);
  147.                 }
  148.             }
  149.         }
  150.  
  151.         private Outline searchInOtherOutlines(Segment segment)
  152.         {
  153.             Outline found = null;
  154.             foreach (Outline outline in outlines)
  155.             {
  156.                 if (outline.Contains(segment)) found = outline;
  157.             }
  158.             return found;
  159.         }
  160.  
  161.         private class ByStartComparator : IComparer<Segment>
  162.         {
  163.             public int Compare(Segment first, Segment second)
  164.             {
  165.                 return first.start.X.CompareTo(second.start.X);
  166.             }
  167.         }
  168.  
  169.         private class EventComparator : IComparer<SweepLineEvent>
  170.         {
  171.             public int Compare(SweepLineEvent first, SweepLineEvent second)
  172.             {
  173.                 return first.POI.X.CompareTo(second.POI.X);
  174.             }
  175.         }
  176.  
  177.         private struct SweepLineEvent
  178.         {
  179.             public string TYPE;
  180.             public const string START = "START";
  181.             public const string END = "END";
  182.             public PointF POI; //point of interest
  183.             public Segment parent;
  184.  
  185.             public override string ToString()
  186.             {
  187.                 return "["+TYPE + " | " + POI + " | Parent:" + parent+"]";
  188.             }
  189.         }
  190.     }
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement