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

06/06/2015

Динамически размеры при помощи GripOverrule

Динамические размеры – это простой и интуитивно удобный способ дать возможность пользователю изменять примитивы при редактировании при помощи «ручек». Для того чтобы это работало необходимо установить системную переменную DYNMODE в значение 2 или 3. Если вы хотите изменить обычное поведение редактирования при помощи «ручек» и указать другой размер, что интуитивно и удобно для пользователя – Grip Overrule поможет вам в этом.

Для окружности, когда «ручка» выбрана, появляется запрос значения радиуса в динамическом размере. Следующий пример кода меняет стандартное поведение. При выборе «ручки» у пользователя спрашивается диаметр окружности и динамический размер помещается горизонтально в центре окружности. Также в командной строке отображается новое, введенное пользователем, значение диаметра.

Вот так это выглядит при включенном и выключенном Grip Overrule:

 

 

Исходный код:

Код - C++: [Выделить]
  1. #include  "dbentityoverrule.h"
  2.  
  3. class  CMyGripOverrule: public  AcDbGripOverrule
  4. {
  5.  
  6. public :
  7.   static  CMyGripOverrule* _pTheOverrule;
  8.  
  9.   ACRX_DECLARE_MEMBERS(CMyGripOverrule);
  10.  
  11.   static  AcDbDimData *mpDimData;
  12.  
  13.   static  void  CMyGripOverrule::AddOverrule()
  14.   {
  15.     mpDimData = NULL;
  16.  
  17.     if (_pTheOverrule != NULL)
  18.       return ;
  19.  
  20.     _pTheOverrule = new  CMyGripOverrule();
  21.  
  22.     AcRxOverrule::addOverrule(
  23.       AcDbCircle::desc(),
  24.       _pTheOverrule,
  25.       true
  26.     );
  27.  
  28.     CMyGripOverrule::setIsOverruling(true );
  29.   }
  30.  
  31.   static  void  CMyGripOverrule::RemoveOverrule()
  32.   {
  33.     if (_pTheOverrule == NULL)
  34.       return ;
  35.  
  36.     CMyGripOverrule::setIsOverruling(false );
  37.  
  38.     AcRxOverrule::removeOverrule(
  39.       AcDbCircle::desc(),
  40.       _pTheOverrule
  41.     );
  42.  
  43.     delete  _pTheOverrule;
  44.     _pTheOverrule = NULL;
  45.   }
  46.  
  47.   ACDB_PORT Acad::ErrorStatus moveGripPointsAt(
  48.     AcDbEntity* pSubject,
  49.     const  AcDbVoidPtrArray& gripAppData,
  50.     const  AcGeVector3d& offset,
  51.     const  int  bitflags)
  52.   {
  53.     if  (!pSubject->isKindOf(AcDbCircle::desc()))
  54.       return  Acad::eOk;
  55.  
  56.     AcDbCircle* pCircle = AcDbCircle::cast(pSubject);
  57.  
  58.     if  (pCircle == NULL)
  59.       return  Acad::eOk;
  60.  
  61.     AcGeVector3d normal = pCircle->normal();
  62.     AcGeVector3d horizDir = normal.perpVector();
  63.     AcGePoint3d center = pCircle->center();
  64.     double  radius = pCircle->radius();
  65.  
  66.     AcGePoint3d pt1 = center + radius * horizDir;
  67.     pt1 = pt1 + offset;
  68.     AcGeVector3d radVec = pt1 - center;
  69.  
  70.     updateDimensions(pCircle,  center-radVec, center+radVec);
  71.  
  72.     AcDbGripOverrule::moveGripPointsAt(
  73.       pSubject,
  74.       gripAppData,
  75.       offset,
  76.       bitflags);
  77.  
  78.   }
  79.  
  80.  
  81.  
  82.   ACDB_PORT Acad::ErrorStatus getGripPoints(
  83.     const  AcDbEntity* pSubject,
  84.     AcDbGripDataPtrArray& grips,
  85.     const  double  curViewUnitSize,
  86.     const  int  gripSize,
  87.     const  AcGeVector3d& curViewDir,
  88.     const  int  bitflags
  89.   )
  90.   {
  91.  
  92.     if  (!pSubject->isKindOf(AcDbCircle::desc()))
  93.       return  Acad::eOk;
  94.  
  95.     AcDbCircle* pCircle
  96.       = AcDbCircle::cast(pSubject);
  97.  
  98.     if  (pCircle == NULL)
  99.       return  Acad::eOk;
  100.  
  101.     AcDbGripDataPtrArray oldGrips;
  102.  
  103.     AcDbGripOverrule::getGripPoints(
  104.       pSubject, oldGrips,
  105.       curViewUnitSize, gripSize,
  106.       curViewDir, bitflags);
  107.  
  108.     AcDbGripData * pGripData
  109.       = new  AcDbGripData(*(oldGrips.at(1)));
  110.  
  111.     pGripData->setGripPoint(oldGrips.at(1)->gripPoint());
  112.  
  113.     pGripData->setHotGripDimensionFunc(MyGripHotGripDimensionfunc);
  114.  
  115.     pGripData->setHoverDimensionFunc(MyHoverGripDimensionfunc);
  116.    
  117.     pGripData->setCLIPromptFunc(MyGripCLIPromptCallback);
  118.  
  119.     grips.append(pGripData);
  120.  
  121.     return  Acad::eOk;
  122.   }
  123.  
  124.   static  void  gripDimensionCbackFunc(
  125.     AcDbGripData* pGrip,
  126.     const  AcDbObjectId& objId,
  127.     double  dimScale,
  128.     AcDbDimDataPtrArray& dimDataArr)
  129.   {
  130.  
  131.     Acad::ErrorStatus es;
  132.  
  133.     if  (pGrip == NULL)
  134.       return ;
  135.  
  136.  
  137.  
  138.     AcDbEntity *pEnt = NULL;
  139.  
  140.     if  (acdbOpenAcDbEntity(
  141.       pEnt, objId,
  142.       AcDb::kForRead) != Acad::eOk)
  143.       return ;
  144.  
  145.  
  146.  
  147.     AcDbCircle *pCircle
  148.       = AcDbCircle::cast(pEnt);
  149.  
  150.     if  (pCircle == NULL) {
  151.       pEnt->close();
  152.       return ;
  153.     }
  154.  
  155.  
  156.  
  157.     AcGeVector3d normal = pCircle->normal();
  158.     AcGeVector3d horizDir = normal.perpVector();
  159.     AcGeVector3d vertDir  = normal.crossProduct(horizDir);
  160.     AcGePoint3d center = pCircle->center();
  161.     double  radius = pCircle->radius();
  162.  
  163.     pCircle->close();
  164.  
  165.     AcDbAlignedDimension *pAlignedDim
  166.       = new  AcDbAlignedDimension();
  167.  
  168.     pAlignedDim->setDatabaseDefaults();
  169.  
  170.     es = pAlignedDim->setDimsah(true );
  171.     es = pAlignedDim->setDimse1(true );
  172.     es = pAlignedDim->setDimblk1(_T("None" ));
  173.     es = pAlignedDim->setNormal(normal);
  174.     es = pAlignedDim->setElevation(0.0);
  175.     es = pAlignedDim->setHorizontalRotation(0.0);
  176.     es = pAlignedDim->setXLine1Point(center - radius * horizDir);
  177.     es = pAlignedDim->setXLine2Point(center + radius * horizDir);
  178.     es = pAlignedDim->setDimLinePoint(center + 0.5 * radius * horizDir);
  179.     es = pAlignedDim->setDynamicDimension(true );
  180.     es = pAlignedDim->setColorIndex(1);
  181.  
  182.     AcDbDimData *pDimData
  183.       = new  AcDbDimData(pAlignedDim);
  184.  
  185.     es = pDimData->setOwnerId(objId);
  186.     es = pDimData->setDimFocal(true );
  187.     es = pDimData->setDimEditable(true );
  188.     es = pDimData->setDimRadius(true );
  189.     es = pDimData->setDimHideIfValueIsZero(true );
  190.     es = pDimData->setDimValueFunc(setDimValueCbackFunc);
  191.     es = pDimData->setDimension(pAlignedDim);
  192.  
  193.     dimDataArr.append(pDimData);
  194.     mpDimData = pDimData;
  195.   }
  196.  
  197.   bool  isApplicable(
  198.     const  AcRxObject *pOverruledSubject) const
  199.   {
  200.     if  (!pOverruledSubject->isKindOf (AcDbCircle::desc())) return  false ;
  201.     return  true ;
  202.   }
  203.  
  204.  
  205.  
  206.   static  const  ACHAR* MyGripCLIPromptCallback
  207.     (AcDbGripData *pGripData)
  208.   {
  209.     return  ACRX_T("\nДиаметр окружности: " );
  210.   }
  211.  
  212.   static  void  MyGripHotGripDimensionfunc
  213.     (AcDbGripData *pGripData,
  214.     const  AcDbObjectId &entId,
  215.     double  dimScale,
  216.     AcDbDimDataPtrArray &dimDataArr)
  217.   {
  218.     gripDimensionCbackFunc(pGripData, entId, dimScale, dimDataArr);
  219.   }
  220.  
  221.  
  222.  
  223.   static  void  MyHoverGripDimensionfunc
  224.     (AcDbGripData *pGripData,
  225.     const  AcDbObjectId &entId,
  226.     double  dimScale,
  227.     AcDbDimDataPtrArray &dimDataArr)
  228.   {
  229.     gripDimensionCbackFunc(pGripData, entId, dimScale, dimDataArr);
  230.   }
  231.  
  232.  
  233.  
  234.   static  AcGeVector3d setDimValueCbackFunc
  235.     (AcDbDimData* pDimData, AcDbEntity* pEnt,
  236.     double  newValue, const  AcGeVector3d& offset)
  237.   {
  238.  
  239.     AcGeVector3d newOffset(offset);
  240.  
  241.     if  ((pDimData == NULL) || (pEnt == NULL))
  242.       return  newOffset;
  243.  
  244.     AcDbObjectId objId;
  245.  
  246.     AcDbCircle *pCir = AcDbCircle::cast(pEnt);
  247.  
  248.     if  (pCir == NULL)
  249.       return  newOffset;
  250.  
  251.     pCir->setRadius(newValue * 0.5);
  252.  
  253.     return  newOffset;
  254.   }
  255.  
  256.  
  257.  
  258.   static  bool  updateDimensions (AcDbCircle* pCircle, AcGePoint3d xline1Pt, AcGePoint3d xline2Pt)
  259.   {
  260.     if  (!pCircle || !mpDimData)
  261.       return  false ;
  262.  
  263.  
  264.     AcDbObjectId entId = pCircle->objectId();
  265.     AcGeVector3d normal = pCircle->normal();
  266.     AcGeVector3d horizDir = normal.perpVector();
  267.     AcGeVector3d vertDir  = normal.crossProduct(horizDir);
  268.     AcGePoint3d center = pCircle->center();
  269.  
  270.     double  radius = pCircle->radius();
  271.  
  272.     AcDbObjectId ownerId;
  273.  
  274.     AcDbDimData *pDimData = mpDimData;
  275.  
  276.     AcDbAlignedDimension *pAlignedDim = AcDbAlignedDimension::cast(pDimData->dimension());
  277.  
  278.     if (pAlignedDim != NULL)
  279.     {
  280.       pAlignedDim->setXLine1Point(xline1Pt);
  281.       pAlignedDim->setXLine2Point(xline2Pt);
  282.       pAlignedDim->setDimLinePoint(xline1Pt + (xline2Pt - xline1Pt) * 0.5);
  283.     }
  284.     return  true ;
  285.   }
  286. };
  287.  
  288. AcDbDimData * CMyGripOverrule::mpDimData = NULL;
  289. CMyGripOverrule* CMyGripOverrule::_pTheOverrule = NULL;
  290.  
  291. ACRX_NO_CONS_DEFINE_MEMBERS( CMyGripOverrule,  AcDbGripOverrule);

 

Источник: http://adndevblog.typepad.com/autocad/2015/06/dynamic-dimension-using-gripoverrule.html

Автор перевода: Александр Ривилис

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

Опубликовано 06.06.2015