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

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


developers:tutorial:sfcedit

Различия

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

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

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
developers:tutorial:sfcedit [2022/04/07 17:40]
proxor
developers:tutorial:sfcedit [2022/04/09 18:54] (текущий)
proxor [Редактирование элементов поверхности]
Строка 14: Строка 14:
 Для добавления [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурных линий]] помощи специальных классов не требуется. Их можно добавлять напрямую в  [[developers:​references:​topomatic.sfc.surface.structurelines|коллекцию структурных линий (Surface.StructureLines)]] нужной поверхности. Аналогично с [[developers:​references:​topomatic.sfc.pointeditor|PointEditor]],​ методы [[developers:​references:​topomatic.sfc.structurelines.add_topomatic.sfc.structureline|StructureLines.Add()]] и [[developers:​references:​topomatic.sfc.structurelines.remove_topomatic.sfc.structureline|StructureLines.Remove()]] дают возможность добавить или удалить структурную линию соответственно. Для удаления структурной линии по её индексу,​ можно воспользоваться методом [[developers:​references:​topomatic.sfc.structurelines.removeat_system.int32|StructureLines.RemoveAt()]]. Для добавления [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурных линий]] помощи специальных классов не требуется. Их можно добавлять напрямую в  [[developers:​references:​topomatic.sfc.surface.structurelines|коллекцию структурных линий (Surface.StructureLines)]] нужной поверхности. Аналогично с [[developers:​references:​topomatic.sfc.pointeditor|PointEditor]],​ методы [[developers:​references:​topomatic.sfc.structurelines.add_topomatic.sfc.structureline|StructureLines.Add()]] и [[developers:​references:​topomatic.sfc.structurelines.remove_topomatic.sfc.structureline|StructureLines.Remove()]] дают возможность добавить или удалить структурную линию соответственно. Для удаления структурной линии по её индексу,​ можно воспользоваться методом [[developers:​references:​topomatic.sfc.structurelines.removeat_system.int32|StructureLines.RemoveAt()]].
  
-Редатировать [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурные линии]] следует напрямую. Например,​ если мы хотим добавить существующую [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точку поверхности]] в [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурную линию]],​ нужно именно у неё вызвать метод [[developers:​references:​topomatic.sfc.structureline.add_system.int32|Add()]].+Редактировать [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурные линии]] следует напрямую. Например,​ если мы хотим добавить существующую [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точку поверхности]] в [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурную линию]],​ нужно именно у неё вызвать метод [[developers:​references:​topomatic.sfc.structureline.add_system.int32|Add()]].
  
-<​note>​Важно помнить,​ что ​[[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурная линия]] всегда опирается на [[developers:​references:​topomatic.sfc.surfacepoint|точки поверхности]] и не может существовать без них.</​note>​+<​note>​[[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|Структурная линия]] всегда опирается на [[developers:​references:​topomatic.sfc.surfacepoint|точки поверхности]] и не может существовать без них.</​note>​
  
 +
 +==== Настройка проекта Visual Studio ====
 +
 +Прежде чем приступить работе с элементами поверхности,​ создайте и настройте новый [[developers:​tutorial:​module|модуль]] для подключения к программному комплексу [[http://​www.topomatic.ru|Топоматик Робур]]. ​
 +
 +С помощью диалогового окна Менеджер ссылок добавьте ссылки на следующие библиотеки:​
 +  * [[developers:​references:​topomatic.cad.foundation|Topomatic.Cad.Foundation.dll]] - базовые математические типы и операции
 +  * [[developers:​references:​topomatic.cad.view|Topomatic.Cad.View.dll]] - элемент управления для отображения слоёв моделей
 +  * [[developers:​references:​topomatic.dwg|Topomatic.Dwg.dll]] - примитивы и модель чертежа
 +  * [[developers:​references:​topomatic.sfc|Topomatic.Sfc.dll]] - поверхность
 +  * [[developers:​references:​topomatic.sfc.layer|Topomatic.Sfc.Layer.dll]] - слой поверхности
 +  * [[developers:​references:​topomatic.foundationclasses|Topomatic.FoundationClasses]] - базовые классы программного комплекса [[http://​www.topomatic.ru|Топоматик Робур]].
 +  * [[developers:​references:​topomatic.smt|Topomatic.Smt]] - семантика
 +
 +В следующих примерах используются классы и методы предыдущего урока, в котором рассматривается процесс [[developers:​tutorial:​sfcselection|выделения элементов поверхности]].
 +
 +===== Добавление элементов поверхности =====
 +В этом примере мы выберем замкнутую [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурную линию]] и на указанном расстоянии от неё построим новую с учётом приращения высоты.
 +
 +Для этого нам потребуются координаты точек эквидистанты существующей [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурной линии]]. Далее мы рассчитаем новое значение высоты этих точек и на основе полученных координат создадим новые [[developers:​references:​topomatic.sfc.surfacepoint|точки поверхности]]. Вновь созданные [[developers:​references:​topomatic.sfc.surfacepoint|точки поверхности]] станут основой для создания новой [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурной линии]].
 +
 +Эквидистанта для новой [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурной линии]] должна рассчитываться относительно удалённости курсора от выбранной [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурной линии]]. Чтобы получить это значение,​ необходимо воспользоваться методом [[developers:​references:​b91330957111b48e6dd7fd9cf6e05eba|CadLibrary.PosToPolylineStaOffset()]]. В качестве ​ аргументов,​ метод принимает список координат полилинии типа [[developers:​references:​topomatic.cad.foundation.vector2d|Vector2D]],​ координаты курсора типа [[developers:​references:​topomatic.cad.foundation.vector2d|Vector2D]] и записывает рассчитанные значения в принимаемые переменные ''​offset''​ и ''​station''​ типа [[https://​docs.microsoft.com/​ru-ru/​dotnet/​api/​system.double?​view=net-6.0|double]] с модификатором [[https://​docs.microsoft.com/​ru-ru/​dotnet/​csharp/​language-reference/​keywords/​out-parameter-modifier|out]]. ''​offset''​ - кратчайшее расстояние от курсора до полилинии,​ а ''​station''​ - длина части полилинии от её первой точки до точки в которой был определён ''​offset''​. ​
 +
 +Для наглядности будущего положения новой структурной линии мы воспользуемся [[developers:​tutorial:​dynamicrender|динамической отрисовкой]] примитива.
 +
 +В теле программного модуля объявите команду,​ и декорируйте её атрибутом «cmd». Команда «create_hill_or_pit» предложит пользователю выбрать замкнутую структурную линию и приращение высоты. Результатом действия станет сооружение насыпи или котлована в зависимости от значений указанных пользователем.
 +
 +<code csharp>
 +{
 +...
 +    [cmd("​create_hill_or_pit"​)]
 +    private void CreateHillOrPit()
 +    {
 +        //​Находим активный SurfaceLayer
 +        var cadview = CadView;
 +        if (cadview == null) return;
 +
 +        var layer = SurfaceLayer.GetSurfaceLayer(cadview);​
 +        if (layer == null) return;
 +        var sfc = layer.Surface;​
 +
 +        //​Выбираем структурную линию и получаем список её двумерных координат
 +        var strLine = layer.SelectOneStructureLine(i => sfc.StructureLines[i].IsClosed,​
 +            "​Выберите замкнутую структурную линию:"​);​
 +        if (strLine == null) return;
 +
 +        var poly = new List<​Vector3D>​();​
 +        strLine.ToPolyline(poly);​
 +        var poly2d = poly.Select(v => v.Pos).ToList();​
 +
 +        //​Делегат для динамической отрисовки контура будущей структурной линии
 +        DrawCursorEvent ondraw = delegate (CadPen pen, Vector3D vertex)
 +        {
 +            double s, o;
 +            //​находим смещение точки по линии
 +            if (CadLibrary.PosToPolylineStaOffset(poly2d,​ vertex.Pos, out o, out s))
 +            {
 +                var offs_line = new List<​Vector3D>​();​
 +                poly.Offset(o,​ offs_line);
 +
 +                //​Создаём примитив и рисуем его
 +                var entity = new DwgPolyline();​
 +                entity.Prepare(sfc.Situation);​
 +                foreach (var v in offs_line)
 +                {
 +                    entity.Add(new BugleVector2D(v.Pos));​
 +                }
 +
 +                entity.Color = CadColor.Green;​
 +                PaintEntityEventArgs.PaintEntity(entity,​ pen);
 +            }
 +        };
 +
 +        //​Подписываемся на событие динамической отрисовки примитивов
 +        cadview.DynamicDraw += ondraw;
 +
 +        Vector3D point;
 +        GetPointResult res;
 +        try
 +        {
 +            //​Указываем курсором точку на плане определяющую сторону и величину смещения
 +            //и закладываем возможность задать смещение с клавиатуры
 +            res = CadCursors.GetPoint(cadview,​ out point, "​Укажите смещение или:",​ "​Задать величину смещения"​);​
 +
 +        }
 +        finally
 +        {
 +            //​Отписываемся от события,​ так как динамическая отрисовка нам больше не требуется
 +            cadview.DynamicDraw -= ondraw;
 +        }
 +
 +
 +        double sta;
 +        var off = 0.0;
 +        if (res == GetPointResult.Accept)
 +        {
 +            CadLibrary.PosToPolylineStaOffset(poly2d,​ point.Pos, out off, out sta);
 +        }
 +        else if (res == GetPointResult.UserCmd)
 +        {
 +            if (CadCursors.GetDouble(cadview,​ ref off, "​Задайте смещение:"​) == GetPointResult.Cancel) return;
 +        }
 +        else if (res == GetPointResult.Cancel) return;
 +
 +        var delta = 0.0;
 +        var incline = 0.0;
 +
 +        //​Указываем величину приращения отметок смещённой структурной линии
 +        //и закладываем возможность задать уклон откоса
 +        //В случае если пользователь просто нажмёт Enter то функция вернёт UserCmd
 +        res = CadCursors.GetDouble(cadview,​ ref delta, "​Укажите разницу высот или:",​ "​Задать уклон"​);​
 +
 +        if (res == GetPointResult.UserCmd && cadview.LastUserCmd != ""​)
 +        {
 +            if (CadCursors.GetDouble(cadview,​ ref incline, "​Укажите уклон:"​) == GetPointResult.Cancel) return;
 +            delta = incline * Math.Abs(off);​
 +        }
 +        else if (res == GetPointResult.Cancel) return;
 +
 +        //​Определяем эквидистанту в соответствии с параметрами указанными пользователем
 +        var offsetPoly = new List<​Vector3D>​();​
 +        poly.Offset(off,​ offsetPoly);​
 +        offsetPoly.Remove(offsetPoly[offsetPoly.Count - 1]);
 +
 +        //​Фиксируем момент начала внесения изменений в поверхность
 +        sfc.BeginUpdate("​Построить насыпь или котлован"​);​
 +
 +        //​Создаём точки поверхности и добавляем их в структурную линию
 +        try
 +        {
 +            var offsetStrLine = new StructureLine();​
 +            var editor = new PointEditor(sfc);​
 +            foreach (var polylinePoint in offsetPoly)
 +            {
 +                var sfcPoint = new SurfacePoint(polylinePoint + new Vector3D(0.0,​ 0.0, delta));
 +                sfcPoint.IsSituation = false;
 +                var sfcPointIndex = editor.Add(sfcPoint);​
 +                offsetStrLine.Add(sfcPointIndex);​
 +            }
 +
 +            offsetStrLine.IsClosed = true;
 +            sfc.StructureLines.Add(offsetStrLine);​
 +        }
 +        finally
 +        {
 +            //​Фиксируем окончание внесения изменений в поверхность
 +            sfc.EndUpdate();​
 +        }
 +
 +        //​Очищаем список выбранных элементов поверхности
 +        //и сообщаем CadView о необходиомсти обновить отображение его содержимого
 +        layer.SelectionSet.Clear();​
 +        cadview.Unlock();​
 +        cadview.Invalidate();​
 +    }
 +...
 +}
 +</​code>​
 +
 +{{ :​developers:​tutorial:​surfaceelementsedit:​tutcreatestrline.png?​nolink&​600 |}}
 +
 +
 +===== Редактирование элементов поверхности =====
 +В этом примере мы рассмотрим процесс замены [[road:​commons_tasks:​purpose_objects_semantics:​start|объекта семантики]] у [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точки поверхности]] и изменение значений его свойств.
 +
 +Изменение семантики точки осуществляется через специальный класс [[developers:​references:​topomatic.sfc.surfacepointextensiveinformation|SurfacePointExtensiveInformation]],​ который хранит в себе подробную информацию о точке поверхности. Получить эту информацию можно с помощью метода [[developers:​references:​topomatic.sfc.surfacepointarray.getextensiveinformation_ref_topomatic.sfc.surfacepoint|SurfacePointArray.GetExtensiveInformation()]]. В качестве аргумента метод принимает [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точку поверхности]] или её индекс в [[developers:​references:​topomatic.sfc.surfacepointarray|массиве точек поверхности]].
 +
 +Чтобы поменять [[road:​commons_tasks:​purpose_objects_semantics:​start|семантический объект]] [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точки поверхности]],​ следует изменить значение свойства [[developers:​references:​topomatic.sfc.surfacepointextensiveinformation.code|SurfacePointExtensiveInformation.Code]]. В этом примере мы назначим точке объект ''​Пункт государственной геодезической сети'',​ который имеет код ''​1000''​.
 +
 +Состояние [[road:​commons_tasks:​purpose_objects_semantics:​start|семантического объекта]] описывается его [[road:​commons_tasks:​edit_objects:​start|семантическими свойствами]] и хранится в классе [[developers:​references:​topomatic.smt.semanticdataset|SemanticDataSet]]. Это состояние можно получить через свойство [[developers:​references:​topomatic.sfc.surfacepointextensiveinformation.semantic|SurfacePointExtensiveInformation.Semantic]].
 +
 +[[road:​commons_tasks:​edit_objects:​start|Семантические свойства]] являются подтипами [[developers:​references:​topomatic.smt.semanticpropertynode|SemanticPropertyNode]]. Среди них:
 +  * [[developers:​references:​topomatic.smt.semanticdoublenode|Topomatic.Smt.SemanticDoubleNode]] - ствойство с плавающей точкой
 +  * [[developers:​references:​topomatic.smt.semanticintegernode|Topomatic.Smt.SemanticIntegerNode]] - целочисленное свойство
 +  * [[developers:​references:​topomatic.smt.semanticjumper|Topomatic.Smt.SemanticJumper]] - условный переключатель
 +  * [[developers:​references:​topomatic.smt.semanticstringnode|Topomatic.Smt.SemanticStringNode]] - строковое свойство
 +
 +Необходимое [[road:​commons_tasks:​edit_objects:​start|семантическое свойство]] можно получить по значению его свойства [[developers:​references:​topomatic.smt.semanticnode.tag|SemanticNode.Tag]]. Далее, зная его тип можно присвоить ему соответствующее значение. В этом примере мы будем менять значение свойства с плавающей точкой со значением тега ''​CENTER''​.
 +
 +{{ :​developers:​tutorial:​surfaceelementsedit:​tutsemprop.png?​nolink&​600 |}}
 +
 +Список [[road:​commons_tasks:​edit_objects:​start|семантических свойств]] объекта можно получить с помощью метода [[developers:​references:​topomatic.smt.semanticdataset.gettags_system.collections.generic.idictionary_2|SemanticDataSet.GetTags()]]. В качестве аргумента метод принимает словарь [[https://​docs.microsoft.com/​ru-ru/​dotnet/​api/​system.collections.generic.dictionary-2?​view=net-6.0|Dictionary<​string,​string>​]],​ который будет заполнен доступными значениями.
 +
 +После назначения [[road:​commons_tasks:​purpose_objects_semantics:​start|объекта семантики]] у [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точки поверхности]],​ следует вызвать метод [[developers:​references:​topomatic.sfc.layer.surfaceextentions.refreshpointsign|Surface.RefreshPointSign()]] для перерисовки отображения условного знака объекта.
 +
 +В теле программного модуля объявите команду,​ и декорируйте её атрибутом «cmd». Команда «change_point_semantic_code» предложит пользователю выбрать [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точку поверхности]] и задать значение отметки центра. Результатом действия станет изменение [[road:​commons_tasks:​purpose_objects_semantics:​start|семантического объекта]] [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точки поверхности]] и заполнение свойства ''​Отметка центра''​ значением указанным пользователем.
 +
 +<code csharp>
 +{
 +...
 +    [cmd("​change_point_semantic_code"​)]
 +    private void ChangePointSemanticCode()
 +    {
 +        //​Находим активный SurfaceLayer
 +        var cadview = CadView;
 +        if (cadview == null) return;
 +
 +        var layer = SurfaceLayer.GetSurfaceLayer(cadview);​
 +        if (layer == null) return;
 +
 +        //​Выбираем точку поверхности
 +        int ind;
 +        var res = layer.PickOnePoint(null,​ out ind, "​Выберите точку поверхности:"​);​
 +        if (res == GetPointResult.Cancel) return;
 +
 +        //​Задаём отметку
 +        var elev = 0.0;
 +        res = CadCursors.GetDouble(cadview,​ ref elev, "​Задайте отметку центра:"​);​
 +        if (res == GetPointResult.Cancel) return;
 +
 +        //​Фиксируем момент начала внесения изменений в поверхность
 +        var sfc = layer.Surface;​
 +        sfc.BeginUpdate("​Преобразование точки поверхности в пункт гос. геод. сети"​);​
 +
 +        try
 +        {
 +            //​Задаём точке код объекта и присваиваем значение свойству ​
 +            var info = sfc.Points.GetExtensiveInformation(ind);​
 +            info.Code = 1000;
 +
 +            var tags = new Dictionary<​string,​ string>​();​
 +            info.Semantic.GetStringTags(tags);​
 +            if (tags.ContainsKey("​CENTER"​)) info.Semantic["​CENTER"​] = elev;
 +
 +            sfc.RefreshPointSign(info);​
 +        }
 +        finally
 +        {
 +            //​Фиксируем окончание внесения изменений в поверхность
 +            sfc.EndUpdate();​
 +        }
 +                            ​
 +        //​Очищаем список выбранных элементов поверхности
 +        //и сообщаем CadView о необходиомсти обновить отображение его содержимого
 +        layer.SelectionSet.Clear();​
 +        cadview.Unlock();​
 +        cadview.Invalidate();​
 +    }
 +...
 +}
 +</​code>​
 +
 +{{ :​developers:​tutorial:​surfaceelementsedit:​tutchangepointsemantic.png?​nolink&​600 |}}
 +
 +Теперь необходимо сформировать наш файл .plugin. Заполните его следующим образом.
 +
 +<code javascript>​
 +{
 +  "​assemblies":​ {
 +    "​TutorialEditSurfaceElements":​ {
 +      "​assembly":​ "​TutorialEditSurfaceElements.dll,​ TutorialEditSurfaceElements.ModulePluginHost"​
 +    }
 +  },
 +
 +  "​actions":​ {
 +    "​id_create_hill_or_pit":​ {
 +      "​cmd":​ "​create_hill_or_pit",​
 +      "​title":​ "​Построить насыпь или котлован"​
 +    },
 +    "​id_change_point_semantic_code":​ {
 +      "​cmd":​ "​change_point_semantic_code",​
 +      "​title":​ "​Преобразование точки поверхности в пункт гос. геод. сети"​
 +    }
 +  },
 +
 +  "​menubars":​ {
 +    "​rbproj":​ {
 +      "​items":​ [
 +        {
 +          "​id":​ "​tutorial_menu",​
 +          "​title":​ "​Tutorial",​
 +          "​items":​ [
 +            "​id_create_hill_or_pit",​
 +            "​id_change_point_semantic_code"​
 +          ]
 +        }
 +      ]
 +    }
 +  }
 +}
 +</​code>​
 +
 +Результатом запуска проекта будет появление в главном меню пункта «Tutorial»,​ с подпунктами,​ которые будут работать в соответствии с описанными выше алгоритмами.
 +
 +<​note>​[[developers:​tutorial:​tutorialcode|Исходный код]] примера расположен в проекте **"​TutorialEditSurfaceElements"​**.</​note>​
developers/tutorial/sfcedit.1649353253.txt.gz · Последние изменения: 2022/04/07 17:40 — proxor