Что интересно, пока писал это сообщение (дня 2), разными действиями так или иначе решил свои проблемы
, но там всё равно есть пласт вопросов (
в конце под заголовком "Вопросы")... в любом случае в сети минимум информации как работать програмно с запросами map 3d -- поэтому в рамках данной темы хотел бы часть из них поднять.
Пользуюсь им к слову только ради быстрых алгоритмов обрезки данных по
dwg файлам и (!?!?) более-менее оптимизации по производительности в этих процедурах.
Что мне было нужно: есть набор dwg-чертежей (пусть для простоты пустых файлов), есть dwg-файл с данными (топооснова к примеру), есть необходимость вставить обрезанную топооснову по полигону в каждый из чертежей (полигон везде свой).
Что я использую: запросы Map 3d (методы библиотеки
C:\Program Files\Autodesk\AutoCAD ****\Map\ManagedMapApi.dll. Их особенность в том, что для идентификации текущего документа используются не производные от DataBase/Application.DocumentManager.MdiActiveDocument, а свой класс --
Autodesk.Gis.Map.MapApplication mapApp = Autodesk.Gis.Map.HostMapApplicationServices.Application;
. Он берет либо текущий документ, либо базу данных открытого документа (что делает невозможным (?) выполнять запросы из-под закрытого чертежа работая только с его Database).
Как корректно делать пакетную обработку? Пока что я придерживаюсь следующего сценария (взял отсюда
https://adn-cis.org/forum/index.php?topic=813.msg3221#msg3221 с изменениями):
[CommandMethod("test1", CommandFlags.Session)]
public static void StartActions()
{
foreach (string OneDwg in Directory.GetFiles(@"D:\Work\Temp\AD_Files", "*.dwg", SearchOption.TopDirectoryOnly))
{
Document dwgFile = Application.DocumentManager.Open(OneDwg, false);
Application.DocumentManager.MdiActiveDocument = dwgFile;
Database db = Application.DocumentManager.MdiActiveDocument.Database;
Autodesk.Gis.Map.Project.ProjectModel activeProject = Autodesk.Gis.Map.HostMapApplicationServices.Application.GetProjectForDB(db);
//Выполняем разные действия (о них ниже по тексту)
dwgSet.DetachDrawing(PathToDataDrawing);
dwgFile.CloseAndSave(OneDwg);
}
}
Что здесь происходит - стандартными средствами .NET получаем каталог файлов в директории, устанавливаем статичный файловый путь к файлу с данными (данные из которого мы хотим получить), и далее поочередно открываем файлы, получаем их Database, и по этой Database получаем
Autodesk.Gis.Map.HostMapApplicationServices.Application.GetProjectForDB(db);
"проект" Map 3d для документа -- по умолчанию он один. В конце в рамках "правил хорошего тона" отключаем присоединенный чертеж от данного набора чертежей "проекта map 3d".
Я не зря описался про отключение присоединенного чертежа от общего набора чертежей. Дело в том, что Map 3d использует механику присоединения чертежей через так называемые "Drive alias" - что позволяет сокращать хранимый путь к файлу, срезая общую для файлов часть пути - до данной директории. И вот эти "alias" хранятся только у данного пользователя. При передаче файла другому пользователю, AutoCAD не найдет заданный путь для такого псевдонима и логично вернет ошибку:
Да конечно, путь можно переопределить - но руками. И при открытии чертежа кодом выше такое надо будет также править руками. Для того, чтобы избежать подобного сценария, используем следующий "костыль":
//Отключаем все прочие ранние файлы
void DetachFiles (int DrawingsCount, AttachedDrawings collection_files)
{
int drawings_count = DrawingsCount;
if (drawings_count > 0)
{
AttachedDrawings dwg_collection_files = collection_files;
for (int i1 = 0; i1 < drawings_count; i1++)
{
AttachedDrawing OneDrawing = dwg_collection_files[i1];
string FilePath = OneDrawing.ActualPath;
OneDrawing.Deactivate();
dwgSet.DetachDrawing(OneDrawing.ObjectId);
}
}
}
DetachFiles(dwgSet.AllDrawingsCount, dwgSet.AllAttachedDrawings);
Здесь мы получаем набор всех (имеется ввиду + вложенных в данный, если они были получены как другие запросы Map 3d) чертежей и поочередно их сперва деактивируем. затем отключаем включая все известные и неизвестные. Тогда эта ошибка возникать не будет
Теперь по поводу исполнения самого запроса. Я исходил оттого, что в открываемых мной файлах уже были раннее определен этот "запрос" - настроена область захвата. Имеющийся запрос получается вот так:
Autodesk.Gis.Map.Project.ProjectModel activeProject = Autodesk.Gis.Map.HostMapApplicationServices.Application.GetProjectForDB(db);
Autodesk.Gis.Map.Query.QueryModel qryModel = activeProject.CurQuery;
Для его исполнения (после настройки) необходимо выполнить такие действия:
qryModel.Run();
qryModel.Execute(dwgSet);
Вопросы
Собственно, вопросы касаются по большей части иных примеров работы с функционалом запросов ... как-то в сети примеров жиденько, даже поиск по GitHub нашел пару куцых репозиториев, да и то -- один на китайском
.
Другой более интересный вопрос связан с возможностью исполнения этих процедур изпод Lisp (я так понял, оно родилось из него - во всяком случае вот сохраняемая конфигурация запроса сильно напоминающая AutoLisp)
(setq ade_cmddia_before_qry (getvar "cmddia"))
(setvar "cmddia" 0)
(mapcar 'ade_dwgdeactivate (ade_dslist))
(setq ade_tmpprefval (ade_prefgetval "ActivateDwgsOnAttach"))
(ade_prefsetval "ActivateDwgsOnAttach" T)
(setq dwg_id(ade_dsattach "C:\\Св_ВР_Кам.dwg"))
(ade_prefsetval "ActivateDwgsOnAttach" ade_tmpprefval)
(ade_qryclear)
(ade_qrysettype "draw")
(ade_qrydefine '("" "(" "" "Location" ("all" )")"))
(ade_qrysetaltprop nil)
(ade_qryexecute)
(setvar "cmddia" ade_cmddia_before_qry)
Также хочу поинтересоваться, корректно ли я делал, подавая базу данных файла для определения текущего проекта map 3d?