Здесь показаны различия между двумя версиями данной страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
developers:tutorial:sfcedit [2022/04/07 17:39] proxor |
developers:tutorial:sfcedit [2022/04/09 18:54] (текущий) proxor [Редактирование элементов поверхности] |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
====== Добавление и редактирование элементов поверхности ====== | ====== Добавление и редактирование элементов поверхности ====== | ||
+ | ==== Добавление и редактирование точек поверхности ==== | ||
Одним из основных элементов [[road:work_with_cmm:create_and_edit_surface_new:basic_terms_and_definition_new|поверхности]] является [[road:work_with_cmm:create_and_edit_surface_new:notion_dots_new|съёмочная точка]] типа [[developers:references:topomatic.sfc.surfacepoint|SurfacePoint]]. Так как [[developers:references:topomatic.sfc.surfacepoint|SurfacePoint]] является структурой, а не классом, редактирование [[developers:references:topomatic.sfc.surfacepoint|SurfacePoint]] напрямую не приведёт к желаемому результату. Добавления новых и редактирование существующих [[road:work_with_cmm:create_and_edit_surface_new:notion_dots_new|точек]] осуществляется с помощью специального класса [[developers:references:topomatic.sfc.pointeditor|PointEditor]]. | Одним из основных элементов [[road:work_with_cmm:create_and_edit_surface_new:basic_terms_and_definition_new|поверхности]] является [[road:work_with_cmm:create_and_edit_surface_new:notion_dots_new|съёмочная точка]] типа [[developers:references:topomatic.sfc.surfacepoint|SurfacePoint]]. Так как [[developers:references:topomatic.sfc.surfacepoint|SurfacePoint]] является структурой, а не классом, редактирование [[developers:references:topomatic.sfc.surfacepoint|SurfacePoint]] напрямую не приведёт к желаемому результату. Добавления новых и редактирование существующих [[road:work_with_cmm:create_and_edit_surface_new:notion_dots_new|точек]] осуществляется с помощью специального класса [[developers:references:topomatic.sfc.pointeditor|PointEditor]]. | ||
Строка 11: | Строка 11: | ||
* [[developers:references:topomatic.sfc.pointeditor.transform_system.collections.generic.ienumerable_1_topomatic.cad.foundation.matrix|PointEditor.Transform()]] - изменение расположения существующих [[road:work_with_cmm:create_and_edit_surface_new:notion_dots_new|точек поверхности]] в пространстве с помощью матрицы преобразования | * [[developers:references:topomatic.sfc.pointeditor.transform_system.collections.generic.ienumerable_1_topomatic.cad.foundation.matrix|PointEditor.Transform()]] - изменение расположения существующих [[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.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> | ||
+ | |||
+ | |||
+ | ==== Настройка проекта 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> | ||
- | <note>Важно помнить, что [[road:work_with_cmm:create_and_edit_surface_new:notion_structural_lines_new|структурная линия]] всегда опирается на [[developers:references:topomatic.sfc.surfacepoint|точки поверхности]] и не может существовать без них.</note> | + | Результатом запуска проекта будет появление в главном меню пункта «Tutorial», с подпунктами, которые будут работать в соответствии с описанными выше алгоритмами. |
+ | <note>[[developers:tutorial:tutorialcode|Исходный код]] примера расположен в проекте **"TutorialEditSurfaceElements"**.</note> |