Разрезать Region

Автор Тема: Разрезать Region  (Прочитано 37046 раз)

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

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Разрезать Region
« Ответ #30 : 02-06-2014, 17:00:50 »
Я же писал о минимальной относительной погрешности в 1e-6. Вот похоже она и вылезла.
1. Это проявляется даже если левый нижний угол границы региона находится в центре WCS.
2. Код, написанный Дима_ не даёт таких погрешностей на тех же самых исходных регионах.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Разрезать Region
« Ответ #31 : 02-06-2014, 17:09:19 »
1. Это проявляется даже если левый нижний угол границы региона находится в центре WCS.
Здесь это уже не принципиально.
2. Код, написанный Дима_ не даёт таких погрешностей на тех же самых исходных регионах.
Дима сразу вырезает ячейки-прямоугольники размером [dx,dy], а ты сначала режешь строками, а потом их уже делишь на ячейки. Наверное разница в этом.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Разрезать Region
« Ответ #32 : 02-06-2014, 17:24:36 »
Дима сразу вырезает ячейки-прямоугольники размером [dx,dy], а ты сначала режешь строками, а потом их уже делишь на ячейки. Наверное разница в этом.
А по другому никак: иначе я буду получать неправильные результаты, что и происходит в ряде случаев с использованием кода Дима_. Ниже прилагается дополнительный чертёж с тестовыми регионами. Берём первый "Ш"-образный регион и вызываем команду NAREZ, указывая следующие параметры:

Цитировать
Command: NAREZ
Select objects: 1 found

Select objects:
РЁРёСЂРёРЅР° 135

Высота 20
Затраченное время: 00:00:00.0595703
nil
На выходе визуально всё вроде выглядит правильно, однако это не так: выделяем верхний левый кусок и видим, что выделилась вся "строка". Возможно для Дима_ такой результат является именно тем, что нужно, однако моим пользователям для каждого из нарезанных кусков нужно получать центр масс. Соответственно в данном случае будет показан центр масс, общий для трёх кусков, а это не то, что требовалось моим юзерам. Именно поэтому у меня в коде две итерации: сначала строки, затем колонки. Собственно эти нюансы я и показывал здесь, выполняя различные логические операции над регионами.

UPD. Александр Наумович, собственно именно эту ситуацию мы и обсуждали с вами по скайпу 28 мая, в результате чего вы согласились, что обозначенная вами ранее оптимизация в данном случае не будет работать. Я как раз на примере буквы "Ш" и показывал вариант, который оптимизация не сможет корректно обработать.

P.S. Теперь мне понятно, за счёт чего код Дима_ работал быстрее, однако данный вариант решения мне не подойдёт.
« Последнее редактирование: 02-06-2014, 17:42:12 от Андрей Бушман »

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Разрезать Region
« Ответ #33 : 02-06-2014, 21:39:27 »
Я же писал о минимальной относительной погрешности в 1e-6. Вот похоже она и вылезла.
Нет, это однозначно ошибка в моём коде. Завтра буду искать. Скорее всего где-то сделал Ctrl+C, Ctrl + V и не переименовал переменную (ну, или что-то вроде того).

Дима_, спасибо за код.

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Разрезать Region
« Ответ #34 : 02-06-2014, 22:43:00 »
По порядку: Словестное описание алгоритма - суть оптимизации такова, единожды высчитываем "сетку" по габаритным размерам которую заполняем прямоугольниками построчно и в процессе заполнения смотрим не пересекает-ли созданный сегмент границы области, если пересекает и имеет площадь - добавляем его в БД, а следующий за ним проверяем на пересечение (если пересекает - тогда все по новой) и площадь - если она около нуля - то тогда все последующие сегменты до пересечения Dispos'ируем, если площадь есть (то есть полный прямоугольник - пересечений ведь нет), то последующие сегменты рисуем без проверок, до следующего пересечения. Упрощая проверяем на "пересечение" только "граничащие" клетки и 1 следующею за ними - остальные по последней.

