Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: melkalex90 от 06-11-2015, 10:33:49

Название: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 10:33:49
Добрый день!
Подскажите, есть ли возможность определить тип угла в контуре - внешний он или внутренний?
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 10:37:19
Я вот сейчас ничего не понял)
Контур - это замкнутая полилиния? Тогда что такое внешний угол и внутренний угол? Я вот чисто из геометрии рассуждаю - в замкнутом контуре у нас есть только острый и тупой угол. И все они внутри!
Уточните вопрос, пожалуйста - о чем речь вообще
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 10:56:18
1) Да контур - замкнутая полилиния
2)
(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fs18.postimg.org%2F83l335m0l%2Fimage.jpg&hash=09497aeb8dadc32744b4c35436fed5a2) (http://postimg.org/image/83l335m0l/)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 11:09:03
Как я и сказал - это острый угол и тупой. Первый <=90 градусов, второй > 90 градусов. Обычная геометрия
Если касаемо программы - просто проходите по сегментам полилинии и меряете угол между ними. Только вот есть куча нюансов: три типа полилинии, у которых разные методы работы и дуговые сегменты (хотя дуговые сегменты, думаю, не проблема)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: bargool от 06-11-2015, 11:56:40
Возможно, имеется в виду, угол "поворачивает" "внутрь" контура, или "наружу". Человек, небось, решает какой-нибудь convex hull, или что-то подобное..
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 12:00:10
Человек, небось, решает какой-нибудь convex hull, или что-то подобное..
Человек ждет, когда ему готовое решение напишут. Знаю по прошлым темам  ;) ;D
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: bargool от 06-11-2015, 12:02:44
Кстати, вот тут есть пояснение (https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%BE%D0%B3%D0%BE%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%B8%D0%BA#.D0.A1.D0.B2.D1.8F.D0.B7.D0.B0.D0.BD.D0.BD.D1.8B.D0.B5_.D0.BE.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F), что такое внешние и внутренние углы. Но мы не знаем, что топик-стартер хотел на самом деле.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 12:02:58
Я так понимаю мне надо использовать GetLineSegmentAt()?
И нет я не жду готовое решение, пытаюсь разобраться сам.))) И прошу не давать готовый код)

Поправьте если буду не прав:
1) выбираем контур Autodesk.AutoCAD.EditorInput.Editor.GetSelection
2) Получаем количество вершин Autodesk.AutoCAD.DatabaseServices.Polyline.NumberOfVertices
3) В цикле от 0 до Autodesk.AutoCAD.DatabaseServices.Polyline.NumberOfVertices получаем сегменты контура
4) Считаем угол между сегментами
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: bargool от 06-11-2015, 12:11:59
Наконец-то посмотрел на картинку.
Я в этом случае делал так:
1. Три вершины смежных сегментов образуют треугольник.
2. Берём точку внутри этого треугольника (например, какую-нибудь характерную)
3. И определяем - внутри многоугольника эта точка, или снаружи. Задача о попадании точки внутрь многоугольника - легка. Если хотим самостоятельной работы - гуглится тоже легко (http://algolist.manual.ru/maths/geom/belong/poly2d.php) (кстати, советую ресурс - там много хороших алгоритмов описано).
UPD: Правда, я работал не с автокадовскими кривыми, по-этому решал чисто геометрически.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 12:15:30
Я так понимаю мне надо использовать GetLineSegmentAt()?
Если у вас полилиния является объектом Polyline, то да - вам подойдут:
Код - C# [Выбрать]
  1. lwp.GetArcSegment2dAt(int index);
  2. lwp.GetArcSegmentAt(int index);
  3. lwp.GetLineSegment2dAt(int index);
  4. lwp.GetLineSegmentAt(int index);
где index - номер вершины.
Итерацию по вершинам:
Код - C# [Выбрать]
  1. for (var i = 0; i < pline.NumberOfVertices; i++)
  2. {
  3. }

Если у вас Polyline2d или Polyline3d, то там другие методы работы (сам еще не знаю какие)

Все остальные манипуляции - геометрия и математика =)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 12:20:31
Я так понимаю мне надо использовать GetLineSegmentAt()?
Если у вас полилиния является объектом Polyline, то да - вам подойдут:
Код - C# [Выбрать]
  1. lwp.GetArcSegment2dAt(int index);
  2. lwp.GetArcSegmentAt(int index);
  3. lwp.GetLineSegment2dAt(int index);
  4. lwp.GetLineSegmentAt(int index);
