Резиновая штриховая линия при перемещении ручки.

Автор Тема: Резиновая штриховая линия при перемещении ручки.  (Прочитано 7373 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Всем привет!
При перемещении стандартной ручки у объекта (Civil 3D, труба на виде профиля) появляется линия, которая визуализирует смещение курсора относительно исходного положения ручки и соответствующее ему смещение самой ручки. Выглядит это так:

Я уже себе всю голову сломал пытаясь придумать как мне для моих ручек сделать такую же линию.
Может быть, у вас есть какие-нибудь идеи на этот счёт?
Что я уже попробовал:
- в методе GripData.ViewportDraw добавлял отрисовку линий по данным из вектора перемещения ручки с помощью ViewportDraw.Geometry.DeviceContextPolyline. Получается рисовать сплошной линией. Но у неё задать даже толщину не получается с помощью ViewportDraw.SubEntityTraits.LineWeight, не говоря уже о том, чтобы рисовать её прерывистой.
- в том же методе попробовал отрисовывать ряд точек с помощью метода ViewportDraw.Geometry.RowOfDots. Мало того, что он работает как-то через раз, так ещё и точки получаются очень тонкими, не такими, как у оригинальной ручки. И на изменение настроек ViewportDraw.SubEntityTraits.LineWeight они тоже не реагируют.
Пока что это выглядит вот так:

Есть, конечно, мысль, что чтобы получить толстую линию, надо вычислять размер пикселя в единицах чертежа и рисовать несколько линий друг с другом вплотную. А чтобы получить прерывистую - вычислять массив точек с учётом промежутков и строить кучу маленьких штрих-отрезков вместо одной сплошной линии. Но как-то это очень костыльно, на мой взгляд. Может есть идеи получше?


Онлайн avc

  • ADN Club
  • *****
  • Сообщений: 806
  • Карма: 166
    • Мои плагины к Автокаду
Похоже на самую обычную линию при вводе точек, которая появляется при установке PromptPointOptions.BasePoint на стартовыю точку
Код - C# [Выбрать]
  1. PromptPointOptions ppo = new PromptPointOptions("Стартовая");
  2.             ppo.AllowNone = false;
  3.             PromptPointResult pr = ed.GetPoint(ppo);
  4.             if (pr.Status != PromptStatus.OK) return;
  5.             Point3d arrowP = pr.Value;
  6.             ppo.Message = "Конечная";
  7.             ppo.UseDashedLine = true;
  8.             ppo.UseBasePoint = true;
  9.             ppo.BasePoint = arrowP;
  10.             pr = ed.GetPoint(ppo);

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Та, что на скриншоте?


Дык ее не надо реализовывать - это же сам автокад делает

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Наверное я наврал. Чтобы она была скорее всего надо реализовать OsnapOverrule. Типа того
Код - C# [Выбрать]
  1. namespace mpESKD.Functions.mpBreakLine.Overrules
  2. {
  3.     using System;
  4.     using Autodesk.AutoCAD.DatabaseServices;
  5.     using Autodesk.AutoCAD.Geometry;
  6.     using Autodesk.AutoCAD.Runtime;
  7.     using Base.Helpers;
  8.     using ModPlusAPI.Windows;
  9.     using System.Diagnostics;
  10.     using Base;
  11.  
  12.     public class BreakLineOsnapOverrule : OsnapOverrule
  13.     {
  14.         protected static BreakLineOsnapOverrule _breakLineOsnapOverrule;
  15.         public static BreakLineOsnapOverrule Instance()
  16.         {
  17.             if (_breakLineOsnapOverrule != null) return _breakLineOsnapOverrule;
  18.             _breakLineOsnapOverrule = new BreakLineOsnapOverrule();
  19.             // Фильтр "отлова" примитива по расширенным данным. Работает лучше, чем проверка вручную!
  20.             _breakLineOsnapOverrule.SetXDataFilter(BreakLineDescriptor.Instance.Name);
  21.             return _breakLineOsnapOverrule;
  22.         }
  23.  
  24.         public override void GetObjectSnapPoints(Entity entity, ObjectSnapModes snapMode, IntPtr gsSelectionMark, Point3d pickPoint,
  25.             Point3d lastPoint, Matrix3d viewTransform, Point3dCollection snapPoints, IntegerCollection geometryIds)
  26.         {
  27.             Debug.Print("BreakLineOsnapOverrule");
  28.             if (IsApplicable(entity))
  29.             {
  30.                 try
  31.                 {
  32.                     var breakLine = EntityReaderFactory.Instance.GetFromEntity<BreakLine>(entity);
  33.                     if (breakLine != null)
  34.                     {
  35.                         snapPoints.Add(breakLine.InsertionPoint);
  36.                         snapPoints.Add(breakLine.EndPoint);
  37.                     }
  38.                 }
  39.                 catch (Autodesk.AutoCAD.Runtime.Exception exception)
  40.                 {
  41.                     ExceptionBox.Show(exception);
  42.                 }
  43.             }
  44.             else base.GetObjectSnapPoints(entity, snapMode, gsSelectionMark, pickPoint, lastPoint, viewTransform, snapPoints, geometryIds);
  45.         }
  46.  
  47.         public override bool IsApplicable(RXObject overruledSubject)
  48.         {
  49.             return ExtendedDataHelpers.IsApplicable(overruledSubject, BreakLineDescriptor.Instance.Name);
  50.         }
  51.     }
  52. }

Вот тогда и привязки будут ловится и линия эта строиться. Это предположительно, так как не могу проверить без OsnapOverrule

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Похоже на самую обычную линию при вводе точек, которая появляется при установке PromptPointOptions.BasePoint на стартовыю точку
Дык ее не надо реализовывать - это же сам автокад делает
Это не та линия. Стандартная линия рисуется из базовой точки к курсору. А мне нужна такая, чтобы рисовалась "углом" - по вертикали до уровня курсора и потом по горизонтали к нему.
Вот тогда и привязки будут ловится и линия эта строиться. Это предположительно, так как не могу проверить без OsnapOverrule
Это линии трассировки - они строятся нормально, с привязками нет проблем. А та линия, про которую я говорю - это именно вспомогательная резиновая линия, с привязками никак не связанная.
Сделал общую картинку для наглядности:

Анимашка:


Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Мне кажется, что смотреть нужно в сторону Transient. Там вон вижу перечислитель TransientDrawingMode у которого есть интересное значение Highlight

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А чтобы получить прерывистую - вычислять массив точек с учётом промежутков и строить кучу маленьких штрих-отрезков вместо одной сплошной линии.
Похоже так и придётся. Точнее кучу кружков при помощи Geometry.Circle с небольшим радиусом, зависящим от высоты видового экрана. Во всяком случае я пока не вижу других альтернатив.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А чтобы получить прерывистую - вычислять массив точек с учётом промежутков и строить кучу маленьких штрих-отрезков вместо одной сплошной линии.
Похоже так и придётся. Точнее кучу кружков при помощи Geometry.Circle с небольшим радиусом, зависящим от высоты видового экрана. Во всяком случае я пока не вижу других альтернатив.
Лучше уж тогда просто цветные вспомогательные линии - и понятней и проще. ИМХО



Кстати, если во время перемещения ручки выполнить зуммирование колесиком мышки, то столкнетесь с кучей проблем )

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Лучше уж тогда просто цветные вспомогательные линии - и понятней и проще. ИМХО
Дмитрий Загорулькин, как я понимаю, хочет сделать в точности так, как это сделано в Civil 3D. В противном случае какой смысл заморачиваться?
Кстати, если во время перемещения ручки выполнить зуммирование колесиком мышки, то столкнетесь с кучей проблем )
Да. Теоретически понадобится обрабатывать это событие и менять масштаб (и соответственно расстояние между кружками и возможно радиус).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Александр Ривилис 12-12-2018, 19:45:58

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Получилось!
Правда, пришлось использовать полилинию, т.к. только у неё удалось задать толщину.
Итоговый вспомогательный метод:
Код - C# [Выбрать]
  1. public static void DrawDashedLine
  2.     (ViewportDraw vd,
  3.     Point3d startModelPt,
  4.     Point3d endModelPt)
  5. {
  6.     Point2d glyphSize
  7.         = vd.Viewport.GetNumPixelsInUnitSquare(startModelPt);
  8.  
  9.     Vector3d
  10.         lineDir3d = startModelPt.GetVectorTo(endModelPt);
  11.  
  12.     Vector2d
  13.         lineDir2d = new Vector2d(lineDir3d.X, lineDir3d.Y),
  14.         lineNormDir2d = lineDir2d.GetNormal();
  15.  
  16.     double
  17.         lineLength = lineDir2d.Length,
  18.         screenSizeFactor = (glyphSize.X + glyphSize.Y) / 2.0,
  19.         step = 5.0 / screenSizeFactor,
  20.         size = 1.0 / screenSizeFactor,
  21.         plineWidth = 0.1 / screenSizeFactor;
  22.  
  23.     Point2d startModelPt2d
  24.         = new Point2d(startModelPt.X, startModelPt.Y);
  25.  
  26.     if (lineLength > 0.0
  27.         && step > 0.0
  28.         && size > 0.0)
  29.     {
  30.         double curDist;
  31.         int i = 0;
  32.         Color color = Color.FromRgb(137, 137, 137);
  33.  
  34.         while ((curDist = ++i * step) <= lineLength)
  35.         {
  36.             Point2d
  37.                 curEndPt = startModelPt2d + lineNormDir2d.MultiplyBy(curDist),
  38.                 curStartPt = curEndPt - lineNormDir2d.MultiplyBy(size);
  39.  
  40.             using (AcDb.Polyline line = new AcDb.Polyline(2))
  41.             {
  42.                 line.AddVertexAt(0, curStartPt, 0, plineWidth, plineWidth);
  43.                 line.AddVertexAt(1, curEndPt, 0, plineWidth, plineWidth);
  44.                 line.ConstantWidth = plineWidth;
  45.                 line.Color = color;
  46.                 vd.Geometry.Draw(line);
  47.             }
  48.         }
  49.     }
  50. }
  51.  
