Тема: Переключение UCS (ARX)

Я создаю свою UCS (AcDbUCSTableRecord), добавляю ее к AcDbUCSTable. Теперь нужно сохранить прежнюю UCS, переключиться на мою, поработать, а затем вернуть прежнюю UCS.

Вопрос:
Где хранится имя текущей UCS? AcDbViewPort::getUCS возвращает лишь оси и начало координат, а не имя.

Re: Переключение UCS (ARX)

Ачерез AcDbViewport::ucsName его найти нельзя?

Re: Переключение UCS (ARX)

Да, но AcDbViewport::ucsName возвращает константное (const) значение и подойдет лишь для того, чтобы УЗНАТЬ имя текущей UCS, а чтобы УСТАНОВИТЬ новую UCS этод метод врят ли подойдет. (::ucsName не попался мне на глаза сразу оттого, что в разделе AcDbViewport Query Functions я не смотрел. Я искал в разделе AcDbViewport Edit Functions).

Итог: Каким образом узнать имя текущей UCS ясно.
Вопрос: Каким же образом можно установить(!) имя новой UCS (тем самым переключившись на нее)?

Re: Переключение UCS (ARX)

Может быть стоит попробовать функцию setUcs(const AcDbObjectId ucsId) из раздела AcDbViewport Edit, который ты внимательно исследовал.

Re: Переключение UCS (ARX)

У меня в хелпе на ссылку AcDbViewport::setUcs он выдает лишь функцию:

Acad::ErrorStatus
setUcs(
     const AcGePoint3d& origin,
     const AcGeVector3d& xAxis,
     const AcGeVector3d& yAxis);

Причем ссылок на такие функции (AcDbViewport::setUcs) три штуки (перегруженные функции), но отчего-то по каждой из ссылок он выдает описание одной и той же функции (см. выше). Это и стало причиной вопроса.
Выходит что это ошибка только в моем хелпе?

Все равно спасибо.

Re: Переключение UCS (ARX)

Такой ненадежный хелп надо менять. Вот эти три функции:
Acad::ErrorStatus
setUcs(

     const AcGePoint3d& origin,
     const AcGeVector3d& xAxis,
     const AcGeVector3d& yAxis);

This function sets the UCS for this viewport as defined by origin, xAxis, and yAxis. The resulting UCS will be unnamed.

Acad::ErrorStatus

setUcs(

     const AcDbObjectId ucsId);

This function sets the UCS for this viewport. The new UCS will be named and UcsId must reference a valid AcDbUcsTableRecord object.

Acad::ErrorStatus

setUcs(

     AcDb::OrthographicView view);

This function sets the UCS for this viewport to the orthographic UCS defined by view (relative to UCSBASE).

Re: Переключение UCS (ARX)

Остановился там, где не ожидал:
каким образом мне получить экземпляр текущего AcDbViewPort?
(у меня есть его ID через acdbGetCurViewportObjectId())

Re: Переключение UCS (ARX)

Обычно,  указатель на объект получают при его открытии с помощью функции acdbOpenObject.

Re: Переключение UCS (ARX)

Теперь с открытием объекта ясно.

Новый вопрос: у меня мой копилятор отказывается принимать имя функции acdbGetCurViewportObjectId(), хотя в хелпе эта функция описана (находится в dbmain.h).
Может быть кто-нибудь может поробовать использовать эту функцию. Если это удасться, то значит эта функция все таки существует (а то я и в файле dbmain.h не нашел определения этой функции).
Может есть другой способ получить текущий UCS, чтобы сохранить его, переключиться на свой собственный (именованный) UCS, а затем восстановить прежний UCS.

Пока я планировал делать это следующим образом:
// Получаю текущий Viewport
AcDbObjectId OldViewportId = acdbGetCurViewportObjectId();
// Получаю через OldViewportId AcDbViewport.
// Получаю имя UCS через AcDbViewport::ucsName;
// Устанавливаем UCS.
AcDbUCSTable* pUCSTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pUCSTable, AcDb::kForRead);
AcDbObjectId NewViewportId;
pUCSTable->getAt("PRF_UCS1",NewViewportId);
pUCSTable->close();

