Добавление пространственного фильтра к вставке блока
В этой статье сделаны небольшие исправления для существующей статьи написанной моим коллегой Xiaodongв 2013, связанные с внутренними изменениями, которые приводят к аварийному завершению AutoCAD 2015 на 32-разрядных машинах. Чтобы предотвратить это я написал универсальный код.Каковы соображения для изменения кода:
Существующий код создает определение фильтра (в том числе и границу фильтра) прежде чем фильтр добавляется в базу. Это приводит к созданию неправильного типа внутреннего объекта границы. Возможны два типа объектов границы. Один из них только для использования с базами данных, открытыми в редакторе AutoCAD, а второй для баз данных не открытых в редакторе AutoCAD. Если фильтр не содержится в базе, то создается объект границы, который используется в базах, не загруженных в редактор AutoCAD. Затем при добавлении фильтра в базу данных, открытую в редакторе, он получает неправильный тип и это приводит к проблемам.
- static void Test_Clip ()
- {
- ads_point pt1, pt2;
- ads_name ent;
- if (acedEntSel(_T("Выберите внешнюю ссылку:"), ent, pt1) != RTNORM)
- return;
- AcDbObjectId idXref;
- if (acdbGetObjectId(idXref,ent) != Acad::eOk)
- return;
- AcDbObjectPointer<AcDbBlockReference> pRef(idXref, AcDb::kForRead);
- if (pRef.openStatus() != Acad::eOk) {
- acutPrintf(_T("Это не внешняя ссылка!\n"));
- return;
- }
- AcGePoint2dArray pts;
- if (acedGetPoint(NULL,_T("Первая точка:"), pt1) != RTNORM) {
- pRef->close();
- return;
- }
- // ECS вершин должна быть определена в системе
- // координат блока для того чтобы правильно вычислить
- // матрицу преобразования между системами координат
- AcGeMatrix3d mat(pRef->blockTransform());
- mat.invert();
- AcGePoint3d pt3d(asPnt3d(pt1));
- pt3d.transformBy(mat);
- pts.append(AcGePoint2d(pt3d.x, pt3d.y));
- while (acedGetPoint(pt1,_T("Следующая точка:"), pt2) == RTNORM) {
- acedGrDraw(pt1, pt2, 1, 1);
- pt3d = asPnt3d(pt2);
- pt3d.transformBy(mat);
- pts.append(AcGePoint2d(pt3d.x, pt3d.y));
- memcpy(pt1, pt2, sizeof(ads_point));
- }
- acedRedraw(NULL,0);
- AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
- AcGeVector3d normal;
- double elev;
- if (pDb->tilemode()) {
- normal = pDb->ucsxdir().crossProduct(pDb->ucsydir());
- elev = pDb->elevation();
- } else {
- normal = pDb->pucsxdir().crossProduct(pDb->pucsydir());
- elev = pDb->pelevation();
- }
- normal.normalize();
- Acad::ErrorStatus es = pRef.object()->upgradeOpen();
- if (es != Acad::eOk) {
- pRef->close();
- return;
- }
- // Создаём фильтр
- AcDbSpatialFilter* pFilter = new AcDbSpatialFilter;
- // Добавляем его к расширенному словарю вставки блока
- // Класс AcDbIndexFilterManger предоставляет для этого специальный метод
- if (AcDbIndexFilterManager::addFilter(pRef.object(), pFilter) != Acad::eOk)
- delete pFilter;
- else {
- acutPrintf(_T("Фильтр успешно добавлен!\n"));
- pRef.object()->downgradeOpen();
- }
- if (pFilter->setDefinition(pts,normal,elev,
- ACDB_INFINITE_XCLIP_DEPTH,-ACDB_INFINITE_XCLIP_DEPTH, true) != Acad::eOk)
- {
- acutPrintf(L"Ошибка при добавлении фильтра.");
- // Удаляем фильтр в случае ошибки setDefinition.
- pFilter->erase();
- }
- pFilter->close();
- pRef->close();
- }
Источник: 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