Инструменты пользователя

Инструменты сайта


developers:tutorial:modelviewexport

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
developers:tutorial:modelviewexport [2022/12/13 12:31]
proxor
developers:tutorial:modelviewexport [2023/01/10 11:12] (текущий)
proxor [Экспорт объектов в сводную ИМ]
Строка 1: Строка 1:
-====== Экспорт чертежа и элементов информационной модели ======+====== Экспорт чертежа и объектов информационной модели ======
  
-Программный комплекс Топоматик Робур предоставляет пользователю возможность ​экспортировать плоские чертежи, а также генерировать сводную информационную ​модель (ИМ). ​В этом примере мы сформируем примитивы на основе данных нашей модели и поместим их в экспортируемый плоский чертёж. Также мы сформируем ​элементы ИМ на основе данных нашей модели и поместим их в экспортируемую сводную ​модель.+Программный комплекс Топоматик Робур предоставляет пользователю возможность ​управления формированием чертежей плана и сводной модели. Для этого необходимо реализовать ​поддержку бродкастов: 
 +  - "​generate_planchet"​ - для формирования чертежа плана 
 +  - "​generate_visualization_map"​ - для ​формирования сводной модели 
 +В этом примере мы сформируем примитивы на основе данных нашей модели и поместим их в экспортируемый плоский чертёж. Также мы сформируем ​объекты на основе данных нашей модели и поместим их в экспортируемую сводную ​ИМ.
  
 ==== Подготовка модуля ==== ==== Подготовка модуля ====
Строка 15: Строка 18:
 ==== Подготовка проекта ==== ==== Подготовка проекта ====
 Добавим элементы нашей модели на план. В нашем случае это будет выглядеть так: Добавим элементы нашей модели на план. В нашем случае это будет выглядеть так:
-{{ :​developers:​tutorial:​createmodel:​tut_export_model_views_1.png?​nolink ​|}}+ 
 +{{ :​developers:​tutorial:​createmodel:​tut_export_model_views_1.png?​direct ​|}}
  
 ==== Экспорт элементов модели в плоский чертёж ==== ==== Экспорт элементов модели в плоский чертёж ====
 Для экспорта элементов пользовательской модели в плоский чертёж необходимы следующий действия:​ Для экспорта элементов пользовательской модели в плоский чертёж необходимы следующий действия:​
-  - Создание ​команды добавления примитивов на чертёж +  - Создать команду для ​добавления примитивов на чертёж 
-  - Подписаться на бродкаст ​"​generate_planchet" ​в plugin-файле ​с помощью команды из пункта 1 +  - Зарегистрировать ​вызов команды через ​бродкаст ​«generate_planchet» ​в plugin-файле
 ==== Создание команды добавления примитивов на чертёж ==== ==== Создание команды добавления примитивов на чертёж ====
-Команда должна вызвать метод принимающий в качестве аргумента объект типа **GeneratePlanchetEventArgs**. Свойство **GeneratePlanchetEventArgs.Model** возвращает корневую область модели чертежа типа **DwgBlock**,​ в которую следует добавить необходимые примитивы (подклассы **DwgEntity**).+Команда должна вызвать метод принимающий в качестве аргумента объект типа **GeneratePlanchetEventArgs**.
  
-Модель чертежа можно получить с помощью свойства **DwgBlock.Drawing**. Прежде чем ​вносить изменения ​в чертёж мы зафиксируем ​его настройки методом ​**Drawing.PushState()** и выполним их сброс до состояния по умолчанию методом **Drawing.ResetStateDefault()**. Далее в блоке **try** внесём необходимые изменения в чертёж и в блоке **finally** вернём настройки чертежа в прежнее ​состояние методом **Drawing.PopState()**.+Свойство **GeneratePlanchetEventArgs.Layer** возвращает текущий экспортируемый слой типа **CadViewLayer**. С помощью этого свойства убедимсячто слой является слоем нашей модели.
  
-Свойство **GeneratePlanchetEventArgs.Layer** возвращает ​текущий экспортируемый ​слой типа **CadViewLayer**. С помощью ​этого ​свойства ​Убедимсячто слой является ​слоем нашей модели.+Свойство **GeneratePlanchetEventArgs.Model** возвращает корневую область модели чертежа ​типа **DwgBlock**,​ в которую следует добавить необходимые ​примитивы (подклассы ​**DwgEntity**). 
 + 
 +Модель чертежа можно получить с помощью свойства ​**DwgBlock.Drawing**. Прежде чем вносить изменения в чертёж мы зафиксируем его настройки методом **Drawing.PushState()** и выполним их сброс до состояния по умолчанию методом **Drawing.ResetStateDefault()**. Далее в блоке **try** внесём необходимые изменения в чертёж и в блоке **finally** вернём настройки чертежа в прежнее состояние ​методом **Drawing.PopState()**.
  
 В теле программного модуля объявите команду,​ и декорируйте её атрибутом «cmd». В теле программного модуля объявите команду,​ и декорируйте её атрибутом «cmd».