В коде:
Код - C# [Выбрать]
  1. Seq.fold (fun (next,check) _ -> //запускаем "свертку" с 2-мя bool аргументами "рисовать следующий" и "проверять"
  2.     let cl=(obr.Clone():?>Region) //создаем "копию" образцового прямоугольника
  3.     obr.TransformBy(mtw) // перемещаем "оригинал" на следующий столбец
  4.     let pc=new Point3dCollection() // коллекция точек пересечения
  5.     cl.IntersectWith(rg,Intersect.ExtendThis,pc,0n,0n) //заполняем коллекцию точками пересечения (если они есть)
  6.     let inters()=cl.BooleanOperation(BooleanOperationType.BoolIntersect,rg.Clone():?>Region)
  7.                  cl.Area<0.0000001 // функция "наложения" регионов, возвращает true если выходной регион "без площади"
  8.     (pc.Count>0,next,check)|>function // функция проверки от 3 аргументов: есть ли пересечения?, рисовать?, требуется ли проверка
  9.       |true,_,_ when inters()->cl.Dispose() // если было пересечение и примитив без площади
  10.                                (false,true) // уничтожаем сегмент и на след. итерации выполняем проверку
  11.       |true,_,_->AppendEnt cl//если пересечение и нормальная площадь
  12.                  (false,true)// добавляем "обрезок" и проверка на следующем
  13.       |_,_,true when inters()->cl.Dispose()//если установлен флаг проверки, но нет площади
  14.                                (false,false)// до следующего пересечения рисовать не надо
  15.       |_,_,true|_,true,_->AppendEnt cl// если была площадь, либо установленн флаг "рисования"
  16.                           (true,false)// то оставляем сегмент без изменений (его не надо подрезать)
  17.       |_->cl.Dispose()
  18.           (false,false))// во всех остальных случаях - удаляем сегмент.
  19. (false,false) // начальное значение аргументов каждой "строки"

По фаталу - да действительно если создать значительное кол-во сегментов - то автокад намертво зависает на записи (у меня x64) - либо я просто не дождался завершения, причем висит именно на записи, саму "нарезку" он делает, я попробовал еще включать dispose копиям "главных" объектов которые идут как аргумент в BooleanOperation (что по моему представлению должно быть встроено непосредственно в метод) - результата не дало. Можно просто попробывать создать эквивалентное кол-во регионов - может просто акад "не осиливает", т.к. вроде все созданное либо в БД либо в Dispose.

По "проблеме буквы Ш" - чтобы "уши" буквы были в разных областях - надо задавать соответствующие размеры "клетки", я не очень понимаю как от этого спасает алгоритм "нарезать вначале строки, потом столбцы", да строки немного "запляшут" относительно друг друга - то есть сегменты лягут "кривым кирпичиком" т.к. столбцы начинаются с физического начала строки (а не сетки - как у меня), что в некоторых частных случаях выделит "разрезанный сегмент" в разные регионы, но с той же вероятностью, на произвольном теле справедливо и обратно - если "клетка" достаточно велика, там в обоих случаях может "попасться" "несколькотельный" сегмент.

з.ы. чтоб лисп не писал "кракозябры" - сохрани в default кодировке.

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Разрезать Region
« Ответ #35 : 02-06-2014, 23:16:34 »
По фаталу - да действительно если создать значительное кол-во сегментов - то автокад намертво зависает на записи (у меня x64) - либо я просто не дождался завершения, причем висит именно на записи, саму "нарезку" он делает, я попробовал еще включать dispose копиям "главных" объектов которые идут как аргумент в BooleanOperation (что по моему представлению должно быть встроено непосредственно в метод) - результата не дало. Можно просто попробывать создать эквивалентное кол-во регионов - может просто акад "не осиливает", т.к. вроде все созданное либо в БД либо в Dispose.
В режиме DEBUG загляни в отладочную консоль. Если у тебя где-то пропущен вызов Dispose, то там должна появиться подсказка на эту тему, т.к. реализация метода !DBObject() следующая:
Код - C# [Выбрать]
  1. // Autodesk.AutoCAD.DatabaseServices.DBObject
  2. private void !DBObject()
  3. {
  4. object[] args = new object[]
  5. {
  6. base.GetType().ToString()
  7. };
  8. Debug.WriteLine("DisposableWrapper", string.Format(CultureInfo
  9.     .InvariantCulture, "Forgot to call Dispose? ({0})", args));
  10. }
