ADN Open CIS
Сообщество программистов Autodesk в СНГ

16/05/2013

Поддержка команды ПОДЕЛИ (DIVIDE) в собственном примитиве

Вопрос:
Как обеспечить поддержку моим примитивом команды AutoCAD ПОДЕЛИ (DIVIDE)?

Ответ:
Чтобы обеспечить поддержку моим примитивом команды ПОДЕЛИ (DIVIDE) необходимо унаследовать его от класса AcDbCurve или одного из его производных классов. Минимальное количество методов, которое следует переопределить для работы команды ПОДЕЛИ (DIVIDE):

Acad::ErrorStatus getStartParam(double& startParam) const;
Acad::ErrorStatus getEndParam(double& endParam) const;
Acad::ErrorStatus getDistAtParam (double param, double& dist)  const;
Acad::ErrorStatus getPointAtDist(double dist, AcGePoint3d& point) const;
Acad::ErrorStatus getPointAtParam(double param, AcGePoint3d& point) const;

 

В качестве примера того как переопределить эти методы рассмотрим пример PolySamp из ObjectARX SDK. Этот собственный примитив – просто замкнутый многоугольник.

 

Соответствующие переопределённые методы:

Код - C++: [Выделить]
  1. virtual Acad::ErrorStatus
  2.         getStartParam  (double& startParam)     const
  3. {
  4.     assertReadEnabled();
  5.     startParam = 0.0;
  6.     return Acad::eOk;
  7. }
  8.  
  9. virtual Acad::ErrorStatus          getEndParam  (double& endParam)    const
  10. {
  11.     assertReadEnabled();
  12.     //замкнутая полилиния. Так что конечный параметр: 2* PI
  13.  
  14.     endParam = 6.28318530717958647692;
  15.     return Acad::eOk;
  16. }
  17.  
  18. Acad::ErrorStatus AsdkPoly::getDistAtParam(
  19.                                 double param,
  20.                                 double& dist)  const
  21. {
  22.     assertReadEnabled();
  23.  
  24.     rx_fixangle(param);
  25.  
  26.     double circumRadius =
  27.         (startPoint() - center()).length();
  28.     double alpha        =
  29.         3.14159265358979323846 * 0.5 -
  30.         3.14159265358979323846 / mNumSides;
  31.     double sideLength   =
  32.         2.0 * circumRadius * cos(alpha);
  33.  
  34.     double includedAngle     =
  35.         6.28318530717958647692 / mNumSides;
  36.     int    numIncludedAngles =
  37.         int(param / includedAngle);
  38.     double theta             =
  39.         param - numIncludedAngles * includedAngle;
  40.  
  41.     if (theta > 1.0e-10) {
  42.         dist = sideLength * numIncludedAngles +
  43.                circumRadius * sin(theta) /
  44.           sin(3.14159265358979323846 - theta - alpha);
  45.     } else {
  46.         dist = sideLength * numIncludedAngles;
  47.     }
  48.  
  49.     return Acad::eOk;
  50. }
  51.  
  52. Acad::ErrorStatus
  53. AsdkPoly::getPointAtParam(
  54.               double param,
  55.               AcGePoint3d& point) const
  56. {
  57.     assertReadEnabled();
  58.  
  59.     Acad::ErrorStatus es = Acad::eOk;
  60.  
  61. // Узнаём сколько углов содержит "param".
  62. // Узнаём вершину и направление отрезка между этой вершиной
  63. // и следующей вершиной. Добавляем соответствующее расстояние
  64. // вдоль этого отрезка для получения новой точки.
  65.  
  66.  
  67.     rx_fixangle(param);
  68.  
  69.     double circumRadius =
  70.               (startPoint() - center()).length();
  71.     double includedAngle=
  72.               6.28318530717958647692 / mNumSides;
  73.     int    numIncludedAngles =
  74.              int(param / includedAngle);
  75.     double theta =
  76.             param - numIncludedAngles * includedAngle;
  77.  
  78.     double gamma =
  79.          3.14159265358979323846 * 0.5 +
  80.           3.14159265358979323846 / mNumSides - theta;
  81.  
  82.     double distToGo =
  83.         circumRadius * sin(theta) / sin(gamma);
  84.  
  85.     AcGeVector3d lineDir  =
  86.            sideVector(numIncludedAngles);
  87.  
  88.     AcGePoint3dArray vertexArray;
  89.     if ((es =
  90.           getVertices3d(vertexArray)) != Acad::eOk) {
  91.         return es;
  92.     }
  93.  
  94.     if (theta > 1.0e-10) {
  95.         point = vertexArray[numIncludedAngles] + (distToGo * lineDir);
  96.     } else {
  97.         point = vertexArray[numIncludedAngles];
  98.     }
  99.  
  100.     return es;
  101. }

 

С помощью этих методов, когда команда ПОДЕЛИ (DIVIDE) выполняется и пользователь введёт количество сегментов для деления, например 10, AutoCAD разделит наш примитив вдоль сторон на заданное количество сегментов:

 

Источник: http://adndevblog.typepad.com/autocad/2013/02/supporting-the-divide-command-in-a-custom-entity.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=31

Опубликовано 16.05.2013
Отредактировано 05.06.2013 в 19:41:42