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

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


developers:tutorial:sfcselection

Различия

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

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

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
developers:tutorial:sfcselection [2022/03/02 21:13]
proxor [Выделение структурных линий]
developers:tutorial:sfcselection [2022/04/09 18:55] (текущий)
proxor [Выделение горизонталей]
Строка 1: Строка 1:
 ====== Выделение элементов поверхности ====== ====== Выделение элементов поверхности ======
  
-Нередко,​ при работе с поверхностью,​ пользователю требуется изменять или получать информацию из её элементов. В этой главе мы рассмотрим простые примеры по работе с элементами поверхности.+Нередко,​ при работе с [[road:​work_with_cmm:​create_and_edit_surface_new:​basic_terms_and_definition_new|поверхностью]], пользователю требуется изменять или получать информацию из её элементов. В этой главе мы рассмотрим простые примеры по работе с элементами поверхности.
  
-В качестве основного инструмента получения элементов поверхности рекомендуется пользоваться методами ​класса ​''​SurfaceLayer''​Некоторые из них мы рассмотрим в следующих примерах. Сперва выберем необходимые нам объекты и начнём мы с выбора точек ​поверхности. ​+Программноповерхность представляет из себя экземпляр класса ​[[developers:​references:​topomatic.sfc.surface|Surface]]. Этот класс ​содержит в себе все элементы поверхности.
  
 +Основные элементы класса [[developers:​references:​topomatic.sfc.surface|Surface]] это:
 +  * [[developers:​references:​topomatic.sfc.surface.points|Surface.Points]] - массив [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точек поверхности]] типа [[developers:​references:​topomatic.sfc.surfacepointarray|SurfacePointArray]]
 +  * [[developers:​references:​topomatic.sfc.surface.structurelines|Surface.StructureLines]] - коллекция [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурных линий]] содержащихся в поверхности типа [[developers:​references:​topomatic.sfc.structurelines|StructureLines]]
 +  * [[developers:​references:​topomatic.sfc.surface.triangles|Surface.Triangles]] - массив треугольников отписывающих кривизну рельефа типа [[developers:​references:​topomatic.sfc.surfacetrianglearray|SurfaceTriangleArray]]
 +  * [[developers:​references:​topomatic.sfc.surface.patchs|Surface.Patchs]] - массив [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_of_parcels_new|участков]] типа [[developers:​references:​topomatic.sfc.surfacepatcharray|SurfacePatchArray]]
 +
 +Базовыми элементами поверхности являются точки поверхности и структурные линии. Опираясь на них, в модели поверхности формируется триангуляция состоящая из треугольников,​ которые в свою очередь способны объединяться в участки,​ а так же на основе которых генерируются горизонтали. Более подробно о работе с элементами поверхности в программном комплексе [[http://​topomatic.ru|Топоматик Робур]] можно ознакомиться [[road:​work_with_cmm:​create_and_edit_surface_new:​start|здесь]].
 +
 +Прежде чем приступить работе с элементами поверхности,​ создайте и настройте новый [[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]] - слой поверхности
 +
 +В качестве основного инструмента получения элементов поверхности рекомендуется пользоваться методами слоя поверхности ''​SurfaceLayer''​. Для получения текущего ''​SurfaceLayer'',​ необходимо воспользоваться статическим методом ''​SurfaceLayer.GetSurfaceLayer(cadview)''​. В качестве аргумента метод принимает видовой экран [[developers:​references:​topomatic.cad.view.cadview|CadView]],​ который мы получаем пользуясь свойством ''​CadView''​ [[developers:​tutorial:​module|нашего модуля]].
 +
 +==== Множественный выбор ====
 +''​SurfaceLayer''​ предоставляет широкий набор инструментов для выделения элементов поверхности. Ниже описаны методы позволяющие пользователю осуществить выбор:
 +  * SurfaceLayer.SelectPoints() - выделение [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точек поверхности]]
 +  * SurfaceLayer.SelectStructureLines() - выделение [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_structural_lines_new|структурных линий]]
 +  * SurfaceLayer.SelectPatches() - выделение [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_of_parcels_new|участков]]
 +
 +Все перечисленные методы принимают одинаковый набор аргументов и возвращают результат выполнения пользовательского запроса типа [[developers:​references:​topomatic.cad.view.getpointresult|GetPointResult]].
 +
 +В качестве первого аргумента,​ принимается предикат выполняющий роль фильтра выделяемых объектов. Предикат должен возвращать значение типа ''​bool'',​ которое указывает на необходимость выделения объекта описанного в предикате. На входе у предиката принимается индекс выбираемого элемента в множестве соответствующем его типу. Например мы хотим ограничиться выбором только ситуационных точек, тогда код должен выглядеть следующим образом:​
 +
 +<code csharp>
 + var result = surfaceLayer.SelectPoints(i => surfaceLayer.Surface.Points[i].IsSituation,​ "​Выделите ситуационные точки:"​);​
 +</​code>​
 +
 +В качестве второго аргумента принимается текст сообщения выводящийся пользователю на экран во время выполнения команды.
 +
 +Третий представляет из себя массив строк. Аргумент является опциональным и может не использоваться. Он позволяет предоставить пользователю возможность осуществить выбор из предложенных ему вариантов.
 +
 +Возвращаемое значение [[developers:​references:​topomatic.cad.view.getpointresult|GetPointResult]] указывает на то, какое действие было совершено пользователем. Пользователь может выделить элементы поверхности и подтвердить выбор (''​Accept''​),​ отменить действие (''​Cancel''​) или выбрать один из предложенных вариантов контекстного меню (''​UserCmd''​).
 +
 +<​note>​Значение ''​UserCmd''​ возвращается только в том случае,​ если в качестве третьего аргумента был передан массив строк и пользователь выбрал одно из предложенных значений. Чтобы понять какой именно ​ пункт был выбран пользователем,​ следует воспользоваться свойством [[developers:​references:​topomatic.cad.view.cadview.lastusercmd|CadView.LastUserCmd]].</​note>​
 +
 +==== Одиночный выбор ====
 +Так же ''​SurfaceLayer''​ располагает возможностью выделения одного конкретного объекта:​
 +  * SurfaceLayer.PickOnePoint() - выделение одной [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_dots_new|точки поверхности]]. В качестве аргументов принимаются предикат-фильтр,​ аналогично описанному ранее, переменная типа ''​int''​ с модификатором ''​out'',​ в которую будет сохранён индекс выбранной точки, сообщение пользователю и массив строк с вариантами пользовательского выбора. Возвращаемое значение [[developers:​references:​topomatic.cad.view.getpointresult|GetPointResult]],​ описанное выше.
 +  * SurfaceLayer.SelectOneStructureLine() - выделение одной [[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|структурную линию]].
 +  * SurfaceLayer.SelectOnePatch() - выбор одного [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_of_parcels_new|участка]]. Аргументы предикат-фильтр и сообщение пользователю. Метод возвращает индекс участка из [[road:​work_with_cmm:​create_and_edit_surface_new:​notion_of_parcels_new|массива участков]].
 ===== Выделение точек поверхности ===== ===== Выделение точек поверхности =====
 В этом примере мы выберем точки поверхности на вкладке "​План"​ и рассчитаем их среднюю отметку. В этом примере мы выберем точки поверхности на вкладке "​План"​ и рассчитаем их среднюю отметку.
 Для этого воспользуемся методом ''​SelectPoints()''​ у слоя текущей поверхности (''​SurfaceLayer''​). Так как метод ''​SelectPoints()''​ предоставляет пользователю возможность выбора элементов контекстного меню, то возвращаемое значение будет иметь вид ''​GetPointResult'',​ которое укажет на то, какое именно действие было совершено пользователем. Для этого воспользуемся методом ''​SelectPoints()''​ у слоя текущей поверхности (''​SurfaceLayer''​). Так как метод ''​SelectPoints()''​ предоставляет пользователю возможность выбора элементов контекстного меню, то возвращаемое значение будет иметь вид ''​GetPointResult'',​ которое укажет на то, какое именно действие было совершено пользователем.
  
-Для того чтобы получить множество выбранных точек, будет необходимо воспользоваться методом ''​GetSelectedPoints()''​ у того же ''​SurfaceLayer''​. Далее пройдёмся по выбранным точкам циклом ''​foreach''​ и применим необходимую логику для расчёта средней отметки+Для того чтобы получить множество выбранных точек, будет необходимо воспользоваться методом ''​GetSelectedPoints()''​ у того же ''​SurfaceLayer''​.
  
-Ниже представлен код ​примера, который ​мы оформим ​в качестве метода ''​CalculateAverageElevation()''​ с атрибутом ​''​[cmd("​calculate_average_elevation"​)]''​Данный метод мы поместим в класс ''​Module'' ​для возможности последующего ​вызова этой команды из командной строки.+В теле программного модуля ​объявите ​команду, и декорируйте её атрибутом ​«cmd»Команда "​calculate_average_elevation" ​предложит пользователю выбрать точки поверхности и посчитает их среднюю отметку.
  
 <code csharp> <code csharp>
Строка 48: Строка 94:
 } }
 </​code>​ </​code>​
 +
 +{{ :​developers:​tutorial:​surfaceelementsselect:​tutselpoints.png?​nolink&​600 |}}
  
  
Строка 53: Строка 101:
  
 ===== Выделение структурных линий ===== ===== Выделение структурных линий =====
