Ошибка intersectWith()

Автор Тема: Ошибка intersectWith()  (Прочитано 6100 раз)

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

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

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

  • ADN OPEN
  • Сообщений: 27
  • Карма: 0
Ошибка intersectWith()
« : 11-05-2024, 20:55:28 »
Добрый. Если выбрать 2 не пересекающихся объекта, функция работает, как задумано. Если выбрать пересекающиеся объекты, то после выхода из функции вылетает ошибка.
Код - C++ [Выбрать]
  1. void F4()
  2. {
  3.         int es1, es2;
  4.         ads_name ent1, ent2;
  5.         ads_point pt1, pt2;
  6.         AcDbObjectId entId1, entId2;
  7.         AcDbEntity* pEnt1 = NULL;
  8.         AcDbEntity* pEnt2 = NULL;
  9.         AcGePoint3dArray points;
  10.  
  11.         if (acedEntSel(L"\nУкажите объект 1: ", ent1, pt1) != RTNORM)
  12.                 return;
  13.  
  14.         if (acdbGetObjectId(entId1, ent1) != Acad::eOk)
  15.                 return;
  16.  
  17.         if (acdbOpenAcDbEntity(pEnt1, entId1, AcDb::kForRead) != Acad::eOk)
  18.                 return;
  19.  
  20.         if (acedEntSel(L"\nУкажите объект 2: ", ent2, pt2) != RTNORM)
  21.         {
  22.                 pEnt1->close();
  23.                 return;
  24.         }
  25.  
  26.         if (acdbGetObjectId(entId2, ent2) != Acad::eOk)
  27.         {
  28.                 pEnt1->close();
  29.                 return;
  30.         }
  31.  
  32.         if (acdbOpenAcDbEntity(pEnt2, entId2, AcDb::kForRead) != Acad::eOk)
  33.         {
  34.                 pEnt1->close();
  35.                 return;
  36.         }
  37.  
  38.         if (pEnt1->intersectWith(pEnt2, AcDb::kOnBothOperands, points) != Acad::eOk)
  39.                 return;
  40.  
  41.         if (points.length() == 0)
  42.                 acutPrintf(L"\nОбъекты не пересекаются. ");
  43.  
  44.         else
  45.         {
  46.                 acutPrintf(L"\nТочки пересечения:");
  47.                 for (int i = 0; i < points.length(); ++i)
  48.                         acutPrintf(L"\n %d: %.6f %.6f %.6f", i + 1, points[i].x, points[i].y, points[i].z);
  49.         }
  50.  
  51.         pEnt1->close();
  52.         pEnt2->close();
  53.  
  54.         return;
  55. }



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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Ошибка intersectWith()
« Ответ #1 : 11-05-2024, 21:27:44 »
Я смотрю, что в твоем коде далеко не всегда вызывается метод pEnt1->close() и pEnt2->close() - а именно в случае если объекты не пересекаются.
Очень рекомендую использовать интеллектуальные указатели (типа AcDbObjectPointer<AcDbLine> или AcDbEntityPointer)
Они автоматически закроют объект (вызовут его метод close()) по выходе из области видимости локальной переменной.

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

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

  • ADN OPEN
  • Сообщений: 27
  • Карма: 0
Re: Ошибка intersectWith()
« Ответ #2 : 11-05-2024, 23:31:12 »
Я смотрю, что в твоем коде далеко не всегда вызывается метод pEnt1->close() и pEnt2->close() - а именно в случае если объекты не пересекаются.
Как я понимаю, закрытие производится только после успешного открытия через acdbOpenAcDbEntity(). Любой код ошибки - объект не открылся, закрывать, соответственно, нечего. Например:
- открыли объект через acdbOpenAcDbEntity();
- выполнили необходимые манипуляции с объектом, в моем случае intersectWith();
- независимо от результата intersectWith() объекты закрыли в 51, 52 строках через close();
Поэтому не понял замечание.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Ошибка intersectWith()
« Ответ #3 : 11-05-2024, 23:35:26 »
- независимо от результата intersectWith() объекты закрыли в 51, 52 строках через close();
Да? Ты уверен? :) Посмотри на строки 38 и 39.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 27
  • Карма: 0
Re: Ошибка intersectWith()
« Ответ #4 : 12-05-2024, 08:51:41 »
Посмотри на строки 38 и 39.
Добавил,
Код - C++ [Выбрать]
  1. if (pEnt1->intersectWith(pEnt2, AcDb::kOnBothOperands, points) != Acad::eOk)
  2.         {
  3.                 pEnt1->close();
  4.                 pEnt2->close();
  5.                 return;
  6.         }
Только функция в случае наличия и отсутствия общих точек срабатывает правильно. Если после нее добавить
Код - C++ [Выбрать]
  1. AcGePoint3d acGePoint3d=points[0];
