Определение внуренних и внешних углов в контуре

Автор Тема: Определение внуренних и внешних углов в контуре  (Прочитано 30298 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Отмечено как Решение Александр Ривилис 07-11-2015, 17:51:44

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Почти не тестировал, но похоже работает:

Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Geometry;
  7. using Autodesk.AutoCAD.EditorInput;
  8.  
  9. #pragma warning disable 0618
  10.  
  11. [assembly: CommandClass(typeof(Rivilis.TestPolygon))]
  12.  
  13. namespace Rivilis
  14. {
  15.   public class TestPolygon
  16.   {
  17.     [CommandMethod("TP", CommandFlags.Modal | CommandFlags.UsePickSet)]
  18.     public void MyCommand()
  19.     {
  20.       Document doc = Application.DocumentManager.MdiActiveDocument;
  21.       if (doc == null) return;
  22.       Editor ed = doc.Editor;
  23.       Database db = doc.Database;
  24.       PromptSelectionOptions pso = new PromptSelectionOptions();
  25.       pso.MessageForAdding = "\nВыберите полилинии: ";
  26.       pso.MessageForRemoval = "\nУдалите полилинии: ";
  27.       TypedValue[] filList = new TypedValue[1] {
  28.         new TypedValue((int)DxfCode.Start, "*POLYLINE")
  29.       };
  30.       SelectionFilter sf = new SelectionFilter(filList);
  31.       PromptSelectionResult psr = ed.GetSelection(pso, sf);
  32.       if (psr.Status == PromptStatus.OK) {
  33.         foreach (ObjectId id in psr.Value.GetObjectIds()) {
  34.           var inds = GetVertexiesDesc(id);
  35.           int i = 0; // Считаем количество выпуклых углов
  36.           foreach (var ind in inds) if (ind.Value) i++;
  37.           ed.WriteMessage("\nВ полилинии {0} выпуклых углов {1}",
  38.             id.Handle.ToString(), i);
  39.         }
  40.       }
  41.     }
  42.  
  43.     /// <summary>
  44.     /// Получаем коллекцию пар (номер вершины) - (флаг выпуклости вершины)
  45.     /// </summary>
  46.     /// <param name="id">ObjectId полилинии.</param>
  47.     /// <returns></returns>
  48.     public static Dictionary<int, bool> GetVertexiesDesc(ObjectId id)
  49.     {
  50.       var inds = new Dictionary<int, bool>();
  51.       using (Curve poly = id.Open(OpenMode.ForRead) as Curve) {
  52.         Vector3d norm = Vector3d.ZAxis;
  53.         try { norm = poly.GetPlane().Normal; } catch { }
  54.         // Количество вершин полилинии. Если полилиния незамкнутая, то
  55.         // к EndParam нужно добавить 1.
  56.         int nVerts = (int)(poly.EndParam + (poly.Closed ? 0 : 1) + 1e-6);
  57.  
  58.         // Полный угол со знаком для определения направления:
  59.         // обход по часовой или против часовой стрелки.
  60.         double angle = 0;
  61.         // Коллекция углов в каждой из вершин
  62.         List<double> angles = new List<double>(nVerts);
  63.  
  64.         for (int i = 0; i < nVerts; i++) {
  65.           Point3d p1 = poly.GetPointAtParameter((i) % nVerts);
  66.           Point3d p2 = poly.GetPointAtParameter((i+1) % nVerts);
  67.           Point3d p3 = poly.GetPointAtParameter((i+2) % nVerts);
  68.           double ang = signedAngle(p1, p2, p3, norm);
  69.           angles.Add(ang); angle += ang;
  70.         }
  71.         for (int i = 0; i < angles.Count; i++) {
  72.           inds.Add(i, angle * angles[i] > 0);
  73.         }
  74.       }
  75.       return inds;
  76.     }
  77.  
  78.     /// <summary>
  79.     /// Функция получает угол со знаком между указанными векторами, заданными точками,
  80.     /// относительно плоскости заданной нормалью
  81.     /// </summary>
  82.     public static double signedAngle(Point3d p1, Point3d p2, Point3d p3, Vector3d norm)
  83.     {
  84.       return signedAngle(p2 - p1, p3 - p2, norm);
  85.     }
  86.     /// <summary>
  87.     /// Функция получает угол со знаком между указанными векторами,
  88.     /// относительно плоскости заданной нормалью
  89.     /// </summary>
  90.     public static double signedAngle(Vector3d v1, Vector3d v2, Vector3d norm)
  91.     {
  92.       Vector3d v3 = v1.CrossProduct(v2);
  93.       double angle = Math.Acos(v1.GetNormal().DotProduct(v2.GetNormal()));
  94.       return angle * Math.Sign(v3.DotProduct(norm));
  95.     }
  96.   }
  97. }

Достоинство этого алгоритма в том, что он не модифицирует полилинии и потенциально значительно быстрее алгоритма с вычислением площади. Ну и работает как с LWPOLYLINE, так и с POLYLINE
« Последнее редактирование: 07-11-2015, 17:28:25 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн melkalex90Автор темы

  • ADN OPEN
  • **
  • Сообщений: 59
  • Карма: 0
Доброе утро. Честно сказать каких конкретно видов будет коридор не могу, но пример коридора, из объекта с которым я в данный момент тестирую программу вот:


Оффлайн art_rrc

  • ADN Club
  • **
  • Сообщений: 70
  • Карма: 1
  • Skype: art_sapranovich
тестирую программу
Программу для чего? На какой вы рассчитываете ИТОГ? Может быть вам вовсе не нужна информация о типе угла, а достаточно немного скорректировать логику программы.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
melkalex90, art_rrc
Не смотрели мой последний код? Интересно всё ли я там учёл.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн art_rrc

  • ADN Club
  • **
  • Сообщений: 70
  • Карма: 1
  • Skype: art_sapranovich
Не смотрели мой последний код? Интересно всё ли я там учёл.
Очень логичный подход. Т.к. нужно определить тип угла, то и работать нужно с углами (имхо), что и реализовано. И если не придираться к незначительным проверкам (см. вложение, ответ должен быть явно 2 или 4 или предупреждение что плиния не замкнута), то на моих тестовых примерах все работает корректно (т.к. речь идет о комнатах, то вывернутые плинии не тестировал).

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
см. вложение, ответ должен быть явно 2 или 4 или предупреждение что плиния не замкнута
Функция работает только (!!!) с замкнутыми не самопересекающимися полилиниями.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн melkalex90Автор темы

  • ADN OPEN
  • **
  • Сообщений: 59
  • Карма: 0
тестирую программу
Программу для чего? На какой вы рассчитываете ИТОГ? Может быть вам вовсе не нужна информация о типе угла, а достаточно немного скорректировать логику программы.
В итоге должно быть приложение, которое по заданным параметрам(размеры помещений, кол-во внутренних и внешних углов), считает кол-во материалов необходимых для отделки объекта. В связи с тем, что L и F профили считаются по количеству внутренних и внешних углов в помещении, то у меня есть необходимость проводить эти расчеты(на сколько я понимаю по другому(ну не считая ручной ввод) этого не реализовать).

melkalex90, art_rrc
Не смотрели мой последний код? Интересно всё ли я там учёл.
Пока еще не успел, только приехал домой. Сейчас попробую проверить.

Оффлайн melkalex90Автор темы

  • ADN OPEN
  • **
  • Сообщений: 59
  • Карма: 0
Александр, работает, считает все выпуклые углы. Пока не разобрался с самим кодом, буду разбираться) Спасибо.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Добавил обработку незамкнутых полилиний. Ну и назначил пост с этим кодом в качестве Решения, т.к. алгоритм с площадями оказался недостаточно универсальным. Надеюсь, что возражений нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн NurGeo

  • ADN OPEN
  • Сообщений: 31
  • Карма: 1