// AcDbViewport::setUCS(NewVieportId);

//.......

// Восстанавливаю UCS:
// AcDbViewport::setUCS(OldViewportId);

Но у меня не работатет (просто отсутствует в dbmain.h) acdbGetCurViewportObjectId().

/* тут я сделал перерыв и поискал по *.h файлам */

Поиском по файлам в \INC нашел лишь
#define acdbGetCurViewportObjectId acedGetCurViewportObjectId

А  поиск по acedGetCurViewportObjectId дал мне файл aced.h со строчкой
extern AcDbObjectId acedGetCurViewportObjectId();
Т.е. то, что нужно.

Таким образом проблема поиска acdbGetCurViewportObjectId решалась включением
#include
про который в файле помощи не было ни слова.

Осталось только это проверить. Если все получиться - сообщу.

Re: Переключение UCS (ARX)

acdbOpenObject компилируется без ошибок.
Но кроме него встретил в хелпе acdbOpebAcDbEntity
(аналог acdbObject, но без шаблонов. Просто первый параметр AcDbEntity*& )
С этим то первым параметром и возникла загвоздка:
пытаюсь получить AcDbViewport через AcDbObjectId
AcDbObjectId MyId;
// Заполняю MyID;
AcDbViewport* MyViewport;
acdbOpenAcDbEntity(AcDbViewport,MyId,AcDb::kForWrite);
На этой строке он мне и выдает сообщение об ошибке: невозможно преобразовать AcDbViewport* к AcDbEntity*&,
хотя по хелпу AcDbViewport наследник AcDbEntity. Отчего же он не хочет делать преобразование типа? Или эта функция (acdbOpenAcDbEntity) не предназначена для получения AcDbViewport* (впрочем тогда абсурд какой-то получается, ведь если вместо AcDbViewport* первым параметром поставить AcDbEntity*, то все прекрасно компилируется).

Вот такой не острый, но интересный вопрос. Может быть кто-то сможет пояснить ситуацию?

Re: Переключение UCS (ARX)

Нет, к сожадению описаный выше способ получения текущего AcDbViewport отказывается работать:

AcDbObjectId OldViewportId = acdbGetCurViewportObjectId();
AcDbViewport* CurViewport;
acdbOpenObject(CurViewport,OldViewportId,AcDb::kForWrite);

CurViewport возвращается неинициализированным.
Скажу больше: OldViewPortId возвращается нениницаилизированным (AcDbObjectId::nId=0).

Каким же образом добраться к текущему AcDbViewport?

Re: Переключение UCS (ARX)

Если внешняя функция acdbOpenAcDbEntity работает с классом AcDbEntity, это вовсе не означает, что она должна воспринимать объекты, производные от класса AcDbEntity(например, AcDbViewport). В данном случае  логично, что acdbOpenAcDbEntity не работает с AcDbViewport,  так  как класс AcDbEntity ? базовый класс для всех графических объектов Автокада, по определению,  а AcDbViewport с большим натягом можно отнести к таковым.

Re: Переключение UCS (ARX)

Не понятно.
Каждый указатель на класс наследник должен нормально восприниматься для любой функции, которая требует в качестве параметра указатель на класс предок. Иначе для чего же тогда нужно наследование?

Ведь каждый класс-наследник наследует все те же поля и методы (он их может переопределять, они могут быть виртуальными), поэтому можно использовать наследников в качестве предков. Ведь у AcDbLine свойство ::layer наследуется от AcDbEntity и перебрав все объекты блока, обращаясь к ним как к AcDbEntity и проверяя у них свойство ::layer можно таким макаром перебрать и линии и окружности и полилинии, которые находятся в этом блоке.

Re: Переключение UCS (ARX)