-В данном примере мы попробуем ​рассчитать максимальный уклон среди всех сегментов структурной линии. +В данном примере мы рассчитаем максимальный уклон среди всех сегментов структурной линии. 
-Как и в предыдущем примере,​ для выбора структурной линии нам потребуется слой текущей поверхности (''​SurfaceLayer''​). Чтобы выбрать одну структурную линию, воспользуемся методом ''​SelectOneStructureLine()''​. Здесь возвращаемым значением сразу же будет ​выступать ​выбранная структурная линия ​(''​StructureLine''​), поэтому никаких дополнительных действий выполнять не придется.+Как и в предыдущем примере,​ для выбора структурной линии нам потребуется слой текущей поверхности (''​SurfaceLayer''​). Чтобы выбрать одну структурную линию, воспользуемся методом ''​SelectOneStructureLine()''​. Здесь возвращаемым значением сразу же будет выбранная ​[[developers:​references:​topomatic.sfc.structureline|структурная линия]], поэтому никаких дополнительных действий выполнять не придется.
  
-Воспользуемся циклом ''​for'',​ чтобы обратиться к узлам структурной линии и в каждой итерации будет обращаться к текущей точке цикла и к следующей,​ тем самым получая представление о сегменте структурной линии. +<​note>​Важно помнить,​ что ​[[developers:​references:​topomatic.sfc.structurelinenode|узел структурной линии]] всегда опирается на [[developers:​references:​topomatic.sfc.surfacepoint|точку поверхности]], индекс которой хранится в поле ​[[developers:​references:​topomatic.sfc.structurelinenode.index|StructureLineNode.Index]]. Узел не несёт информации о его плановом положении,​ но при помощи индекса опорной точки, мы можем найти её в [[developers:​references:​topomatic.sfc.surfacepointarray|массиве точек поверхности]] и получить необходимые данные о расположении этого узла в пространстве.</​note>​
-<​note>​Для того чтобы мы не получили исключение в результате обращения к последующему узлу структурной линии в последней итерации,​ заведомо уменьшим количество итераций цикла на 1.</​note>​ +
-<​note>​Важно помнить,​ что узел структурной линии всегда опирается на точку поверхности,​ индекс которой хранится в поле ​''​StructureLineNode.Index''​. Узел не несёт информации о его плановом положении,​ но при помощи индекса опорной точки, мы можем найти её в массиве точек поверхности и получить необходимые данные о расположении этого узла в пространстве.</​note>​ +
-В ходе цикла определяется уклон сегмента на текущей итерации и если он больше,​ чем предыдущее значение,​ то запоминаем его и, после выхода из цикла, выводим диалоговое окно с рассчитанными данными.+
  
-Ниже представлен код ​примера, который ​мы оформим ​в качестве метода ''​DefineSteepestGrade()''​ с атрибутом ​''​[cmd(«define_steepest_grade»)]''​Данный метод мы поместим в класс Module ​для возможности последующего ​вызова этой команды из командной ​строки.+В теле программного модуля ​объявите ​команду, и декорируйте её атрибутом ​«cmd»Команда «define_steepest_grade» ​предложит пользователю выбрать структурную линию и определит ​максимальный уклон среди всех её сегментов.
  
 <code csharp> <code csharp>
