2016-11-15 2 views
1

У меня есть список с полилиниями (PointCollection), как показано на рисунке. Некоторые сегменты перекрываются, как синяя и оранжевая линии, как показано в «оригинале». Я уже знаю, какие сегменты они есть. Мне нужно сдвинуть перекрывающиеся сегменты. Трудность заключается в том, чтобы избежать новых совпадений с другими строками, как показано в «неправильном».Алгоритм изменения полилинии

enter image description here

Я эту проблему, что я только координаты узлов и никакой информации о сегментах. Есть ли возможность определить, переношу ли я узел на сегмент другой линии? У кого-то хорошая идея, как я мог бы решить эту проблему?

+0

Что вы нацеливаете: Winforms, WPF, ASP ..? __Always__ правильно помечайте свой вопрос! - Как вы хотите переместиться? Вручную или в коде? В каком направлении? Случайно? Вы можете написать процедуру проб и ошибок, которая использует один и тот же тест, чтобы проверить наложение совпадений, как тот, который вам нужно найти, в первую очередь. (Подсказка: вы можете сделать полилинии в графических дорожках и объединить их в область, которая может быть проверена на отсутствие) – TaW

+0

Я готовлю данные для стороннего инструмента, и я не буду визуализировать его в своем приложении. Цель состоит в том, чтобы переместить узел по коду. Моя идея - сдвинуть узлы либо влево, либо вправо в направлении биссектрисы угла между двумя сегментами. Прежде чем переместить узел, я хотел бы проверить, какое направление пусто. Как преобразовать полилинии в графические пути? – Nindalf

+0

Вы можете использовать графику GDI + и по-прежнему экспортировать только результаты без фактического отображения чего-либо, несмотря на то, что для тестирования подпрограмм может быть хорошей проекцией небольшого проекта winforms ... вы просто добавляете точку в путь emptygraphicspath: 'gp.AddLines (pointlist .ToArray()) '. Для перемещения GP используйте матрицу и gp.tranform! Создайте область из одного gp и протестируйте с помощью reg.Intersect (gp2) и if (reg.IsEmtpy (графический объект)). – TaW

ответ

1

Как было отмечено в комментариях у вас есть выбор

  • решение вопроса аналитический геометрические расчеты или
  • с использованием некоторых GDI + метод

Вот пример последними:

Сначала ваше консольное приложение должно содержать ссылку на System.Drawing и несколько статей:

using System.Drawing; 
using System.Drawing.Drawing2D; 
using System.Drawing.Imaging; //optional, used for bitmap saving only 

Вот статическая функция, которая проверяет, если два GraphicsPaths пересекаются:

static bool intersect(GraphicsPath gp1, GraphicsPath gp2, Graphics g) 
{ 
    using (Region reg = new Region(gp1)) 
    { 
     reg.Intersect(gp2); 
     return !reg.IsEmpty(g); 
    } 
} 

Он принимает два GraphicsPaths и так же в Graphics объекта.

Настоящий стенд демонстрирует, как его можно использовать. Он создает 2 случайных полилинии, а затем каждый раз сдвигает второй вправо на 50 пикселей, пока он больше не пересечет 1-й.

Всех стадий втягиваются в растровое изображение, которое затем будет сохранено ..:

static void Main(string[] args) 
{ 
    int w = 1234; 
    int h = 1234; 

    Random rnd = new Random(0); 
    for (int t = 0; t < 33; t++) 
    { 
     List<Point> l1 = new List<Point>(); 
     List<Point> l2 = new List<Point>(); 
     for (int i = 0; i < 4; i++) 
     { 
      l1.Add(new Point(rnd.Next(1234), rnd.Next(567))); 
      l2.Add(new Point(rnd.Next(567), rnd.Next(1234))); 
     } 

     using (Matrix m = new Matrix()) 
     using (Bitmap bmp = new Bitmap(w, h)) 
     using (Graphics g = Graphics.FromImage(bmp)) 
     using (GraphicsPath gp1 = new GraphicsPath()) 
     using (GraphicsPath gp2 = new GraphicsPath()) 
     { 
      gp1.AddLines(l1.ToArray()); 
      gp2.AddLines(l2.ToArray()); 
      m.Translate(50, 0); 
      bool intersects = intersect(gp1, gp2, g); 
      g.Clear(Color.White); 
      g.DrawPath(Pens.Blue, gp1); 
      g.DrawPath(intersects ? Pens.Red : Pens.Green, gp2); 

      while (intersects) 
      { 
       gp2.Transform(m); 
       intersects = intersect(gp1, gp2, g); 
       g.DrawPath(intersects ? Pens.Red : Pens.Green, gp2); 
       intersects = intersect(gp1, gp2, g); 
      } 


      bmp.Save(@"D:\scrape\x\__xTest_" + t.ToString("000") + ".png", 
        ImageFormat.Png); 

     } 
    } 
} 

Вот один из выходных файлов:

enter image description here

Вы можете получить доступ к смещенным точкам пути, как

List<PointF> l3 = gp2.PathPoints.ToList(); 

Обратите внимание, что вы должны либо сделать Bitmap достаточно большой для ваших фактических чисел или масштабирования их и работать с floats!

+0

Хорошо, мне нравится ваш подход с GDI +. Спасибо за пример. Моя идея - сначала заполнить плоскость линиями, у которых нет пересечений. Затем я выбираю первую из перекрывающейся пары (например, синюю) и рисую ее также. Затем я выбираю второй (оранжевый) и сдвигаю его вправо. Затем я сравниваю это с уже нарисованными линиями, чтобы проверить, есть ли у меня все еще пересечения. Если это так, сдвиньте его влево и повторите проверку. Это хороший подход? Можно ли сравнить один GraphicsPath с уже нарисованным GraphicsPath в плоскости, чтобы проверить пересечения? – Nindalf

+0

Конечно, просто поместите их в «List » и переверните его. Обратите внимание, что я только рисую их для демонстрации идеи; вам не нужно делать какой-либо фактический чертеж. Вам нужен объект «Graphics», хотя для вызова функции, вам также понадобится «Bitmap»; но сам чертеж не нужен! – TaW