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

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

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

Оффлайн art_rrc

  • ADN Club
  • **
  • Сообщений: 70
  • Карма: 1
  • Skype: art_sapranovich
То что здесь назвали "внешним" углом, делает фигуру невыпуклой. От этого можно и плясать. Создаем цикл по вершинам до .NumberOfVertices-1 и строим прямую от пред. точки до текущей, потом проверяем .InterSectWith, т.е. пересечение с нашим контуром (это метод VBA, не уверен что на С# так же). Если >0, то угол внешний.

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 470
  • Карма: 63
Есть хорошая книжка - ISBN 5-94157-264-6
Советую почитать

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Ааааааа, то есть удалив вершину, соединяем предыдущую и следующие вершины, после измеряем площадь получившегося контура? Таким образом?
Да. И так итеративно перебрать все вершины, для каждой выполняя все 4 обозначенных пункта.

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

  • ADN OPEN
  • **
  • Сообщений: 59
  • Карма: 0
Попытался написать программку, на мой взгляд должно было работать, но выдает ошибку Unhandled Access Violation Reading 0x0000 Exception at 2a55ba83h(понять не могу в чем проблема)(((
Код - C# [Выбрать]
  1. namespace Angles
  2. {
  3.     public class FindAngles
  4.     {
  5.         [CommandMethod("Find", CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
  6.         public void test()
  7.         {
  8.             DocumentCollection acDocMgr = AcAp.Application.DocumentManager;
  9.             Document acDoc = acDocMgr.MdiActiveDocument;
  10.             Database acCurDb = acDoc.Database;
  11.             Editor ed = acDoc.Editor;
  12.             double polies = 0;
  13.             int S = 0, p=0;
  14.             double totalArea = 0;
  15.             double totalLength = 0;
  16.             ObjectId[] ids;
  17.             using (DocumentLock docLock = acDoc.LockDocument())
  18.             {
  19.                 using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
  20.                 {
  21.                     PromptSelectionResult acSSPrompt = ed.GetSelection();
  22.                     if (acSSPrompt.Status == PromptStatus.OK)
  23.                     {
  24.                         SelectionSet acSSet = acSSPrompt.Value;
  25.                         foreach (SelectedObject acSSObj in acSSet)
  26.                         {
  27.                             if (acSSObj != null)
  28.                             {
  29.                                 Polyline polyk = tr.GetObject(acSSObj.ObjectId, OpenMode.ForWrite) as Polyline;
  30.                                 if (polyk != null)
  31.                                 {
  32.                                     polies = polyk.Area;
  33.                                     for (int j = 0; j < polyk.NumberOfVertices; j++)
  34.                                     {
  35.                                         polyk.RemoveVertexAt(j);
  36.                                         polyk.Close();
  37.                                         double k = polyk.Area;
  38.                                         if (k > polies)
  39.                                         {
  40.                                             S += 1;
  41.                                         }
  42.                                         if (k < polies)
  43.                                         {
  44.                                             p += 1;
  45.                                         }
  46.                                     }
  47.                                 }
  48.                             }
  49.                         }
  50.                     }
  51.                         tr.Commit();
  52.                 }
  53.             }
  54.             ed.WriteMessage("\n" + S + p);
  55.         }
  56.     }
  57. }

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
S1 == S2 - три точки на одной прямой
Если S1 == S2, то либо удалённая точка находится на одной прямой с предыдущей и последующей точками, либо эта точка имеет те же координаты, что и последующая (или предыдущая).

Оффлайн bargool

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Не учтён п.4 совета Александра Наумовича. В какой-то момент от полилинии ничего не останется

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
выдает ошибку Unhandled Access Violation Reading 0x0000 Exception at 2a55ba83h
Когда выкладываешь ведро кода, не забывай указывать номер строки, в которой выскакивает ошибку.

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

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

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
не вижу в коде варианта, предусматривающего k == polies.

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

  • ADN OPEN
  • **
  • Сообщений: 59
  • Карма: 0
Не учтён п.4 совета Александра Наумовича. В какой-то момент от полилинии ничего не останется
Вспомнил об этом, уже когда написал на форум и уехал от компа. Сейчас буду пробовать.
На счет номера строки, просто выбивает ошибку без указания номера, сейчас попробую отловить ошибку.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
На счет номера строки, просто выбивает ошибку без указания номера, сейчас попробую отловить ошибку.
Пошаговую отладку (F10, F11, etc) и breakpoint никто не отменял. Может и это заинтересует. :)

P.S. тынц (если интересно происхождение слова).

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

  • ADN OPEN
  • **
  • Сообщений: 59
  • Карма: 0
Про пошаговую слышал и знаю) просто не успел провести, исправил несколько ошибок и все заработало!!!!
1)в цикле перебора вершин запустил транзакцию, которую потом отменял(Abort).
2)polyk.close() стояло(ошибочно думал, что это делает полилинию замкнутой), изменил на polyk.Closed = true
Благодарю всех за помощь

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
melkalex90
Так и где результирующий (работающий код)?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 59
  • Карма: 0
melkalex90
Так и где результирующий (работающий код)?

Код - C# [Выбрать]
  1. namespace Angles
  2. {
  3.     public class FindAngles
  4.     {
  5.         [CommandMethod("Find", CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
  6.         public void test()
  7.         {
  8.             DocumentCollection acDocMgr = AcAp.Application.DocumentManager;
  9.             Document acDoc = acDocMgr.MdiActiveDocument;
  10.             Database acCurDb = acDoc.Database;
  11.             Editor ed = acDoc.Editor;
  12.             double polies = 0;
  13.             int S = 0, p=0;
  14.             double totalArea = 0;
  15.             double totalLength = 0;
  16.             ObjectId[] ids;
  17.  
  18.             try
  19.             {
  20.                 using (DocumentLock docLock = acDoc.LockDocument())
  21.                 {
  22.                     using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
  23.                     {
  24.                         PromptSelectionResult acSSPrompt = ed.GetSelection();
  25.                         if (acSSPrompt.Status == PromptStatus.OK)
  26.                         {
  27.                             SelectionSet acSSet = acSSPrompt.Value;
  28.                             foreach (SelectedObject acSSObj in acSSet)
  29.                             {
  30.                                 if (acSSObj != null)
  31.                                 {
  32.                                     Polyline polyk = tr.GetObject(acSSObj.ObjectId, OpenMode.ForWrite) as Polyline;
  33.                                     if (polyk != null)
  34.                                     {
  35.                                         polies = polyk.Area;
  36.                                         for (int j = 0; j < polyk.NumberOfVertices; j++)
  37.                                         {
  38.                                             using (Transaction tr1 = acCurDb.TransactionManager.StartTransaction())
  39.                                             {
  40.                                                 polyk.RemoveVertexAt(j);
  41.                                                 double k = polyk.Area;
  42.                                                 polyk.Closed = true;
  43.  
  44.                                                 if (k > polies)
  45.                                                 {
  46.                                                     S += 1;
  47.                                                 }
  48.                                                 if (k < polies)
  49.                                                 {
  50.                                                     p += 1;
  51.                                                 }
  52.                                                 else
  53.                                                 {
  54.  
  55.                                                 }
  56.                                                 tr1.Abort();
  57.                                             }
  58.                                         }
  59.                                     }
  60.                                 }
  61.                             }
  62.                         }
  63.  
  64.                         tr.Commit();
  65.                     }
  66.                 }
  67.             }
  68.              catch(System.Exception ex)
  69.                 {
  70.                 ed.WriteMessage("\n" + ex.Message + "\n" + ex.StackTrace);
  71.             }
  72.            ed.WriteMessage("\n" + S + " " + p);
  73.         }
  74.     }
  75. }

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Предлагаю простейший способ:
1) Получаем площадь полилинии S1.
2) Удаляем угловую вершину и получаем площадь полученной полилинии S2.
3) Сравниваем площади. Если S1 < S2 - угол внешний, S1 > S2 - внутренний, S1 == S2 - три точки на одной прямой.
4) Отменяю транзакцию (ну или восстанавливаю вершину).
кстати, я не проверял, но как быть с ситуациями, когда удаление очередной вершины создаёт самопересекающийся контур? Сейчас вожусь не с акадом, поэтому бросить всё и начать проверять не могу...