Строка 104: Строка 149:
 } }
 </​code>​ </​code>​
 +
 +{{ :​developers:​tutorial:​surfaceelementsselect:​tutselstrline.png?​nolink&​600 |}}
 +===== Выделение горизонталей =====
 +По умолчанию,​ в программном комплексе [[http://​topomatic.ru|Топоматик Робур]],​ выделение горизонталей отключено. Чтобы включить выделение горизонталей нужно изменить значение статического свойства ''​SurfaceLayer.SurfaceSelectionSet.IsHorizontalSelectable''​ на ''​true''​. Взаимодействовать с объектами горизонталей напрямую нельзя,​ но горизонтали реализуют интерфейс [[developers:​references:​topomatic.cad.foundation.ilinearobject|ILinearObject]],​ поэтому мы можем получить [[developers:​references:​topomatic.cad.foundation.polyline3d|трёхмерную полилинию]] описывающую положение горизонтали,​ воспользовавшись методом [[developers:​references:​topomatic.cad.foundation.ilinearobject.getpolyline_topomatic.cad.foundation.ipolyline3d|GetPolyline()]]. Для получения площади [[developers:​references:​topomatic.cad.foundation.polyline3d|трёхмерной полилинии]] воспользуемся методом расширения [[developers:​references:​topomatic.cad.foundation.polylineextentions.getarea2d_topomatic.cad.foundation.ipolyline3d|PolylineExtentions.GetArea2D(IPolyline3D)]]
 +
 +В теле программного модуля объявите команду,​ и декорируйте её атрибутом «cmd». Команда "​get_horizontal_line_area"​ предложит пользователю выбрать замкнутую горизонталь и определит её площадь.
 +
 +<code csharp>
 +...
 +    [cmd("​get_horizontal_line_area"​)]
 +    private void GetHorizontalLineArea()
 +    {
 +        //​Находим активный SurfaceLayer
 +        var cadview = CadView;
 +        var actSfcLayer = SurfaceLayer.GetSurfaceLayer(cadview);​
 +        if (actSfcLayer == null) return;
 +
 +        //​Включаем возможность выбор горизонталей
 +        var initSelectState = SurfaceLayer.SurfaceSelectionSet.IsHorizontalSelectable;​
 +        SurfaceLayer.SurfaceSelectionSet.IsHorizontalSelectable = true;
 +
 +        //​Получаем указатель на текущий набор объектов
 +        var ss = actSfcLayer.SelectionSet;​
 +
 +        //​Получаем указатель на слой горизонталей
 +        var layer = actSfcLayer.Surface.Style.HorizontalsStyle.GetLayer();​
 +
 +        //​Выбираем горизонталь на плане
 +        var linear_object = ss.PickOneObjectAtScreen(obj =>
 +        {
 +            if (obj is SurfaceObjectWrapper layered_object)
 +            {
 +                return layered_object.LayerID == layer.ObjectID;​
 +            }
 +            return false;
 +        }, "​Выберите замкнутую горизонталь"​) as ILinearObject;​
 +
 +        //​Восстанавливаем состояние флага возможности выбора горизонталей
 +        SurfaceLayer.SurfaceSelectionSet.IsHorizontalSelectable = initSelectState;​
 +        if (linear_object == null) return;
 +
 +        //​Извлекаем полилинию из горизонтали и получаем её площадь
 +        var poly = new Polyline3D();​
 +        linear_object.GetPolyline(poly);​
 +
 +        //​Проверяем замкнута ли горизонталь
 +        var startVec = poly[0];
 +        var endVec = poly[poly.Count - 1];
 +        if (startVec.EqualEps(endVec))
 +        {
 +            var area = poly.GetArea2D();​
 +            MessageDlg.Show($"​Площадь горизонтали:​ {area}"​);​
 +        }
 +        else MessageDlg.Show($"​Горизонталь не замкнута."​);​
 +    }
 +...
 +</​code>​
 +
 +{{ :​developers:​tutorial:​surfaceelementsselect:​tutselhorizontal.png?​nolink&​600 |}}
 +
 +
 +
 +Теперь необходимо сформировать наш файл .plugin. Заполните его следующим образом.
 +
 +<code javascript>​
 +{
 +  "​assemblies":​ {
 +    "​TutorialSelectSurfaceElements":​ {
 +      "​assembly":​ "​TutorialSelectSurfaceElements.dll,​ TutorialSelectSurfaceElements.ModulePluginHost"​
 +    }
 +  },
 +
 +  "​actions":​ {
 +    "​id_calculate_average_elevation":​ {
 +      "​cmd":​ "​calculate_average_elevation",​
 +      "​title":​ "​Рассчитать среднюю отметку"​
 +    },
 +    "​id_define_steepest_grade":​ {
 +      "​cmd":​ "​define_steepest_grade",​
 +      "​title":​ "​Рассчитать наибольший уклон"​
 +    },
 +    "​id_get_horizontal_line_area":​ {
 +      "​cmd":​ "​get_horizontal_line_area",​
 +      "​title":​ "​Получить площадь горизонтали"​
 +    }
 +  },
 +
 +  "​menubars":​ {
 +    "​rbproj":​ {
 +      "​items":​ [
 +        {
 +          "​id":​ "​tutorial_menu",​
 +          "​title":​ "​Tutorial",​
 +          "​items":​ [
 +            "​id_calculate_average_elevation",​
 +            "​id_define_steepest_grade",​
 +            "​id_get_horizontal_line_area"​
 +          ]
 +        }
 +      ]
 +    }
 +  }
 +}
 +</​code>​
 +
 +Результатом запуска проекта будет появление в главном меню пункта «Tutorial»,​ с подпунктами,​ которые будут работать в соответствии с описанными выше алгоритмами.
 +
 +<​note>​[[developers:​tutorial:​tutorialcode|Исходный код]] примера расположен в проекте **"​TutorialSelectSurfaceElements"​**.</​note>​
developers/tutorial/sfcselection.1646255605.txt.gz · Последние изменения: 2022/03/02 21:13 — proxor