====== Выбор модели подобъекта и преобразование координат ====== В терминологии программного комплекса [[http://www.topomatic.ru|Топоматик Робур]] подобъектами принято называть модели [[road:road:start|автомобильных]] и [[rail:rail:start|железных дорог]], а также [[road:work_with_track:start|модели трасс]]. Подобъекты являются наследниками класса [[developers:references:topomatic.alg.model.alignmentmodel|AlignmentModel]]. Они содержат в себе информацию о плане линии, продольных и поперечных профилях и прочие данные присущие конкретному типу подобъекта. При работе с подобъектами, подавляющее большинство операций производится посредством изменения состояния экземпляра класса [[developers:references:topomatic.alg.alignment|Alignment]], получаемого через свойство [[developers:references:topomatic.alg.model.alignmentmodel.alignment|Alignment]] модели подобъекта. Доступ к наиболее часто используемые данным подобъекта осуществляется через следующие свойства [[developers:references:topomatic.alg.alignment|Alignment]]: * [[developers:references:topomatic.alg.alignment.corridor|Corridor]] - поперечные профили * [[developers:references:topomatic.alg.alignment.plan|Plan]] - план линии * [[developers:references:topomatic.alg.alignment.stationing|Stationing]] - пикетаж * [[developers:references:topomatic.alg.alignment.transitions|Transitions]] - продольные профили ===== Подготовка модуля ===== Создайте и настройте новый [[developers:tutorial:module|модуль]] для подключения к программному комплексу [[http://www.topomatic.ru|Топоматик Робур]]. С помощью диалогового окна Менеджер ссылок добавьте ссылки на следующие библиотеки: * [[developers:references:topomatic.alg|Topomatic.Alg]] - базовые классы подобъектов * [[developers:references:topomatic.cad.foundation|Topomatic.Cad.Foundation.dll]] - базовые математические типы и операции * [[developers:references:topomatic.cad.view|Topomatic.Cad.View.dll]] - элемент управления для отображения слоёв моделей Выбор подобъекта на экране осуществляется с помощью свойства [[developers:references:topomatic.cad.view.cadview.selectionset|SelectionSet]] класса [[developers:references:topomatic.cad.view.cadview|CadView]]. Подробнее о выборе объектов на экране можно узнать в разделе руководства [[developers:tutorial:cadcursors|Выбор элемента и ввод через курсор]]. Для выбора подобъекта воспользуемся методом [[developers:references:topomatic.cad.view.selectionset.selectobjectsatscreen_system.predicate_1_system.string_arr_system.string|SelectObjectsAtScreen]] с соответствующим [[https://docs.microsoft.com/ru-ru/dotnet/api/system.predicate-1?view=net-6.0|предикатом]]. Выбираемый объект должен реализовывать интерфейс IWrapped, а объект возвращаемый его свойством WrappedObject должен быть экземпляром класса [[developers:references:topomatic.alg.alignment|Alignment]]. ===== Преобразование координат ===== В этом примере мы укажем точку на плане и определим соответствующие этой точке пикетаж, смещение от оси и расстояние от начала трассы. Сперва необходимо получить геометрию плана линии. Для этого у [[developers:references:topomatic.alg.alignment|Alignment]]'а получим значение свойства [[developers:references:topomatic.alg.alignment.plan|Plan]]. Далее у полученного плана линии ([[developers:references:topomatic.alg.plan.planline|PlanLine]]) вернём значение свойства [[developers:references:topomatic.alg.plan.planline.compoundline|CompoundLine]]. Смещение и расстояние от начала трассы получается методом [[developers:references:topomatic.alg.compoundline.postostaoffset_topomatic.cad.foundation.vector2d_ref_system.double_ref_system.double|PosToStaOffset]] класса [[developers:references:topomatic.alg.compoundline|CompoundLine]], которому передаётся указанная на плане точка. Для преобразования расстояния от начала трассы в пикетаж получим пикетаж подобъекта через свойство [[developers:references:topomatic.alg.alignment.stationing|Stationing]] у [[developers:references:topomatic.alg.alignment|Alignment]]'а. Преобразование осуществляется методом [[developers:references:topomatic.alg.stationing.algbasestationing.stationtostring_system.double|StationToString]] класса [[developers:references:topomatic.alg.stationing.algbasestationing|AlgBaseStationing]]. В теле программного модуля объявите команду, и декорируйте её атрибутом «cmd». Команда «define_stationing_at_point» предложит пользователю указать точку на плане и определит её пикетаж, расстояние от начала трассы и смещение от оси подобъекта. ... [cmd("define_stationing_at_point")] private void DefineStationingAtPoint() { var cadview = CadView; if (cadview == null) return; //Выбираем трассу object select; var res = cadview.SelectionSet.SelectOneObjectAtScreen( o => o is IWrapped && ((IWrapped)o).WrappedObject is Alignment, out select, "Выберите подобъект:"); cadview.SelectionSet.Clear(); if (res != GetPointResult.Accept) return; var alignment = ((IWrapped)select).WrappedObject as Alignment; var compound = alignment.Plan.CompoundLine; var stationing = alignment.Stationing; //Указываем точку, в которой требуется определить пикетаж Vector3D point; var getPointRes = CadCursors.GetPoint(cadview, out point, "Укажите точку определения пикетажа:"); if (!getPointRes) return; //Определяем расстояние от начала пути и величину смещения до указанной точки double station, offset; var convertRes = compound.PosToStaOffset(point.Pos, out station, out offset); if (!convertRes) { MessageDlg.Show("Не удалось определить расстояние от начала пути в указанной точке.", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); return; } //Определяем пикетаж на полученном расстоянии от начала пути и выводим данные на экран var pkPlus = stationing.StationToString(station); var msg = string.Join(Environment.NewLine, $"ПК{pkPlus}", $"Расстояние: {ValueConverter.FloatToStr(station, 3)}", $"Смещение: {ValueConverter.FloatToStr(offset, 3)}"); MessageDlg.Show(msg, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); } ... {{ :developers:tutorial:alignmentedit:tutalgpnttopksta.png?nolink&600 |}} Далее выполним обратную операцию преобразования. Определим точку на плане по пикетажу и смещению введёнными пользователем. Для этого потребуется преобразовать значение пикетажа в расстояние от начала трассы с помощью метода [[developers:references:topomatic.alg.stationing.algbasestationing.trystringtostation_system.string_ref_system.double|TryStringToStation]] класса [[developers:references:topomatic.alg.stationing.algbasestationing|AlgBaseStationing]]. Точка на плане определяется методом [[developers:references:topomatic.alg.compoundline.staoffsettopos_system.double_system.double_ref_topomatic.cad.foundation.vector2d|StaOffsetToPos]] класса [[developers:references:topomatic.alg.compoundline|CompoundLine]], в который передаётся расстояние от начала трассы и смещение. В теле программного модуля объявите команду, и декорируйте её атрибутом «cmd». Команда «define_point_at_stationing» предложит пользователю ввести пикетаж и смещение от оси подобъекта и определит координаты точки, а также расстояние от начала трассы для введённых параметров. ... [cmd("define_point_at_stationing")] private void DefinePointAtStationing() { var cadview = CadView; if (cadview == null) return; //Выбираем трассу object select; var res = cadview.SelectionSet.SelectOneObjectAtScreen( o => o is IWrapped && ((IWrapped)o).WrappedObject is Alignment, out select, "Выберите подобъект:"); cadview.SelectionSet.Clear(); if (res != GetPointResult.Accept) return; var alignment = ((IWrapped)select).WrappedObject as Alignment; var compound = alignment.Plan.CompoundLine; var stationing = alignment.Stationing; //Вводим пикетаж и определяем расстояние от начала пути var pkPlus = "0+00.00"; res = CadCursors.GetString(cadview, ref pkPlus, "Введите пикетаж в формате ПК+:"); if (res == GetPointResult.Cancel) return; double station; if (!stationing.TryStringToStation(pkPlus, out station)) { MessageDlg.Show("Указанный пикетаж не найден.", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); return; } //Вводим смещение var offset = 0.0; res = CadCursors.GetDouble(cadview, ref offset, "Введите смещение:"); if (res == GetPointResult.Cancel) return; //Определяем координаты по задданым значениям и выводим значения на экран Vector2D point; var vectorFound = compound.StaOffsetToPos(station, offset, out point); if (!vectorFound) { MessageDlg.Show("Не удалось определить координаты.", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); return; } var msg = string.Join(Environment.NewLine, $"X: {ValueConverter.FloatToStr(point.X, 3)}", $"Y: {ValueConverter.FloatToStr(point.Y, 3)}", $"Расстояние: {ValueConverter.FloatToStr(station, 3)}"); MessageDlg.Show(msg, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); } ... {{ :developers:tutorial:alignmentedit:tutalgpkoffsettopos.png?nolink&600 |}} Теперь необходимо сформировать наш файл .plugin. Заполните его следующим образом. { "assemblies": { "TutorialEditAlignment": { "assembly": "TutorialEditAlignment.dll, TutorialEditAlignment.ModulePluginHost" } }, "actions": { "id_define_stationing_at_point": { "cmd": "define_stationing_at_point", "title": "Определить пикетаж в точке" }, "id_define_point_at_stationing": { "cmd": "define_point_at_stationing", "title": "Определить координаты по пикетажу и смещению" } }, "menubars": { "rbproj": { "items": [ { "id": "tutorial_menu", "title": "Tutorial", "items": [ "id_define_stationing_at_point", "id_define_point_at_stationing" ] } ] } } } Результатом запуска проекта будет появление в главном меню пункта «Tutorial», с подпунктами, которые будут работать в соответствии с описанными выше алгоритмами. [[developers:tutorial:tutorialcode|Исходный код]] примера расположен в проекте **"TutorialEditAlignment"**.