рисование внутри monitorInputPoint

Автор Тема: рисование внутри monitorInputPoint  (Прочитано 5907 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
появилась необходимость подсвечивать грипсы объектов (например, полилиний) при прохождении над ними указателя мышки. Ну и грипса, ближайшая к курсору должна быть другого цвета. вроде как ничего сложного, но заливка почему-то не рисуется :( может чего не дописал в коде?
Код - C++ [Выбрать]
  1. Acad::ErrorStatus plinePointMonitor::monitorInputPoint(const AcEdInputPoint& input, AcEdInputPointMonitorResult& output)
  2. {      
  3.         if (input.pointComputed())
  4.         {
  5.                 resbuf view; acedGetVar(_T("VIEWSIZE"), &view);
  6.                 double gripsize = view.resval.rreal * 0.007;
  7.                
  8.                 if (input.keyPointEntities().length() > 0)
  9.                 {
  10.                         AcGePoint3dArray ptsHilightAll;
  11.                         for (int i = 0; i < input.keyPointEntities().length(); ++i)
  12.                         {
  13.                                 AcDbObjectPointer<AcDbEntity> pEnt(input.keyPointEntities().at(i), AcDb::kForRead);
  14.                                 if (pEnt.openStatus() == Acad::eOk)
  15.                                 {
  16.                                         if (pEnt->isA() == AcDbPolyline::desc() || pEnt->isA() == AcDb2dPolyline::desc())
  17.                                         {
  18.                                                 AcDbCurve * pPlineFound = AcDbCurve::cast(pEnt);
  19.                                                 AcGePoint3dArray ptsHilight; ptsHilight.removeAll();
  20.                                                 pPlineFound->getStretchPoints(ptsHilight);
  21.                                                 ptsHilightAll.append(ptsHilight);
  22.                                         }                                      
  23.                                 }
  24.                         }
  25.  
  26.                         int nearestIndex = -1;
  27.                         double curDist = 99999999.9;
  28.                         for (int i = 0; i < ptsHilightAll.length(); i++)
  29.                         {
  30.                                 if (input.rawPoint().distanceTo(ptsHilightAll.at(i)) < curDist)
  31.                                 {
  32.                                         curDist = input.rawPoint().distanceTo(ptsHilightAll.at(i));
  33.                                         nearestIndex = i;
  34.                                 }
  35.                                
  36.                         }
  37.  
  38.                         // подсветка узлов полилинии
  39.                         for (int i = 0; i < ptsHilightAll.length(); i++)
  40.                         {
  41.                                 acdbWcs2Ucs(asDblArray(ptsHilightAll[i]), asDblArray(ptsHilightAll[i]), 0);
  42.                                
  43.                                 AcGePoint3d * pts = new AcGePoint3d[5];
  44.                                 pts[0] = AcGePoint3d(ptsHilightAll.at(i) - AcGeVector3d(gripsize, gripsize, 0.0));
  45.                                 pts[1] = AcGePoint3d(ptsHilightAll.at(i) - AcGeVector3d(gripsize, -gripsize, 0.0));
  46.                                 pts[2] = AcGePoint3d(ptsHilightAll.at(i) + AcGeVector3d(gripsize, gripsize, 0.0));
  47.                                 pts[3] = AcGePoint3d(ptsHilightAll.at(i) + AcGeVector3d(gripsize, -gripsize, 0.0));
  48.                                 pts[4] = AcGePoint3d(ptsHilightAll.at(i) - AcGeVector3d(gripsize, gripsize, 0.0));
  49.  
  50.                                 Adesk::UInt16 curColor = input.drawContext()->subEntityTraits().color();
  51.                                 AcGiFillType curFt = input.drawContext()->subEntityTraits().fillType();
  52.                                 double curThickness = input.drawContext()->subEntityTraits().thickness();
  53.  
  54.                                 input.drawContext()->subEntityTraits().setThickness(1); // на всякий случай      
  55.                                 int color = (nearestIndex == i) ? 12 : 150;
  56.  
  57.                                 // внутренняя заливка
  58.                                 input.drawContext()->subEntityTraits().setFillType(kAcGiFillAlways);
  59.                                 input.drawContext()->subEntityTraits().setColor(color);
  60.                                 input.drawContext()->geometry().polygon(5, pts);
  61.  
  62.                                 // внешний контур
  63.                                 input.drawContext()->subEntityTraits().setFillType(kAcGiFillNever);
  64.                                 input.drawContext()->subEntityTraits().setColor(7);
  65.                                 input.drawContext()->geometry().polygon(5, pts);
  66.  
  67.                                 delete pts;
  68.                                 pts = NULL;
  69.  
  70.                                 input.drawContext()->subEntityTraits().setColor(curColor);
  71.                                 input.drawContext()->subEntityTraits().setFillType(curFt);
  72.                                 input.drawContext()->subEntityTraits().setThickness(curThickness);
  73.                         }
  74.                 }
  75.         }
  76.  
  77.         return Acad::eOk;
  78. }

ну и вызов всего этого для тестирования:
Код - C++ [Выбрать]
  1. plinePointMonitor entsMonitor;
  2. curDoc()->inputPointManager()->addPointMonitor(&entsMonitor);
  3. AcGePoint3d pt;
  4. acedGetPoint(NULL, _T("\nВодим мышкой над полилиниями. ЛКМ - выход. "), asDblArray(pt));
  5. curDoc()->inputPointManager()->removePointMonitor(&entsMonitor);

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #1 : 21-11-2018, 12:33:37 »
А если заменить:
Код - C++ [Выбрать]
  1. input.drawContext()->geometry().polygon(5, pts);
на
Код - C++ [Выбрать]
  1. input.drawContext()->geometry().polygon(4, pts);
Это явно лишнее: acdbWcs2Ucs. Расстояние если уж измерять, то в DCS, а не в UCS
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: рисование внутри monitorInputPoint
« Ответ #2 : 21-11-2018, 12:51:37 »
убрал замыкающую точку (то я перестраховывался :) в хелпе то написано, что автоматом замыкает, но мало ли), результат тот же. только контурный черный квадратик
Это явно лишнее: acdbWcs2Ucs. Расстояние если уж измерять, то в DCS, а не в UCS
расстояние я меряю в WCS выше :), а  перевод в UCS для отображения грипсы в нужном месте

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #3 : 21-11-2018, 12:58:47 »
  перевод в UCS для отображения грипсы в нужном месте