Анимашка:


Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А зуммирование в этот момент проверил?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А зуммирование в этот момент проверил?
А анимашку смотрел? Выглядит очень даже прилично.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А зуммирование в этот момент проверил?
А анимашку смотрел? Выглядит очень даже прилично.
В анимашке нет зуммирования - вот и спросил

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
В анимашке нет зуммирования - вот и спросил
Плохо смотрел. Есть там зуммирование.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
При зуммировании автоматически внутренними механизмами самого AutoCAD-Civil вызывается метод перерисовки ручки ViewportDraw, в котором вызывается метод отрисовки этой линии. В методе есть определение коэффициента, который учитывает размер экрана. Поэтому, при зуммировании никаких проблем не возникает - геометрия всегда отрисовывается корректно.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Да, не досмотрел анимашку))
Проблема с зуммированием вероятно связана с тем, откуда работает метод - в самой overrule или в методах ручки

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Возможно. Я не помню, правда, чтобы где-то ловил проблему с зуммированием. Но стало любопытно :) Есть пример?

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Возможно. Я не помню, правда, чтобы где-то ловил проблему с зуммированием. Но стало любопытно :) Есть пример?
Да вот в том-то и дело, что нет) Пробовал что-то - не получилось - пошёл другим путём) Может в следующий раз опять наткнусь