где index - номер вершины.
Итерацию по вершинам:
Код - C# [Выбрать]
  1. for (var i = 0; i < pline.NumberOfVertices; i++)
  2. {
  3. }

Если у вас Polyline2d или Polyline3d, то там другие методы работы (сам еще не знаю какие)

Все остальные манипуляции - геометрия и математика =)

Долго писал я, но видимо в правильном направлении.

Командой (entget(car(entsel))) выводит, что у меня контуры LWPOLYLINE. То есть мне подходит GetLineSegmentAt();?
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 12:35:42
То есть мне подходит GetLineSegmentAt();?
Ну тогда да - это ваш случай. Только нужно еще проверить, что это именно прямолинейный участок. Для этого подойдет метод GetBulge(int index) - если 0, значит прямолинейный
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 06-11-2015, 12:36:36
Предлагаю простейший способ:
1) Получаем площадь полилинии S1.
2) Удаляем угловую вершину и получаем площадь полученной полилинии S2.
3) Сравниваем площади. Если S1 < S2 - угол внешний, S1 > S2 - внутренний, S1 == S2 - три точки на одной прямой.
4) Отменяю транзакцию (ну или восстанавливаю вершину).

Метод оказался заманчивым, но не универсальным.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 12:39:09
Александр Ривилис, изящно! ))
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 12:53:46
Предлагаю простейший способ:
1) Получаем площадь полилинии S1.
2) Удаляем угловую вершину и получаем площадь полученной полилинии S2.
3) Сравниваем площади. Если S1 < S2 - угол внешний, S1 > S2 - внутренний, S1 == S2 - три точки на одной прямой.
4) Отменяю транзакцию (ну или восстанавливаю вершину).
Прошу прощения, но я как то не понял данного метода)
Площадь полилинии? Она же вроде =0, или я что то не понимаю(если это просто прямая)? Я однозначно чего то не понимаю....