Кто сказал, что координаты для рисования нужно передавать в UCS???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #4 : 21-11-2018, 13:02:33 »
Сейчас нет возможности тестировать твой код. Мой аналогичный работает. Уточни версию AutoCAD и направление взгляда. Не работает и при плане МСК?
Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. Acad::ErrorStatus VertexPointMonitor::monitorInputPoint (
  3.     bool &appendToTooltipStr,
  4.     ACHAR *&additionalTooltipString,
  5.     AcGiViewportDraw *drawContext,
  6.     AcApDocument *document,
  7.     bool pointComputed,
  8.     int history,
  9.     const AcGePoint3d &lastPoint,
  10.     const AcGePoint3d &rawPoint,
  11.     const AcGePoint3d &grippedPoint,
  12.     const AcGePoint3d &cartesianSnappedPoint,
  13.     const AcGePoint3d &osnappedPoint,
  14.     AcDb::OsnapMask osnapMask,
  15.     const AcArray<AcDbCustomOsnapMode *> &customOsnapModes,
  16.     AcDb::OsnapMask osnapOverrides,
  17.     const AcArray<AcDbCustomOsnapMode *> &customOsnapOverrides,
  18.     const AcArray<AcDbObjectId> &apertureEntities,
  19.     const AcArray<AcDbObjectIdArray, AcArrayObjectCopyReallocator<AcDbObjectIdArray> > &nestedApertureEntities,
  20.     const AcArray<int> &gsSelectionMark,
  21.     const AcArray<AcDbObjectId> &keyPointEntities,
  22.     const AcArray<AcDbObjectIdArray, AcArrayObjectCopyReallocator<AcDbObjectIdArray> > &nestedKeyPointEntities,
  23.     const AcArray<int> &keyPointGsSelectionMark,
  24.     const AcArray<AcGeCurve3d *> &alignmentPaths,
  25.     const AcGePoint3d &computedPoint,
  26.     const ACHAR *tooltipString
  27.     ) {
  28.         appendToTooltipStr =false ;
  29.         if (drawContext != NULL) {
  30.             resbuf rbGripSize;   acedGetVar(L"GRIPSIZE",&rbGripSize);
  31.             resbuf rbSreensize;  acedGetVar(L"SCREENSIZE",&rbSreensize);
  32.             resbuf rbViewSize;   acedGetVar(L"VIEWSIZE",&rbViewSize);
  33.             int color = getvar(L"GRIPHOT",1);
  34.             double rad = rbViewSize.resval.rreal / rbSreensize.resval.rpoint[Y] * (rbGripSize.resval.rint*2);
  35.             drawContext->subEntityTraits().setColor(color);
  36.             drawContext->subEntityTraits().setFillType(kAcGiFillAlways);
  37.             AcGePoint3d pts[4] = {
  38.                 pVertex + AcGeVector3d(-rad,-rad,0),
  39.                 pVertex + AcGeVector3d(-rad,+rad,0),
  40.                 pVertex + AcGeVector3d(+rad,+rad,0),
  41.                 pVertex + AcGeVector3d(+rad,-rad,0)
  42.             };
  43.             drawContext->geometry().polygon(4,pts);
  44.         }
  45.  
  46.         return (Acad::eOk) ;
  47. }
  48.  
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: рисование внутри monitorInputPoint
« Ответ #5 : 21-11-2018, 13:13:49 »
хм. таки да. перегонять в UCS не надо, так что действительно это лишнее.
Сейчас нет возможности тестировать твой код. Мой аналогичный работает. Уточни версию AutoCAD и направление взгляда. Не работает и при плане МСК?
тестирую в 2016x64. работать должно в 2010+
по поводу осей... не работает во всех случаях. и в стандартной единичной матрице (это я про направление взгляда :) и положение осей) и уж тем более, если крутануть произвольную орбиту.
короче говоря, пытаюсь добиться такого же отображения грипсиков как и при выделении объекта в любой системе координат
--------------------------
проверил ваш код. ничего не рисует.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #6 : 21-11-2018, 21:48:19 »
Похоже на какой-то баг с AcGiGeometry::polygon
Вот два варианта. В первом используется  AcGiGeometry::polygon:

Во втором AcGiGeometry::circle:


Интересный факт? Тот код, который я приводил у меня работает еще в AutoCAD 2008. Это я тестировал в AutoCAD 2019.

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #7 : 21-11-2018, 22:21:34 »
короче говоря, пытаюсь добиться такого же отображения грипсиков как и при выделении объекта в любой системе координат
Я немного подумал, и понял, что нифига не получится. В отличие от нормальных грипсиков monitorInputPoint вызывается много раз в секунду даже если курсор не двигается и каждый раз создаётся новый контекст для рисования. AutoCAD не успевает отрисовать предыдущую графику, как от него требуется её стереть и начать рисовать новую....
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #8 : 21-11-2018, 23:54:56 »
Еще немного подумал и решил отправить запрос в ADN DevHelp. Добавил тестовый проект и это видео:



Пусть прокомментируют.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: рисование внутри monitorInputPoint
« Ответ #9 : 22-11-2018, 11:54:42 »
Добавил тестовый проект и это видео:
хотел написать, что у меня при использовании залитого полигона в командной строке ошибка вылазит, а она и на видео есть на последних секундах, так что я не один такой :)

Я немного подумал, и понял, что нифига не получится.
я пришел к такому же мнению. потягал мышку по полилинии с залитыми кружочками... это как на сварку смотреть :):):) всё блымает как новогодняя елка. так что решил пока вернуться обратно на acedGrDraw (помечать крестиками узлы). по крайней мере не блымает при перерисовке (кстати, вот откуда в моём коде взялась перегонка в UCS)