Онлайн avc

  • ADN Club
  • *****
  • Сообщений: 806
  • Карма: 166
    • Мои плагины к Автокаду
Мне кажется, что смотреть нужно в сторону Transient.
Неее, туда лучше не cмотреть. Багосборник-фаталогенератор :(

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Мне кажется, что смотреть нужно в сторону Transient.
Неее, туда лучше не cмотреть. Багосборник-фаталогенератор :(
Не скажу, что в полный рост и везде использую, но есть у меня один инструмент, в котором для временной отрисовки применена транзиентная графика. Работает стабильно и безглючно. Есть какие-то проблемы с ней? Очень интересно! Мало ли - вдруг проблема есть, а пользователи молчат...

Онлайн avc

  • ADN Club
  • *****
  • Сообщений: 806
  • Карма: 166
    • Мои плагины к Автокаду
Есть какие-то проблемы с ней?
Да, глюки и фаталы. Вывести блок вообще не могу - фатал стабильно и сразу, даже если сначала сделать Explode. Но даже избегая блоков Автокад вышибает регулярно. Очень может быть, что я просто не знаю как этих кошек готовить... Просто вывести клон Entity мало - он сразу исчезнет при сборке мусора. Приходится хранить ссылку на него в специальном статическом списке до тех пор пока надо будет стереть. Возможно это и приводит к сбоям, черт его знает... Но это все уже не по теме...