Ааааааа, то есть удалив вершину, соединяем предыдущую и следующие вершины, после измеряем площадь получившегося контура? Таким образом?
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: art_rrc от 06-11-2015, 13:29:20
То что здесь назвали "внешним" углом, делает фигуру невыпуклой. От этого можно и плясать. Создаем цикл по вершинам до .NumberOfVertices-1 и строим прямую от пред. точки до текущей, потом проверяем .InterSectWith, т.е. пересечение с нашим контуром (это метод VBA, не уверен что на С# так же). Если >0, то угол внешний.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: trir от 06-11-2015, 13:49:08
Есть хорошая книжка - ISBN 5-94157-264-6
Советую почитать
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 14:08:26
Ааааааа, то есть удалив вершину, соединяем предыдущую и следующие вершины, после измеряем площадь получившегося контура? Таким образом?
Да. И так итеративно перебрать все вершины, для каждой выполняя все 4 обозначенных пункта.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 14:29:33
Попытался написать программку, на мой взгляд должно было работать, но выдает ошибку 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. }
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 14:31:51
S1 == S2 - три точки на одной прямой
Если S1 == S2, то либо удалённая точка находится на одной прямой с предыдущей и последующей точками, либо эта точка имеет те же координаты, что и последующая (или предыдущая).
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: bargool от 06-11-2015, 14:33:26
Не учтён п.4 совета Александра Наумовича. В какой-то момент от полилинии ничего не останется
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 14:34:12
выдает ошибку Unhandled Access Violation Reading 0x0000 Exception at 2a55ba83h
Когда выкладываешь ведро кода, не забывай указывать номер строки, в которой выскакивает ошибку.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 14:35:58
кроме того, что указал bargool, вряд ли имеет смысл пытаться получить площадь полилинии, состоящей лишь из двух оставшихся вершин (равно как и понять, какой же угол они образуют :) ).
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 14:42:32
не вижу в коде варианта, предусматривающего k == polies.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 14:55:42
Не учтён п.4 совета Александра Наумовича. В какой-то момент от полилинии ничего не останется
Вспомнил об этом, уже когда написал на форум и уехал от компа. Сейчас буду пробовать.
На счет номера строки, просто выбивает ошибку без указания номера, сейчас попробую отловить ошибку.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 14:57:07
На счет номера строки, просто выбивает ошибку без указания номера, сейчас попробую отловить ошибку.
Пошаговую отладку (F10, F11 (https://msdn.microsoft.com/ru-ru/library/ms366733%28v=vs.90%29.aspx), etc) и breakpoint (https://ru.wikipedia.org/wiki/%D0%A2%D0%BE%D1%87%D0%BA%D0%B0_%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B0) никто не отменял. Может и это (https://msdn.microsoft.com/ru-ru/library/ms366739%28v=vs.90%29.aspx) заинтересует. :)

P.S. тынц (https://ru.wikipedia.org/wiki/%D0%9E%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2) (если интересно происхождение слова).
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 15:10:16
Про пошаговую слышал и знаю) просто не успел провести, исправил несколько ошибок и все заработало!!!!
1)в цикле перебора вершин запустил транзакцию, которую потом отменял(Abort).
2)polyk.close() стояло(ошибочно думал, что это делает полилинию замкнутой), изменил на polyk.Closed = true
Благодарю всех за помощь
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 06-11-2015, 16:06:53
melkalex90
Так и где результирующий (работающий код)?
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 16:07:54
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. }
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 16:12:28
Предлагаю простейший способ:
1) Получаем площадь полилинии S1.
2) Удаляем угловую вершину и получаем площадь полученной полилинии S2.
3) Сравниваем площади. Если S1 < S2 - угол внешний, S1 > S2 - внутренний, S1 == S2 - три точки на одной прямой.
4) Отменяю транзакцию (ну или восстанавливаю вершину).
кстати, я не проверял, но как быть с ситуациями, когда удаление очередной вершины создаёт самопересекающийся контур? Сейчас вожусь не с акадом, поэтому бросить всё и начать проверять не могу...
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 16:14:38
melkalex90, а что это хитрая конструкция в виде не относящейся ни к чему вложенной транзакции? Ты объекты получаешь при помощи внешней, а внутренная-то тебе зачем?
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 16:23:23
Цитата: melkalex90
Код - C# [Выбрать]
  1. Polyline polyk = tr.GetObject(acSSObj.ObjectId, OpenMode.ForWrite) as Polyline;
  2.   if (polyk != null)
  3.   {
Почему не хочешь отфильтровывать лишнее? Зачем пытаться приводить к полилинии то, что ею не является, если этого легко можно избежать (представь, что пользователь нажмёт комбинацию клавиш Ctrl + A)?

Смотри второй параметр перегруженого варианта метода:
Код - C# [Выбрать]
  1. Editor.GetSelection Method (PromptSelectionOptions, SelectionFilter)
ну, или этот, на худой конец:
Код - C# [Выбрать]
  1. Editor.GetSelection Method (SelectionFilter)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 06-11-2015, 16:47:02
melkalex90, а что это хитрая конструкция в виде не относящейся ни к чему вложенной транзакции? Ты объекты получаешь при помощи внешней, а внутренная-то тебе зачем?
Честно признаюсь, я так не разобрался, для чего конкретно нужна транзакция.  Александр Ривилис написал: 4) Отменяю транзакцию (ну или восстанавливаю вершину), - потому решил попробовать добавить ее. И оно заработало.
Цитата: melkalex90
Код - C# [Выбрать]
  1. Polyline polyk = tr.GetObject(acSSObj.ObjectId, OpenMode.ForWrite) as Polyline;
  2.   if (polyk != null)
  3.   {
Почему не хочешь отфильтровывать лишнее? Зачем пытаться приводить к полилинии то, что ею не является, если этого легко можно избежать (представь, что пользователь нажмёт комбинацию клавиш Ctrl + A)?

Смотри второй параметр перегруженого варианта метода:
Код - C# [Выбрать]
  1. Editor.GetSelection Method (PromptSelectionOptions, SelectionFilter)
ну, или этот, на худой конец:
Код - C# [Выбрать]
  1. Editor.GetSelection Method (SelectionFilter)
А это сделаю.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 16:47:17
Зачем пытаться приводить к полилинии то, что ею не является, если этого легко можно избежать
Так вроде он избежал =) При использовании оператора as, если объект не полилиния, в переменную polyk запишется null. А далее он проверяет polyk != null...
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 16:48:05
Так вроде он избежал =)
Он не избежал попытки приведения. Фильтрация это устраняет.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 16:49:47
Он не избежал попытки приведения. Фильтрация это устраняет.
Конечно с фильтрацией намного правильней будет. Но и ошибки он не допустил ))
А про фильтрацию ему уже писали раньше...
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 16:49:56
melkalex90, а что это хитрая конструкция в виде не относящейся ни к чему вложенной транзакции? Ты объекты получаешь при помощи внешней, а внутренная-то тебе зачем?
А вот тут я был неправ... Нашёл в документации:
Цитата: ObjectARX SDK
Transactions can be nested—that is, you can start one transaction inside another and end or abort the recent transaction. The transaction manager maintains transactions in a stack, with the most recent transaction at the top of the stack. When you start a new transaction using AcTransactionManager::startTransaction(), the new transaction is added to the top of the stack and a pointer to it is returned (an instance of AcTransaction). When someone calls AcTransactionManager::endTransaction() or AcTransactionManager::abortTransaction(), the transaction at the top of the stack is ended or aborted.