Конечно решение по коду найдено, но вдруг кому понадобится. В геодезии есть правило. Сумма внутренних углов замкнутого полигона равна (180*n-2), сумма внешних углов полигона равна (180*n+2). n-количество углов в полигоне. Исходя из этого можно было узнать какие углы высчитаны внутренние или внешние.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Исходя из этого можно было узнать какие углы высчитаны внутренние или внешние.
Не понял. Как это ты из суммы углов собираешься определить внутренний или внешний конкретный из углов многоугольника?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
какие углы высчитаны
расчитаны, вычислены.... может вычесаны? :)

Оффлайн NurGeo

  • ADN OPEN
  • Сообщений: 31
  • Карма: 1
Не понял. Как это ты из суммы углов собираешься определить внутренний или внешний конкретный из углов многоугольника?
Ну, если постоянно отнимать от угла (XYAxis) передней линии обратный угол задней линии, то ты будешь получать всегда угол с одной стороны полигона. Вычислив углы на всех вершинах по этому методу и по данным формулам можно узнать, какими являются все вычисленные углы.
расчитаны, вычислены.... может вычесаны?
Что поделать, русский язык никогда у меня не был в любимых предметах, а щас когда вырос, часто неудобно из-за этого.  ::)

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
NurGeo
Боюсь, что без кода я не смогу понять что ты имел в виду.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение