движение по оси AcDbMline

Автор Тема: движение по оси AcDbMline  (Прочитано 4367 раз)

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

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

  • ADN Club
  • ***
  • Сообщений: 156
  • Карма: 8
  • Skype: begiz_i
движение по оси AcDbMline
« : 14-08-2019, 10:07:35 »
Доброго времени суток.
Возникла необдимость двигаться по мултилинии через заданые промежутки по оси и проставлять "заклёпки".
С полинией всё понятно, getPointAtDist.
А тут как? Объект ведь не от AcDbCurve проиходит
Взрывать её как-то совсем не хочется...

Отмечено как Решение begiz 14-08-2019, 11:55:00

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: движение по оси AcDbMline
« Ответ #1 : 14-08-2019, 11:51:44 »
Взрывать её как-то совсем не хочется...
Взрывать ничего не надо. Проходишься по всем вершинам, используя AcDbMline::vertexAt и получаешь массив вершин. По ним строишь AcDbPolyline (временную в памяти - в базу её добавлять не нужно). Ну и дальше:
С полинией всё понятно, getPointAtDist.
После этого временную полилинию уничтожаешь (delete, а не erase()).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • ***
  • Сообщений: 156
  • Карма: 8
  • Skype: begiz_i
Re: движение по оси AcDbMline
« Ответ #2 : 14-08-2019, 11:54:56 »
Спасибо,
как раз к этому и пришел :)

Оффлайн Debalance

  • ADN Club
  • ****
  • Сообщений: 421
  • Карма: 16
    • Advanced software for AutoCAD
  • Skype: Debalance
Re: движение по оси AcDbMline
« Ответ #3 : 14-08-2019, 12:48:30 »
По ним строишь AcDbPolyline
На мой взгляд AcGePolyline2d более дешёвый вариант в данной связи.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: движение по оси AcDbMline
« Ответ #4 : 14-08-2019, 14:20:32 »
На мой взгляд AcGePolyline2d более дешёвый вариант в данной связи.
Ну если учесть, что AcGePolyline2d - это сплайн, и кроме того прямого метода типа getPointAtDist у него нет, то вряд ли...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Debalance

  • ADN Club
  • ****
  • Сообщений: 421
  • Карма: 16
    • Advanced software for AutoCAD
  • Skype: Debalance
Re: движение по оси AcDbMline
« Ответ #5 : 14-08-2019, 14:31:05 »
Ну если учесть, что AcGePolyline2d - это сплайн
Это вопрос терминологий. Полилиния - частный случая сплайна.

прямого метода типа getPointAtDist у него нет
И что из этого? AcGeCurve2d::paramAtLength и AcGeCurve2d::evalPoint в помощь.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: движение по оси AcDbMline
« Ответ #6 : 14-08-2019, 15:03:52 »
Это вопрос терминологий. Полилиния - частный случая сплайна.
Да. Но сложность вычислений (внутренних) повышается... Думаю, что если поэкспериментировать, то выигрыша в скорости не будет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Debalance

  • ADN Club
  • ****
  • Сообщений: 421
  • Карма: 16
    • Advanced software for AutoCAD
  • Skype: Debalance
Re: движение по оси AcDbMline
« Ответ #7 : 14-08-2019, 16:04:28 »
... то выигрыша в скорости не будет.
Это весьма спорно. AcDb - довольно "весомая" сущность. Может статься так, что время на создание/удаление такого объекта покроет все вычислительные процессы.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: движение по оси AcDbMline
« Ответ #8 : 15-08-2019, 13:55:10 »
... то выигрыша в скорости не будет.
Это весьма спорно. AcDb - довольно "весомая" сущность. Может статься так, что время на создание/удаление такого объекта покроет все вычислительные процессы.
В данном случае ты оказался неправ. Интересно было перепроверить. В моих тестах скорость с AcDb в 3.5 раза выше чем с AcGe на одних и тех же данных. Вот тестовый код. Если интересно - перепроверь (и может сможешь оптимизировать):

Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.cpp
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #include "resource.h"
  6. #include <dbobjptr2.h>
  7. #include <omp.h>
  8. //-----------------------------------------------------------------------------
  9. #define szRDS _RXST("")
  10.  
  11. //-----------------------------------------------------------------------------
  12. //----- ObjectARX EntryPoint
  13. class CAddDynamicPropertyApp : public AcRxArxApp {
  14.  
  15. public:
  16.   CAddDynamicPropertyApp() : AcRxArxApp() {}
  17.  
  18.   virtual AcRx::AppRetCode On_kInitAppMsg(void *pkt) {
  19.     AcRx::AppRetCode retCode = AcRxArxApp::On_kInitAppMsg(pkt);
  20.     return (retCode);
  21.   }
  22.  
  23.   virtual AcRx::AppRetCode On_kUnloadAppMsg(void *pkt) {
  24.     AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadAppMsg(pkt);
  25.     return (retCode);
  26.   }
  27.  
  28.   virtual void RegisterServerComponents() { }
  29.  
  30.   static void RivilisTestAcDbAcGe() {
  31.  
  32.     ads_name en; ads_point p;
  33.     while (acedEntSel(L"\nВыберите мультилинию", en, p) == RTNORM)
  34.     {
  35.       AcDbObjectId id; acdbGetObjectId(id, en);
  36.       if (!id.objectClass()->isDerivedFrom(AcDbMline::desc()))
  37.       {
  38.         acutPrintf(L"\nЭто не мультилиния! Повторите выбор.");
  39.         continue;
  40.       }
  41.       AcDbSmartObjectPointer<AcDbMline> pMline(id, AcDb::kForRead);
  42.       if (pMline.openStatus() == Acad::eOk)
  43.       {
  44.         AcGePoint3dArray pts;
  45.         for (int i = 0; i < pMline->numVertices(); i++) pts.append(pMline->vertexAt(i));
  46.         AcGePoint3dArray ptsAxis1;
  47.         double d_start = omp_get_wtime();
  48.         for (int i = 0; i < 1000; i++) GetAcDb(ptsAxis1, pts);
  49.         acutPrintf(L"\nTime AcDb = %g", omp_get_wtime() - d_start);
  50.         AcGePoint3dArray ptsAxis2;
  51.         d_start = omp_get_wtime();
  52.         for (int i = 0; i < 1000; i++) GetAcGe(ptsAxis2, pts);
  53.         acutPrintf(L"\nTime AcGe = %g", omp_get_wtime() - d_start);
  54.         for (int i = 0; i < min(ptsAxis1.length(), ptsAxis2.length()); i++)
  55.         {
  56.           acutPrintf(L"\nDist[%d]=%g", i, (ptsAxis1[i]-ptsAxis2[i]).length());
  57.         }
  58.         break;
  59.       }
  60.     }
  61.   }
  62.  
  63.   static void GetAcDb(AcGePoint3dArray &ptsAxis, AcGePoint3dArray &pts)
  64.   {
  65.     AcDbPolyline poly(pts.length() + 1);
  66.     for (int i = 0; i < pts.length(); i++)
  67.     {
  68.       AcGePoint2d p(pts[i].x, pts[i].y);
  69.       poly.addVertexAt(i, p);
  70.     }
  71.     ptsAxis.setLogicalLength(0); ptsAxis.setPhysicalLength(100);
  72.     double pEnd = 0, pLength = 0;
  73.     poly.getEndParam(pEnd); poly.getDistAtParam(pEnd, pLength);
  74.  
  75.     for (double d = 0; d < pLength; d += pLength * 0.01)
  76.     {
  77.       AcGePoint3d p; poly.getPointAtDist(d, p);
  78.       ptsAxis.append(p);
  79.     }
  80.   }
  81.  
  82.   static void GetAcGe(AcGePoint3dArray &ptsAxis, AcGePoint3dArray &pts)
  83.   {
  84.     AcGePolyline3d poly(pts);
  85.     ptsAxis.setLogicalLength(0); ptsAxis.setPhysicalLength(100);
  86.     double pLength = poly.length(poly.startParam(), poly.endParam());
  87.  
  88.     for (double d = 0; d < pLength; d += pLength * 0.01)
  89.     {
  90.       ptsAxis.append(poly.evalPoint(poly.paramAtLength(0, d)));
  91.     }
  92.   }
  93. };
  94.  
  95. //-----------------------------------------------------------------------------
  96. IMPLEMENT_ARX_ENTRYPOINT(CAddDynamicPropertyApp)
  97.  
  98. ACED_ARXCOMMAND_ENTRY_AUTO(CAddDynamicPropertyApp, Rivilis, TestAcDbAcGe, TestAcDbAcGe, ACRX_CMD_MODAL, NULL)

И вот результат на моём чертеже (значения точек совпадали до 14 знака):





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

Оффлайн Debalance

  • ADN Club
  • ****
  • Сообщений: 421
  • Карма: 16
    • Advanced software for AutoCAD
  • Skype: Debalance
Re: движение по оси AcDbMline
« Ответ #9 : 15-08-2019, 14:22:17 »
В моих тестах скорость с AcDb в 3.5 раза выше чем с AcGe на одних и тех же данных.
Весьма любопытно!