Т.о. при "потере" Dispose должны появляться сообщения вида "Forgot to call Dispose? ...".


Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Разрезать Region
« Ответ #36 : 02-06-2014, 23:29:27 »
По "проблеме буквы Ш" - чтобы "уши" буквы были в разных областях - надо задавать соответствующие размеры "клетки", я не очень понимаю как от этого спасает алгоритм "нарезать вначале строки, потом столбцы", да строки немного "запляшут"
Да, что-то меня перемкнуло: твой код запустил, чтобы проверить проблему, а свой почему-то решил не запускать, т.к. "всё должно быть пучком". Похоже я поторопился, завтра ещё подумаю. Проблема в том, что нужно как-то гарантированно резать так, чтобы в одном регионе не было нескольких сегментов (как при резке буквы Ш клеткой, равной длине региона).

Нужно как-то получить количество внешних контуров в регионе и на основе каждого такого контура (с учётом вложенных контуров- отверстий, если такие есть) создать отдельные регионы. Тут дополнительная проблема возникает: если в одном из таких контуров имеется отверстие, в составе которого будет ещё один контур (островок в отверстии), то и его нужно отдельно обрабатывать и т.д. рекурсивно анализируя структуру контуров... Т.е. всё не так просто, как хотелось бы.

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Разрезать Region
« Ответ #37 : 02-06-2014, 23:58:47 »
то и его нужно отдельно обрабатывать и т.д. рекурсивно анализируя структуру контуров...
... это не слабое такое уточнение...
боюсь через текущий .Net API тут глухо, ихмо надо лезть в расшифровку ACIS (что само по себе гемор, а для тебя еще и лисп-гемор), тут надо на поклон к Елпанову Евгению - он по моему в этом "хорошо шагнул". Либо методом Ньютона обрезать регион до допустимых ограничений и искать - но тогда время выполнения "немножко" прибавится (хоть ньютон и быстр, на раз в 10-15 вынь да полож) Или "врзрывать и смотреть" - короче по хорошему сложно (очень), по "быстрому" не быстро и "криво".

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Разрезать Region
« Ответ #38 : 03-06-2014, 00:04:11 »
... это не слабое такое уточнение...
Согласен. Просто когда я показал юзеру эту ситуацию на конкретных примерах, и уточнил насчёт рекурсивного анализа (островки в отверстиях и т.п.), то ответ был "ну конечно же, это обязательно".
Цитировать
короче по хорошему сложно (очень), по "быстрому" не быстро и "криво".
Буду пытаться найти "консенсус" с юзерами.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Разрезать Region
« Ответ #39 : 03-06-2014, 00:18:43 »
боюсь через текущий .Net API тут глухо
Для этого есть BREP .NET API
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Разрезать Region
« Ответ #40 : 03-06-2014, 00:28:48 »
Маэстро! раз и Вы не спите - на что похожи "симптомы" когда много (очень) объектов создано, но потом не сохранится? (Dispose пропущен или еще что). Про Brep Вы же сами здесь писали - что не прокатит?

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Разрезать Region
« Ответ #41 : 03-06-2014, 00:33:45 »
Буду пытаться найти "консенсус" с юзерами.
ИХМО - по моему, в данном случае, это наиболее верное решение.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Разрезать Region
« Ответ #42 : 03-06-2014, 00:36:32 »
Про Brep Вы же сами здесь писали - что не прокатит?
Там ошибка в одном из методов, который к этой теме отношения не имеет.  Да и тот метод можно реализовать через P/Invoke.
Маэстро! раз и Вы не спите - на что похожи "симптомы" когда много (очень) объектов создано, но потом не сохранится? (Dispose пропущен или еще что).
Вполне возможно, что пропущен Dispose. Но на 100% уверенно сказать не могу. Особенно в AutoCAD 2014, в котором переписали работу с Solid3d и Region таким образом, что быстродействие упало при прочих равных условиях в два раза по сравнению с AutoCAD 2013 (факт подтвержденный в ADN DevHelp).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Разрезать Region
« Ответ #43 : 03-06-2014, 07:57:30 »
Особенно в AutoCAD 2014, в котором переписали работу с Solid3d и Region таким образом, что быстродействие упало при прочих равных условиях в два раза по сравнению с AutoCAD 2013 (факт подтвержденный в ADN DevHelp).
А в 2015-м как дела обстоят?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Разрезать Region
« Ответ #44 : 03-06-2014, 10:58:12 »
А в 2015-м как дела обстоят?
Пока также как и в 2015 - я слишком поздно отправил этот баг.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение