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

25/08/2014

Добавление пространственного фильтра к вставке блока

В этой статье сделаны небольшие исправления для существующей статьи написанной моим коллегой Xiaodongв 2013, связанные с внутренними изменениями, которые приводят к аварийному завершению AutoCAD 2015 на 32-разрядных машинах. Чтобы предотвратить это я написал универсальный код.

Каковы соображения для изменения кода:

Существующий код создает определение фильтра (в том числе и границу фильтра) прежде чем фильтр добавляется в базу. Это приводит к созданию неправильного типа внутреннего объекта границы. Возможны два типа объектов границы. Один из них только для использования с базами данных, открытыми в редакторе AutoCAD, а второй для баз данных не открытых в редакторе AutoCAD. Если фильтр не содержится в базе, то создается объект границы, который используется в базах, не загруженных в редактор AutoCAD. Затем при добавлении фильтра в базу данных, открытую в редакторе, он получает неправильный тип и это приводит к проблемам.

Код - C++: [Выделить]
  1. static void Test_Clip ()
  2. {
  3.   ads_point pt1, pt2;
  4.   ads_name ent;
  5.   if (acedEntSel(_T("Выберите внешнюю ссылку:"), ent, pt1) != RTNORM)
  6.     return;
  7.   AcDbObjectId idXref;
  8.   if (acdbGetObjectId(idXref,ent) != Acad::eOk)
  9.     return;
  10.   AcDbObjectPointer<AcDbBlockReference> pRef(idXref, AcDb::kForRead);
  11.   if (pRef.openStatus() != Acad::eOk) {
  12.     acutPrintf(_T("Это не внешняя ссылка!\n"));
  13.     return;
  14.   }
  15.   AcGePoint2dArray pts;
  16.   if (acedGetPoint(NULL,_T("Первая точка:"), pt1) != RTNORM) {
  17.     pRef->close();
  18.     return;
  19.   }
  20.   // ECS вершин должна быть определена в системе
  21.   // координат блока для того чтобы правильно вычислить
  22.   // матрицу преобразования между системами координат
  23.   AcGeMatrix3d mat(pRef->blockTransform());
  24.   mat.invert();
  25.   AcGePoint3d pt3d(asPnt3d(pt1));
  26.   pt3d.transformBy(mat);
  27.   pts.append(AcGePoint2d(pt3d.x, pt3d.y));
  28.   while (acedGetPoint(pt1,_T("Следующая точка:"), pt2) == RTNORM) {
  29.     acedGrDraw(pt1, pt2, 1, 1);
  30.     pt3d = asPnt3d(pt2);
  31.     pt3d.transformBy(mat);
  32.     pts.append(AcGePoint2d(pt3d.x, pt3d.y));
  33.     memcpy(pt1, pt2, sizeof(ads_point));
  34.   }
  35.   acedRedraw(NULL,0);
  36.   AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
  37.   AcGeVector3d normal;
  38.   double elev;
  39.   if (pDb->tilemode()) {
  40.     normal = pDb->ucsxdir().crossProduct(pDb->ucsydir());
  41.     elev = pDb->elevation();
  42.   } else {
  43.     normal = pDb->pucsxdir().crossProduct(pDb->pucsydir());
  44.     elev = pDb->pelevation();
  45.   }
  46.   normal.normalize();
  47.   Acad::ErrorStatus es = pRef.object()->upgradeOpen();
  48.   if (es != Acad::eOk) {
  49.     pRef->close();
  50.     return;
  51.   }
  52.   // Создаём фильтр
  53.   AcDbSpatialFilter* pFilter = new AcDbSpatialFilter;
  54.   // Добавляем его к расширенному словарю вставки блока
  55.   // Класс AcDbIndexFilterManger предоставляет для этого специальный метод
  56.   if (AcDbIndexFilterManager::addFilter(pRef.object(), pFilter) != Acad::eOk)
  57.     delete pFilter;
  58.   else {
  59.     acutPrintf(_T("Фильтр успешно добавлен!\n"));
  60.     pRef.object()->downgradeOpen();
  61.   }
  62.   if (pFilter->setDefinition(pts,normal,elev,
  63.     ACDB_INFINITE_XCLIP_DEPTH,-ACDB_INFINITE_XCLIP_DEPTH, true) != Acad::eOk)
  64.   {
  65.     acutPrintf(L"Ошибка при добавлении фильтра.");
  66.     // Удаляем фильтр в случае ошибки setDefinition.
  67.     pFilter->erase();
  68.  
  69.   }
  70.   pFilter->close();
  71.   pRef->close();
  72. }

Источник: http://adndevblog.typepad.com/autocad/2014/08/adding-a-spatial-filter-to-a-block-reference.html

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

Опубликовано 25.08.2014
Отредактировано 25.08.2014 в 15:32:50