Человек, небось, решает какой-нибудь convex hull, или что-то подобное..Человек ждет, когда ему готовое решение напишут. Знаю по прошлым темам ;) ;D
Я так понимаю мне надо использовать GetLineSegmentAt()?Если у вас полилиния является объектом Polyline, то да - вам подойдут:
Я так понимаю мне надо использовать GetLineSegmentAt()?Если у вас полилиния является объектом Polyline, то да - вам подойдут:Код - C# [Выбрать]где index - номер вершины.
lwp.GetArcSegment2dAt(int index); lwp.GetArcSegmentAt(int index); lwp.GetLineSegment2dAt(int index); lwp.GetLineSegmentAt(int index);
Итерацию по вершинам:Код - C# [Выбрать]
for (var i = 0; i < pline.NumberOfVertices; i++) { }
Если у вас Polyline2d или Polyline3d, то там другие методы работы (сам еще не знаю какие)
Все остальные манипуляции - геометрия и математика =)
То есть мне подходит GetLineSegmentAt();?Ну тогда да - это ваш случай. Только нужно еще проверить, что это именно прямолинейный участок. Для этого подойдет метод GetBulge(int index) - если 0, значит прямолинейный
Предлагаю простейший способ:Прошу прощения, но я как то не понял данного метода)
1) Получаем площадь полилинии S1.
2) Удаляем угловую вершину и получаем площадь полученной полилинии S2.
3) Сравниваем площади. Если S1 < S2 - угол внешний, S1 > S2 - внутренний, S1 == S2 - три точки на одной прямой.
4) Отменяю транзакцию (ну или восстанавливаю вершину).
Ааааааа, то есть удалив вершину, соединяем предыдущую и следующие вершины, после измеряем площадь получившегося контура? Таким образом?Да. И так итеративно перебрать все вершины, для каждой выполняя все 4 обозначенных пункта.
S1 == S2 - три точки на одной прямойЕсли S1 == S2, то либо удалённая точка находится на одной прямой с предыдущей и последующей точками, либо эта точка имеет те же координаты, что и последующая (или предыдущая).
выдает ошибку Unhandled Access Violation Reading 0x0000 Exception at 2a55ba83hКогда выкладываешь ведро кода, не забывай указывать номер строки, в которой выскакивает ошибку.
Не учтён п.4 совета Александра Наумовича. В какой-то момент от полилинии ничего не останетсяВспомнил об этом, уже когда написал на форум и уехал от компа. Сейчас буду пробовать.
На счет номера строки, просто выбивает ошибку без указания номера, сейчас попробую отловить ошибку.Пошаговую отладку (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) заинтересует. :)
melkalex90
Так и где результирующий (работающий код)?
Предлагаю простейший способ:кстати, я не проверял, но как быть с ситуациями, когда удаление очередной вершины создаёт самопересекающийся контур? Сейчас вожусь не с акадом, поэтому бросить всё и начать проверять не могу...
1) Получаем площадь полилинии S1.
2) Удаляем угловую вершину и получаем площадь полученной полилинии S2.
3) Сравниваем площади. Если S1 < S2 - угол внешний, S1 > S2 - внутренний, S1 == S2 - три точки на одной прямой.
4) Отменяю транзакцию (ну или восстанавливаю вершину).
Почему не хочешь отфильтровывать лишнее? Зачем пытаться приводить к полилинии то, что ею не является, если этого легко можно избежать (представь, что пользователь нажмёт комбинацию клавиш Ctrl + A)?Код - C# [Выбрать]
Polyline polyk = tr.GetObject(acSSObj.ObjectId, OpenMode.ForWrite) as Polyline; if (polyk != null) {
melkalex90, а что это хитрая конструкция в виде не относящейся ни к чему вложенной транзакции? Ты объекты получаешь при помощи внешней, а внутренная-то тебе зачем?Честно признаюсь, я так не разобрался, для чего конкретно нужна транзакция. Александр Ривилис написал: 4) Отменяю транзакцию (ну или восстанавливаю вершину), - потому решил попробовать добавить ее. И оно заработало.
А это сделаю.Цитата: melkalex90Почему не хочешь отфильтровывать лишнее? Зачем пытаться приводить к полилинии то, что ею не является, если этого легко можно избежать (представь, что пользователь нажмёт комбинацию клавиш Ctrl + A)?Код - C# [Выбрать]
Polyline polyk = tr.GetObject(acSSObj.ObjectId, OpenMode.ForWrite) as Polyline; if (polyk != null) {
Смотри второй параметр перегруженого варианта метода:Код - C# [Выбрать]ну, или этот, на худой конец:
Editor.GetSelection Method (PromptSelectionOptions, SelectionFilter)Код - C# [Выбрать]
Editor.GetSelection Method (SelectionFilter)
Зачем пытаться приводить к полилинии то, что ею не является, если этого легко можно избежатьТак вроде он избежал =) При использовании оператора as, если объект не полилиния, в переменную polyk запишется null. А далее он проверяет polyk != null...
Так вроде он избежал =)Он не избежал попытки приведения. Фильтрация это устраняет.
Он не избежал попытки приведения. Фильтрация это устраняет.Конечно с фильтрацией намного правильней будет. Но и ошибки он не допустил ))
melkalex90, а что это хитрая конструкция в виде не относящейся ни к чему вложенной транзакции? Ты объекты получаешь при помощи внешней, а внутренная-то тебе зачем?А вот тут я был неправ... Нашёл в документации:
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.
А про фильтрацию ему уже писали раньше...Не вижу этого в теме, потому и пишу о фильтрации.
Не вижу этого в теме, потому и пишу о фильтрацииПисал вот тут (http://adn-cis.org/forum/index.php?topic=3152.msg12729#msg12729) - а это тема того-же автора. Причем в другой части кода (уверен, что той-же самой программы) как раз фильтрация и используется
Менеджер транзакций автоматически ассоциирует все ранее полученные объекты (и операции, производимые над ними) с самой последней транзакцией из стека имеющихся транзакций.
Когда запущена вложенная транзакция - объекты, полученные во внешней транзакции, будут также доступны для работы во вложенной. Если вложенная транзакция будет прервана, то и все операции, выполненные в рамках этой транзакции, над объектами (не важно в какой транзакции эти объекты были получены: во внешней или во внутренней) так же будут отменены и объекты откатываются к тому состоянию, в котором они находились в момент начала работы вложенной транзакции.
кстати, я не проверял, но как быть с ситуациями, когда удаление очередной вершины создаёт самопересекающийся контур?Доказать не могу, но во всех моих тестах при получении самопересекающегося контура всё срабатывало правильно. Похоже, что такие контура могут получится только если угол выпуклый. А если он выпуклый, то его удаление в любом случае уменьшают площадь. В прочем на 100% утверждать не берусь.
Контур коридора вполне может оказаться таким.Согласен. Алгоритм не универсальный. Нужно подумать о другом алгоритме, основанном на углах.
тестирую программуПрограмму для чего? На какой вы рассчитываете ИТОГ? Может быть вам вовсе не нужна информация о типе угла, а достаточно немного скорректировать логику программы.
Не смотрели мой последний код? Интересно всё ли я там учёл.Очень логичный подход. Т.к. нужно определить тип угла, то и работать нужно с углами (имхо), что и реализовано. И если не придираться к незначительным проверкам (см. вложение, ответ должен быть явно 2 или 4 или предупреждение что плиния не замкнута), то на моих тестовых примерах все работает корректно (т.к. речь идет о комнатах, то вывернутые плинии не тестировал).
см. вложение, ответ должен быть явно 2 или 4 или предупреждение что плиния не замкнутаФункция работает только (!!!) с замкнутыми не самопересекающимися полилиниями.
В итоге должно быть приложение, которое по заданным параметрам(размеры помещений, кол-во внутренних и внешних углов), считает кол-во материалов необходимых для отделки объекта. В связи с тем, что L и F профили считаются по количеству внутренних и внешних углов в помещении, то у меня есть необходимость проводить эти расчеты(на сколько я понимаю по другому(ну не считая ручной ввод) этого не реализовать).тестирую программуПрограмму для чего? На какой вы рассчитываете ИТОГ? Может быть вам вовсе не нужна информация о типе угла, а достаточно немного скорректировать логику программы.
melkalex90, art_rrcПока еще не успел, только приехал домой. Сейчас попробую проверить.
Не смотрели мой последний код? Интересно всё ли я там учёл.
Исходя из этого можно было узнать какие углы высчитаны внутренние или внешние.Не понял. Как это ты из суммы углов собираешься определить внутренний или внешний конкретный из углов многоугольника?
какие углы высчитанырасчитаны, вычислены.... может вычесаны? :)
Не понял. Как это ты из суммы углов собираешься определить внутренний или внешний конкретный из углов многоугольника?Ну, если постоянно отнимать от угла (XYAxis) передней линии обратный угол задней линии, то ты будешь получать всегда угол с одной стороны полигона. Вычислив углы на всех вершинах по этому методу и по данным формулам можно узнать, какими являются все вычисленные углы.
расчитаны, вычислены.... может вычесаны?Что поделать, русский язык никогда у меня не был в любимых предметах, а щас когда вырос, часто неудобно из-за этого. ::)