Еще одна попытка получить AcDbObjectId для текущего AcDbViewport:
AcDbViewportTable* pViewportTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pViewportTable, AcDb::kForRead);
AcDbObjectId OldViewportId;
pViewportTable->getAt("*ACTIVE",OldViewportId);
// До этого все нормально.
// И getAt возвращает Acad::eOk
AcDbViewport* CurViewport;
acdbOpenObject(CurViewport,OldViewportId,AcDb::kForWrite);
// Вот тут то acdbOpenObject и возвращает
// Acad::eNotThatKindOfClass
// Хелп не дает никаких пояснений по этому типу ошибки.

Т.о. AcDbObjectId получаем (во всяком случае функция завершается с eOk), но на этапе получения AcDbViewport по этому AcDbObjectId получаем ошибку (возвращается неинициализированное значение AcDbViewport).

Где я делаю неверно?

Re: Переключение UCS (ARX)

Одно из заблуждений найдено:
Я использовал AcDbObjectId, который получал через AcDbViewportTable::getAt для того, чтобы получить экземпляр AcDbViewport. При этом полученный AcDbObjectId на самом деле "показывал" на экземпляр AcDbViewportTableRecord. Поэтому я и получал Acad::eNotThatKindOfClass.

Таким образом одной загадкой стало меньше, но я получаю лишь активный AcDbViewportTableRecord, а он мне не помогает установить новый UCS (в самом начале задача шла именно об этом).

Вопрос--, вопрос++:
Каким образом связаны AcDbViewport и AcDbViewportTableRecord? (например в AcDbViewportTableRecord::setUcsPerViewport говориться об "... then the ucs that is saved with this viewport will become active ...", т.е. речь идет о "сохраненном вместе с вьюпортом UCS'е", значит какая то связь имеется).

Re: Переключение UCS (ARX)

Такое изобилие вопросов, что не знаешь на какой отвечать. С одной стороны это хорошо, но мне все таки кажется, что с задаванием некоторых из них спешить не следует, тем более, что  через 30 минут ты сам находишь на них ответ. Я считаю, что на форуме имеет смысл обсуждать только сложные или принципиальные вопросы. К числу таких я отношу вопрос от 3.06.2002  14:41:58 и постараюсь ответить на него.
?
  Спасибо, конечно, за ABC изложение основ механизма наследования С++.
  Теоретически все правильно и должен работать стандартный механизм неявного
  преобразования указателя на порожденный класс к указателю на базовый.
  Но в некоторых случаях при наследовании с видом порождения типа private возникает
  неоднозначность, связанная с тем, что объектам наследуемого класса становятся недоступны  наследуемые члены базового класса. Компилятор не в состоянии разрешить такую ситуацию и выдает завершение с ошибкой. Например:
?
  class base_class
{
   public:
    int a ;
    ...
    };
class der_class:private base_class
{
  ...
};
...
int vvv(base_class* xx) // внешняя функция
{
    xx->a = 100; // член а доступен только через указатель на базовый класс
    return 0;
}
...
int main( )
{
    base_class aa;
    der_class  bb;
    vvv(&aa);// этот вызов работает,
    vvv(&bb);// а этот нет!
    ...
}

Re: Переключение UCS (ARX)

Принимаю замечаие по поводу изобилия вопросов. В оправдание могу сказать лишь, что не на все вопросы, которые я задаю решение находится через 30 мин. Это даже скорее не вопрос (вроде: "какая функция..." или "какой параметр..."), а некоторая проблема, причем не всегда понятно каким способом ее лучше решать. Понятно, что за эти 30мин. я сам переберу некоторые способы решения, именно об этих результатах я и писал, чтобы кроме меня эту лишнюю работу никто не делал.

Все равно спасибо тов. VVV за все ответы. Это почти единственный постоянный мой собеседник по OARX. Спасибо.

С вопросом о наследовании:
Теоретически такой  механизме private наследования возможен в иерархии классов.
Но я не предполагал, что в иерархии AcDbObject -> AcDbEntity -> и пр. могут быть private члены класса (и/или private-наследованные), ведь все эта классы - основные узлы в иерархии, а не вспомогательные классы.

Среди избилия вопросов я выделю самый первый, который, видимо, затерялся в этом изобилии:
Каким образом мне переключить с текущего UCS на новый, а затем восстановить прежний? (у меня до сих пор не получилось это сделать).