When object pointers are obtained from object IDs, they are always associated with the most recent transaction. You can obtain the recent transaction using AcTransactionManager::topTransaction(), then use AcTransaction::getObject() or AcTransactionManager::getObject() to obtain a pointer to an object. The transaction manager automatically associates the object pointers obtained with the recent transaction. You can use AcTransaction::getObject() only with the most recent transaction.

When nested transactions are started, the object pointers obtained in the outer containing transactions are also available for operation in the innermost transaction. If the recent transaction is aborted, all the operations done on all the objects (associated with either this transaction or the containing ones) since the beginning of the recent transaction are canceled and the objects are rolled back to the state at the beginning of the recent transaction. The object pointers obtained in the recent transaction cease to be valid once it's aborted.

If the innermost transaction is ended successfully by calling AcTransactionManager::endTransaction(), the objects whose pointers were obtained in this transaction become associated with the containing transaction and are available for operation. This process is continued until the outermost (first) transaction is ended, at which time modifications on all the objects are committed. If the outermost transaction is aborted, all the operations on all the objects are canceled and nothing is committed.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 16:52:29
А про фильтрацию ему уже писали раньше...
Не вижу этого в теме, потому и пишу о фильтрации.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Пекшев aka Modis от 06-11-2015, 16:55:12
Не вижу этого в теме, потому и пишу о фильтрации
Писал вот тут (http://adn-cis.org/forum/index.php?topic=3152.msg12729#msg12729) - а это тема того-же автора. Причем в другой части кода (уверен, что той-же самой программы) как раз фильтрация и используется
А так - повторение - мать учения =)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 06-11-2015, 16:56:38
Проще было вообще не пользоваться транзакциями, а использовать ObjectId.Open в паре с DBObject.Cancel()
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 06-11-2015, 17:36:38
Здесь (http://bushman-andrey.blogspot.ru/2013/01/database-autocad.html) добавил:
Цитата: Андрей Бушман
Менеджер транзакций автоматически ассоциирует все ранее полученные объекты (и операции, производимые над ними) с самой последней транзакцией из стека имеющихся транзакций.

Когда запущена вложенная транзакция - объекты, полученные во внешней транзакции, будут также доступны для работы во вложенной. Если вложенная транзакция будет прервана, то и все операции, выполненные в рамках этой транзакции, над объектами (не важно в какой транзакции эти объекты были получены: во внешней или во внутренней) так же будут отменены и объекты откатываются к тому состоянию, в котором они находились в момент начала работы вложенной транзакции.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 07-11-2015, 01:25:48
Мне кажется, что такой вариант должен работать быстрее:

Код - 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, "LWPOLYLINE")
  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 (Polyline poly = id.Open(OpenMode.ForWrite) as Polyline) {
  52.         double s = poly.Area;
  53.         for (int i = 0; i < poly.NumberOfVertices; i++) {
  54.           double bulge = poly.GetBulgeAt(i);
  55.           Point2d p = poly.GetPoint2dAt(i);
  56.           poly.RemoveVertexAt(i); // Удаляем вершину
  57.           double s1 = poly.Area;
  58.           poly.AddVertexAt(i, p, bulge, 0, 0); // Возвращаем вершину
  59.           if (s > s1) inds.Add(i, true); else inds.Add(i, false);
  60.         }
  61.         poly.Cancel();
  62.       }
  63.       return inds;
  64.     }
  65.   }
  66. }
кстати, я не проверял, но как быть с ситуациями, когда удаление очередной вершины создаёт самопересекающийся контур?
Доказать не могу, но во всех моих тестах при получении самопересекающегося контура всё срабатывало правильно. Похоже, что такие контура могут получится только если угол выпуклый. А если он выпуклый, то его удаление в любом случае уменьшают площадь. В прочем на 100% утверждать не берусь.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: art_rrc от 07-11-2015, 01:47:27
Контур коридора вполне может оказаться таким. Тут скорее нужна доп. информация от автора, какого плана фигуры будут обрабатываться.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: art_rrc от 07-11-2015, 01:52:54
Мой вариант с прямыми лишен такого бага, но вот для такого варианта не подойдет. Но такого может и не быть, либо автор может о нем знать и применить Ваш способ.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 07-11-2015, 02:18:52
Контур коридора вполне может оказаться таким.
Согласен. Алгоритм не универсальный. Нужно подумать о другом алгоритме, основанном на углах.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 07-11-2015, 03:49:00
Почти не тестировал, но похоже работает:

Код - 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
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 07-11-2015, 07:46:55
Доброе утро. Честно сказать каких конкретно видов будет коридор не могу, но пример коридора, из объекта с которым я в данный момент тестирую программу вот:
(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fs24.postimg.org%2Fg5rtwj369%2Fimage.jpg&hash=e65597a79be9db4bb2e8b4516268ce90) (http://postimg.org/image/g5rtwj369/)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: art_rrc от 07-11-2015, 12:03:53
тестирую программу
Программу для чего? На какой вы рассчитываете ИТОГ? Может быть вам вовсе не нужна информация о типе угла, а достаточно немного скорректировать логику программы.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 07-11-2015, 12:55:24
melkalex90, art_rrc
Не смотрели мой последний код? Интересно всё ли я там учёл.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: art_rrc от 07-11-2015, 13:48:15
Не смотрели мой последний код? Интересно всё ли я там учёл.
Очень логичный подход. Т.к. нужно определить тип угла, то и работать нужно с углами (имхо), что и реализовано. И если не придираться к незначительным проверкам (см. вложение, ответ должен быть явно 2 или 4 или предупреждение что плиния не замкнута), то на моих тестовых примерах все работает корректно (т.к. речь идет о комнатах, то вывернутые плинии не тестировал).
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 07-11-2015, 14:49:33
см. вложение, ответ должен быть явно 2 или 4 или предупреждение что плиния не замкнута
Функция работает только (!!!) с замкнутыми не самопересекающимися полилиниями.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 07-11-2015, 14:57:28
тестирую программу
Программу для чего? На какой вы рассчитываете ИТОГ? Может быть вам вовсе не нужна информация о типе угла, а достаточно немного скорректировать логику программы.
В итоге должно быть приложение, которое по заданным параметрам(размеры помещений, кол-во внутренних и внешних углов), считает кол-во материалов необходимых для отделки объекта. В связи с тем, что L и F профили считаются по количеству внутренних и внешних углов в помещении, то у меня есть необходимость проводить эти расчеты(на сколько я понимаю по другому(ну не считая ручной ввод) этого не реализовать).

melkalex90, art_rrc
Не смотрели мой последний код? Интересно всё ли я там учёл.
Пока еще не успел, только приехал домой. Сейчас попробую проверить.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: melkalex90 от 07-11-2015, 16:38:20
Александр, работает, считает все выпуклые углы. Пока не разобрался с самим кодом, буду разбираться) Спасибо.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 07-11-2015, 17:35:44
Добавил обработку незамкнутых полилиний. Ну и назначил пост с этим кодом в качестве Решения, т.к. алгоритм с площадями оказался недостаточно универсальным. Надеюсь, что возражений нет.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: NurGeo от 03-12-2015, 20:34:30
Конечно решение по коду найдено, но вдруг кому понадобится. В геодезии есть правило. Сумма внутренних углов замкнутого полигона равна (180*n-2), сумма внешних углов полигона равна (180*n+2). n-количество углов в полигоне. Исходя из этого можно было узнать какие углы высчитаны внутренние или внешние.
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 03-12-2015, 21:25:14
Исходя из этого можно было узнать какие углы высчитаны внутренние или внешние.
Не понял. Как это ты из суммы углов собираешься определить внутренний или внешний конкретный из углов многоугольника?
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Андрей Бушман от 03-12-2015, 21:27:57
какие углы высчитаны
расчитаны, вычислены.... может вычесаны? :)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: NurGeo от 04-12-2015, 12:24:46
Не понял. Как это ты из суммы углов собираешься определить внутренний или внешний конкретный из углов многоугольника?
Ну, если постоянно отнимать от угла (XYAxis) передней линии обратный угол задней линии, то ты будешь получать всегда угол с одной стороны полигона. Вычислив углы на всех вершинах по этому методу и по данным формулам можно узнать, какими являются все вычисленные углы.
расчитаны, вычислены.... может вычесаны?
Что поделать, русский язык никогда у меня не был в любимых предметах, а щас когда вырос, часто неудобно из-за этого.  ::)
Название: Re: Определение внуренних и внешних углов в контуре
Отправлено: Александр Ривилис от 04-12-2015, 12:57:34
NurGeo
Боюсь, что без кода я не смогу понять что ты имел в виду.