жалко что нет команды для написания текстовых строк аналогичной acedGrDraw :(. мне там еще для пользователей, которые не обращают внимание на текущие координаты в сатусбаре, узел подписывать надо. а рисовать цифры отрезками как-то попахивает извращениями. прикрутил рисование через geometry().text(). и таки да, тоже блымает.

Пусть прокомментируют.
:o ;D ;D ;D ;D ;D

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #10 : 22-11-2018, 12:02:21 »
жалко что нет команды для написания текстовых строк аналогичной acedGrDraw :(.
Напиши алфавит в виде отрезков и рисуй их при помощи acedGrDraw (а еще лучше acedGrVecs). В очень древние времена я такое делал на лиспе.
так что решил пока вернуться обратно на acedGrDraw (помечать крестиками узлы). по крайней мере не блымает при перерисовке
Ну крестики наверное особенно не будут блымать если их рисовать geometry().polyline
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: рисование внутри monitorInputPoint
« Ответ #11 : 22-11-2018, 15:03:28 »
Напиши алфавит в виде отрезков и рисуй их при помощи acedGrDraw
ой, что-то мне лениво :) особенно высчитывать точки аппроксимирующих отрезков для дуговых сегментов.

Ну крестики наверное особенно не будут блымать если их рисовать geometry().polyline
ну квадратик то блымает, хоть он нарисован через полигон. и текст блымает. думаю, если переделать на полилинию, то ничего не поменяется. а вот если это всё взять и представить в масштабах полилинии точек на... 2-3 тысячи :) то и в туалет сходить можно, пока перерисует через geometry(). а у acedGrDraw таких проблем не заметил.

ps: интересно, что скажут автодесковцы. скорей всего что-то типа "если не работает, то так и задумывалось. тем более, что прошло уже 10 лет с того момента как оно работало" или посоветуют делать через overrule :)

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #12 : 22-11-2018, 15:12:45 »
ой, что-то мне лениво :) особенно высчитывать точки аппроксимирующих отрезков для дуговых сегментов.
Ну можно было бы обойтись и без дуговых сегментов. Выбрать какой-нибудь shx-файл попроще и конвертировать его в свою структуру (а можно и не конвертировать, а читать на лету)
а вот если это всё взять и представить в масштабах полилинии точек на... 2-3 тысячи :) то и в туалет сходить можно, пока перерисует через geometry().
А вот тут хитро. Нужно анализировать результат geometry().polygon (или любой другой метод рисования). И если он возвращает false, то немедленно выходить из метода monitorInputPoint без продолжения рисования.
интересно, что скажут автодесковцы. скорей всего что-то типа "если не работает, то так и задумывалось. тем более, что прошло уже 10 лет с того момента как оно работало"
Ну тогда я рисовал только один заполненный прямоугольник - мне не приходило в голову рисовать грипсы сразу во всех вершинах, которых у меня бывают десятки тысяч.
или посоветуют делать через overrule :)
Очень вероятно. Но у overrule есть свой прикол - насколько я помню требуется регенерация чертежа при её включении/выключении.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Николай Горлов 26-11-2018, 10:48:41

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: рисование внутри monitorInputPoint
« Ответ #13 : 24-11-2018, 01:03:41 »
Получил ответ из ADN DevHelp от "Архитектора Point Input Graphics" :D
Вкратце смысл его в том, что в этой временной графике реализован минимум, в который залитые полилинии не входят. Реализовано всего несколько методов. Пожелание добавлено, но нужен bisness case. Честно говоря я не вижу в нём смысла, с учетом всех вышеописанных соображений.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: рисование внутри monitorInputPoint
« Ответ #14 : 26-11-2018, 10:48:35 »
Получил ответ из ADN DevHelp от "Архитектора Point Input Graphics" :D
Вкратце смысл его в том, что в этой временной графике реализован минимум, в который залитые полилинии не входят. Реализовано всего несколько методов. Пожелание добавлено, но нужен bisness case. Честно говоря я не вижу в нём смысла, с учетом всех вышеописанных соображений.
м-да... может действительно сделать класс по рисованию текстов через acedGr, а то вдруг их минимум в следующих версиях "усохнется" еще и на тексты ))). пасибки за помощь. делать bisness case смысла нет.