Строка 120: Строка 125:
 В результате работы команды "​**tutorial_generate_planchet**"​ в экспортированном файле плоского чертежа появятся примитивы нашей модели. В результате работы команды "​**tutorial_generate_planchet**"​ в экспортированном файле плоского чертежа появятся примитивы нашей модели.
  
-{{ :​developers:​tutorial:​createmodel:​tut_export_model_views_3.png?​nolink ​|}}+{{ :​developers:​tutorial:​createmodel:​tut_export_model_views_3.png?​direct ​|}}
  
-==== Экспорт ​элементов ​информационной модели ​в сводную ИМ ==== +==== Экспорт ​объектов в сводную ИМ ==== 
-Для экспорта ​элементов пользовательской модели в сводную ИМ необходимы следующий действия:​ +Для экспорта ​объектов пользовательской модели в сводную ИМ необходимы следующий действия:​ 
-  - Создание ​команды добавления ​элементов ​ИМ в сводную ИМ +  - Создать команду для ​добавления ​объектов в сводную ИМ 
-  - Подписаться на бродкаст ​"​generate_visualization_map" ​в plugin-файле ​с помощью ​команды ​из пункта ​1+  - Зарегистрировать ​вызов команды через ​бродкаст ​«generate_visualization_map» ​в plugin-файле 
 +==== Создание команды добавления объектов в сводную ИМ ==== 
 +Команда должна вызвать метод ​принимающий в качестве аргумента объект типа **CreateVisualizationEventArgs**.
  
-==== Создание команды добавления ИМ в сводную ИМ ==== +Свойство **CreateVisualizationEventArgs.Layer** возвращает ​текущий ​экспортируемый слой типа **CadViewLayer**. По свойству Layer можно определить, какая ​именно модель в данный момент экспортируется.
-Команда должна вызвать метод принимающий ​в качестве аргумента ​объект ​типа **CreateVisualizationEventArgs**. Свойство ​**CreateVisualizationEventArgs.Model** возвращает корневую область модели ​чертежа типа **DwgBlock**,​ в которую следует добавить ​необходимые примитивы (подклассы **DwgEntity**).+
  
-Модель чертежа можно получить с помощью свойства **DwgBlock.Drawing**. Прежде ​чем вносить изменения в чертёж мы зафиксируем его настройки методом **Drawing.PushState()** и выполним их сброс до состояния по умолчанию методом **Drawing.ResetStateDefault()**. Далее в блоке **try** внесём необходимые изменения в чертёж и в блоке **finally** вернём настройки чертежа в прежнее состояние методом **Drawing.PopState()**.+Свойство **CreateVisualizationEventArgs.Map** возвращает сводную ИМ типа **VisualizationMap**,​ в которую следует добавить необходимые объекты. 
 + 
 +Объекты ИМ объединяются в группы (**VisualizationGroup**). Каждая группа - это узел в дереве сводной модели. Текущую группу ​можно получить ​через ​свойство **VisualizationMap.Group**,​ и при необходимости переопределить её свойства ​через метод ​**VisualizationGroup.ApplayOverridedProperties()** или типГруппы так же могут содержать в себе ​другие группы. Новая группа создаётся методом **VisualizationMap.BeginGroup()** и становится текущей. Метод ​ **VisualizationGroup.EndGroup()** заканчивает работу с текущей группой ​и возвращает группу уровнем выше. 
 + 
 +<​note>​Связку **BeginGroup() => EndGroup()** следует использовать в сочетании с блоком **try/​finally**. 
 +<code csharp>​ 
 +# args - аргументы типа CreateVisualizationEventArgs 
 +VisualizationMap map = args.Map; 
 +map.BeginGroup("​GroupName",​ false); 
 +try 
 +
 +    VisualizationGroup group = map.Group;​ 
 +    # пользовательские действия 
 +
 +finally 
 +{     
 +    map.BeginGroup("​GroupName",​ false); 
 +
 +</​code>​ 
 +</​note>​ 
 + 
 +Для добавления ​моделей в сводную ИМ используется метод **VisualizationMap.AddMesh()**,​ а для размещения ​добавленной модели в пространстве метод **VisualizationMap.AddInsertion()**. 
 + 
 +=== Добавление объекта в сводную модель === 
 + 
 +Наша модель содержит в себе линейные объекты. В качестве примера для отображения на сводной ​модели примем,​ что линейный объект нашей модели это ​забор (**Fence**) с фиксированной высотой 3 метра. 
 + 
 +Для каждого ​участка забора создадим полигональную сеть (**MeshGeometry3D**). 
 + 
 +Через свойство **MeshGeometry3D.Groups** получим коллекцию ​групп сети (**MaterialGroupsCollection**) ​ и добавим в неё группу с материалом (**MaterialGroup**). 
 + 
 +Определим координаты вершин (**Vector3F**) и добавим их в коллекцию вершин (**Vector3dCollection**) через свойство **MeshGeometry3D.Positions**.  
 + 
 +Определим грани (**Face**) опирающиеся на индексы вершин полигональной сети. Для ​каждой грани добавим в группу сети новый индекс ​методом **MaterialGroup.AddIndex()**. Через свойство **MeshGeometry3D.TriangleIndices** ​получим коллекцию треугольников (**TrianglesCollection**) и добавим в неё грани.  
 + 
 +Создадим трёхмерную модель (**GeometryModel3D**). Получим ​словарь ​с материалами через свойство **GeometryModel3D.Materials** и добавим в него материал (**PhongMaterial**). Через свойство **GeometryModel3D.Meshes** ​получим словарь полигональных сетей ​и добавим в него вышеописанную сеть. 
 + 
 +Сгенерируем новое имя для нашей 3D-модели ​методом **VisualizationMap.GenMeshName()**. Добавим нашу 3D-модель с новым именем в коллекцию моделей сводной ИМ методом **VisualizationMap.AddMesh**. 
 + 
 +Создадим новую группу методом **VisualizationMap.BeginGroup()**. В блоке **try** ​добавим вставку (**GeometryInsertion**) ранее добавленной 3D-модели методом **VisualizationMap.AddInsertion**. Через свойство **VisualizationMap.Group** получим текущую группу (**VisualizationGroup**). Назначим ​ей тип через свойство **VisualizationGroup.Type**. Через свойство **VisualizationGroup.Properties** получим коллекцию свойств (**ImProperties**) и добавим в неё новые свойства (**ImProperty**) "Количество узлов"​ и "​Длина"​. 
 + 
 +В блоке **finally** закроем группу ​методом **VisualizationMap.EndGroup()**.
  
 В теле программного модуля объявите команду,​ и декорируйте её атрибутом «cmd». В теле программного модуля объявите команду,​ и декорируйте её атрибутом «cmd».
  
 +<file csharp Module.cs>​
 +//​функция срабатывающая при объявлении бродкаста "​generate_visualization_map"​
 +//​подписка на бродкаст осуществляется в plugin-файле в разделе "​broadcasts"​
 +[cmd("​tutorial_generate_visualization"​)]
 +private void GenerateVisualization(CreateVisualizationEventArgs args)
 +{
 +    // проверяем слой на соответствие типу слоя нашей модели
 +    if (args.Layer is ModelLayer)
 +    {
 +        GenerateModelVisualization(args);​
 +        args.Handled = true;
 +    }
 +}
 +
 +/// <​summary>​
 +/// Формирование элементов информационной модели на основе данных полученных из модели
 +/// и добавление их в информационную модель
 +/// </​summary>​
 +/// <param name="​args"></​param>​
 +private void GenerateModelVisualization(CreateVisualizationEventArgs args)
 +{
 +    var fenceHeight = 3.0; // высота забора
 +    var map = args.Map; // сводная модель
 +    var layer = args.Layer as ModelLayer;
 +    ​
 +    // проверяем слой на видимость и наличием нашей модели
 +    if (layer.Visible && layer.Model is Model model)
 +    {
 +        // собираем поверхности для определения высотного положения забора
 +        var project = ApplicationHost.Current.ActiveProject as ModelProject;​
 +        var items = project.Model.GetChilds();​
 +        var surfaces = new List<​ISurface>​();​
 +        foreach (var item in items)
 +        {
 +            if (item.ModelType.Equals("​dtm",​ StringComparison.OrdinalIgnoreCase) && item.Model is TerrainModel dtm)
 +            {
 +                var sfc = args.FetchSurfaces(dtm);​
 +                surfaces.Add(sfc);​
 +            }
 +        }
 +
 +        map.BeginGroup("​CustomModel",​ false);
 +        try
 +        {
 +            for (int i = 0; i < model.Count;​ i++)
 +            {
 +                // создаём полигональную сеть и добавляем в неё группу материалов
 +                var mesh = new MeshGeometry3D();​
 +                var materialGroup = new MaterialGroup { Material = "​Fence_Material"​ };
 +                mesh.Groups.Add(materialGroup);​
 +                ​
 +                // наполняем сеть вершинами и определяем грани опирающиеся на эти точки
 +                var length = 0.0; //​длина участка забора
 +                var points = model[i];
 +                for (int j = 0; j < points.Count;​ j++)
 +                {
 +                    var point = points[j];
 +                    var elevation = 0.0;
 +                    foreach (var sfc in surfaces)
 +                    {
 +                        var z = sfc.GetElevation(point);​
 +                        if (z.HasValue && ValueConverter.CompValues(z.Value,​ elevation) == 1)
 +                        {
 +                            elevation = z.Value;
 +                        }
 +                    }
 +                    mesh.Positions.Add(new Vector3F(new Vector3D(point,​ elevation)));​
 +                    mesh.Positions.Add(new Vector3F(new Vector3D(point,​ elevation + fenceHeight)));​
 +
 +                    if (j < points.Count - 1)
 +                    {
 +                        var nextPoint = points[j + 1];
 +                        var delta = nextPoint - point;
 +                        length += delta.Length;​
 +
 +                        var face1 = new Face(j * 2, (j + 1) * 2, j * 2 + 1);
 +                        var face2 = new Face((j + 1) * 2, (j + 1) * 2 + 1, j * 2 + 1);
 +                        materialGroup.AddIndex(TrimShort(mesh.TriangleIndices.Count));​
 +                        mesh.TriangleIndices.Add(face1);​
 +                        materialGroup.AddIndex(TrimShort(mesh.TriangleIndices.Count));​
 +                        mesh.TriangleIndices.Add(face2);​
 +                    }
 +                }
 +
 +                // создаём 3D-модель и добавляем в неё материал
 +                // добавляем сеть в 3D-модель
 +                var geometry = new GeometryModel3D();​
 +                if (!geometry.Materials.ContainsKey("​Custom_Material"​))
 +                {
 +                    var material = new PhongMaterial();​
 +                    material.Diffuse = new Vector3F(0.6,​ 0.6, 0.6);
 +                    material.Shininess = 0.8f;
 +                    material.SpecularLevel = 0.8f;
 +                    geometry.Materials["​Custom_Material"​] = material;
 +                }
 +                geometry.Meshes["​Fence_Mesh"​] = mesh;
 +
 +                // добавляем 3D-модель в сводную модель,​
 +                // назначаем ей тип и необходимые свойства
 +                var meshName = map.GenMeshName("​custom_mesh"​);​
 +                map.AddMesh(meshName,​ geometry);
 +                map.BeginGroup("​Fence",​ false);
 +                try
 +                {
 +                    map.AddInsertion(meshName,​ new Vector3D(0, 0, 0));
 +
 +                    var type = map.FindType("​SmdxCustomFence"​);​
 +                    if (type == null)
 +                    {
 +                        var parent = map.FindType("​SmdxElement"​);​
 +                        var typeDesc = new ImTypeDescriptor("​SmdxCustomFence",​ "​Пользовательский забор",​ parent);
 +                        type = map.CreateType(typeDesc);​
 +                    }
 +
 +                    map.Group.Type = type;
 +                    map.Group.Properties.Add(new ImProperty("​points",​ "​Количество узлов",​ points.Count));​
 +                    map.Group.Properties.Add(new ImProperty("​length",​ "​Длина",​ length));
 +                }
 +                finally
 +                {
 +                    map.EndGroup();​
 +                }
 +            }
 +        }
 +        finally
 +        {
 +            map.EndGroup();​
 +        }
 +    }
 +}
 +
 +private static ushort TrimShort(int value)
 +{
 +    Debug.Assert(value <= ushort.MaxValue);​
 +    return value > ushort.MaxValue ? ushort.MaxValue : (ushort)value;​
 +}
 +</​file>​
 +
 +Команда «**tutorial_generate_visualization**» должна выполняться в момент создания сводной модели. Для этого добавим соответствующую запись в plugin-файл в секции "​**broadcast**"​
 +
 +<file javascript tut_export_model_views.plugin>​
 +"​broadcasts":​ {
 +  "​generate_visualization_map":​ "​tutorial_generate_visualization"​
 +}
 +</​file>​
 +
 +В результате работы команды "​**tutorial_generate_visualization**"​ в экспортированной сводной модели появятся объекты нашей модели.
 +
 +{{ :​developers:​tutorial:​createmodel:​tut_export_model_views_2.png?​direct |}}
 +
 +<​note>​[[developers:​tutorial:​tutorialcode|Исходный код]] примера расположен в проекте **"​TutorialExportModelViews"​**.</​note>​
developers/tutorial/modelviewexport.1670934686.txt.gz · Последние изменения: 2022/12/13 12:31 — proxor