Там будет точка с правильными координатами.
У меня ошибка вылетает не во время выполнения вызова какой-либо из функций, а после завершения основной функции F4().

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Ошибка intersectWith()
« Ответ #5 : 12-05-2024, 15:30:34 »
pucher,
Похоже, что это проблема при распределении памяти. Попробуй компиляцию в Release, а не в Debug.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Ошибка intersectWith()
« Ответ #6 : 12-05-2024, 16:06:46 »
Решил проверить у себя, благо версия AutoCAD 2013 x64 у меня есть:
Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.cpp
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #include "resource.h"
  6.  
  7. //-----------------------------------------------------------------------------
  8. #define szRDS _RXST("")
  9.  
  10. //-----------------------------------------------------------------------------
  11. //----- ObjectARX EntryPoint
  12. class CTestIntersect2013App : public AcRxArxApp {
  13.  
  14. public:
  15.   CTestIntersect2013App () : AcRxArxApp () {}
  16.  
  17.   virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
  18.     AcRx::AppRetCode retCode = AcRxArxApp::On_kInitAppMsg (pkt) ;
  19.     return (retCode) ;
  20.   }
  21.  
  22.   virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
  23.     AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadAppMsg (pkt) ;
  24.     return (retCode) ;
  25.   }
  26.  
  27.   virtual void RegisterServerComponents () {}
  28.  
  29.  
  30.   // - TestIntersect2013.TestInt command (do not rename)
  31.   static void TestIntersect2013TestInt(void)
  32.   {
  33.     F4();
  34.   }
  35.  
  36.   static void F4()
  37.   {
  38.     int es1, es2;
  39.     ads_name ent1, ent2;
  40.     ads_point pt1, pt2;
  41.     AcDbObjectId entId1, entId2;
  42.     AcGePoint3dArray points;
  43.  
  44.     if (acedEntSel(L"\nУкажите объект 1: ", ent1, pt1) != RTNORM)
  45.       return;
  46.  
  47.     if (acdbGetObjectId(entId1, ent1) != Acad::eOk)
  48.       return;
  49.  
  50.     AcDbEntityPointer pEnt1(entId1, AcDb::kForRead);
  51.  
  52.     if (pEnt1.openStatus() != Acad::eOk)
  53.       return;
  54.  
  55.     if (acedEntSel(L"\nУкажите объект 2: ", ent2, pt2) != RTNORM)
  56.       return;
  57.  
  58.     if (acdbGetObjectId(entId2, ent2) != Acad::eOk)
  59.       return;
  60.  
  61.     AcDbEntityPointer pEnt2(entId2, AcDb::kForRead);
  62.     if (pEnt2.openStatus() != Acad::eOk)
  63.       return;
  64.  
  65.     if (pEnt1->intersectWith(pEnt2, AcDb::kOnBothOperands, points) != Acad::eOk || (points.length() == 0))
  66.     {
  67.       acutPrintf(L"\nОбъекты не пересекаются. ");
  68.       return;
  69.     }
  70.  
  71.     acutPrintf(L"\nТочки пересечения:");
  72.     for (int i = 0; i < points.length(); i++)
  73.       acutPrintf(L"\n %d: %.6f %.6f %.6f", i + 1, points[i].x, points[i].y, points[i].z);
  74.   }
  75. } ;
  76.  
  77. //-----------------------------------------------------------------------------
  78. IMPLEMENT_ARX_ENTRYPOINT(CTestIntersect2013App)
  79.  
  80. ACED_ARXCOMMAND_ENTRY_AUTO(CTestIntersect2013App, TestIntersect2013, TestInt, TestInt, ACRX_CMD_TRANSPARENT, NULL)
  81.  

Все нормально работает без ошибок. Кстати, на похожую ошибку я натолкнулся, когда у меня вместо Platform Toolset = v100 стояло v90.
В этом случае неправильно работает диспетчер памяти и возможны непредсказуемые ошибки.
На всякий случай прикладываю готовый проект.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 27
  • Карма: 0
Re: Ошибка intersectWith()
« Ответ #7 : 12-05-2024, 19:23:10 »
Попробуй компиляцию в Release, а не в Debug.
В Release сработало. Это навело на мысль, что причина м.б. в разных настройках проекта для Release, Debug версий проекта. В скаченном ObjectARX 2013 SDK нет Arx Wizzard. Поэтому проект создаю "с ноля". По умолчанию Visual Studio "Runtime library" для Release выставляет Multi-threaded DLL (/MD), для Debug - Multi-threaded Debug DLL (/MDd). Установка для Debug значения в Multi-threaded DLL (/MD) убрало ошибку, всё работает. Только не понятна логика  ???. Ведь при отладке обычно используются debug версии всевозможных библиотек, задействованных в проекте. А тут такая ситуация. Хотелось бы узнать объяснение, если оно есть.

Отмечено как Решение pucher 12-05-2024, 20:14:59

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Ошибка intersectWith()
« Ответ #8 : 12-05-2024, 19:35:45 »
Только не понятна логика. Ведь при отладке обычно используются debug версии всевозможных библиотек, задействованных в проекте. А тут такая ситуация. Хотелось бы узнать объяснение, если оно есть.

Тут всё очень просто - сам AutoCAD скомпилирован в Release. Соответственно он использует Multi-threaded DLL (/MD). Смешивание вместе Multi-threaded Debug DLL (/MDd) с Multi-threaded DLL (/MD) приводит к ошибкам распределения памяти и др. Чтобы обойти эти ошибки можно использовать такой трюк. В файле stdafx.h в начале вставляем:
Код - C++ [Выбрать]
  1. #if defined( _DEBUG) && !defined(DEBUG_AUTOCAD)
  2.     #pragma message("Building debug version of arx to be used with non-debug/Prod AutoCAD")
  3.     #define _DEBUG_WAS_DEFINED
  4.     #undef _DEBUG
  5. #endif

А в конце:
Код - C++ [Выбрать]
  1. #ifdef _DEBUG_WAS_DEFINED
  2.     #define _DEBUG
  3.     #undef _DEBUG_WAS_DEFINED
  4. #endif
  5.  

В этом случае можно использовать и Multi-threaded Debug DLL (/MDd)

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

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Ошибка intersectWith()
« Ответ #9 : 12-05-2024, 19:45:38 »
В скаченном ObjectARX 2013 SDK нет Arx Wizzard
Он есть здесь: http://images.autodesk.com/adsk/files/objectarx_wizards_2013.zip
Разблокировать и устанавливать от имени Администратора.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение