Проблема с отрисовкой вспомогательной дуги в PointMonitor

Автор Тема: Проблема с отрисовкой вспомогательной дуги в PointMonitor  (Прочитано 8839 раз)

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Всем привет!
Столкнулся с неожиданной проблемой. Пытаюсь отрисовать вспомогательную дугу в событии PointMonitor и никак не получается. Код:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.GraphicsInterface;
  6. using Autodesk.AutoCAD.Runtime;
  7.  
  8. namespace AcadTest
  9. {
  10.     public class TestEditorDraw
  11.     {
  12.         [CommandMethod("TestEditorDrawArc")]
  13.         public void Run()
  14.         {
  15.             Support.InitializeVars(out Document adoc, out Editor ed, out Database db);
  16.             ed.PointMonitor += Ed_PointMonitor;
  17.             ed.GetPoint("\nSelect point");
  18.             ed.PointMonitor -= Ed_PointMonitor;
  19.         }
  20.  
  21.         private void Ed_PointMonitor(object sender, PointMonitorEventArgs e)
  22.         {
  23.             if (e.Context.PointComputed)
  24.             {
  25.                 Point3d pt = e.Context.ComputedPoint;
  26.  
  27.                 double
  28.                     radius = Point3d.Origin.DistanceTo(pt),
  29.                     angle = Vector3d.XAxis.GetAngleTo(Point3d.Origin.GetVectorTo(pt), Vector3d.ZAxis);
  30.                 bool res = e.Context.DrawContext.Geometry.CircularArc
  31.                     (Point3d.Origin, radius, Vector3d.ZAxis, Vector3d.XAxis, angle, ArcType.ArcSimple);
  32.                 bool res1 = e.Context.DrawContext.Geometry.CircularArc
  33.                     (Point3d.Origin, radius, Vector3d.ZAxis, Vector3d.XAxis, angle, ArcType.ArcSector);
  34.                 bool res2 = e.Context.DrawContext.Geometry.CircularArc
  35.                     (Point3d.Origin, radius, Vector3d.ZAxis, Vector3d.XAxis, angle, ArcType.ArcChord);
  36.  
  37.                 using (Arc arc = new Arc(Point3d.Origin, Vector3d.ZAxis, radius, 0.0, angle))
  38.                 {
  39.                     bool res3 = e.Context.DrawContext.Geometry.Draw(arc);
  40.                 }
  41.             }
  42.         }
  43.     }
  44. }
  45.  
Почему-то метод отрисовки дуги в строках 30-31 не работает. Для сравнения - ниже (строки 32-35) отрисовка центрального угла и хорды - работают без проблем.
Попробовал создавать временный объект-дугу (строки 37-40). Работает как-то нестабильно. Ближе к границе экрана - отрисовывает, ближе к центру - не хочет.

Есть идеи, как это можно побороть?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
У меня строки 30-31 работают нормально (остальные отрисовки я закомментировал). Тут или аппаратное ускорение или значения переменных DRAGP1/DRAGP2 или баг в конкретной версии AutoCAD. Я проверял в 2019-ом со всеми обновлениями.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Вы знаете, в Civil 3D 2018 и 2019 тоже работает как надо без дополнительных манипуляций! А вот в 2017 версии - только с отключенным аппаратным ускорением! Получается, надо какое-то решение только для этой версии. Странно, кстати, что у Вас в 2017 работает без отключения ускорения. Видимо, имеет значение - чистый AutoCAD или Civil.

Отмечено как Решение Дмитрий Загорулькин 26-02-2019, 16:18:51

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
А вот в 2017 версии - только с отключенным аппаратным ускорением! Получается, надо какое-то решение только для этой версии.
Вот такой вот костыль получился :)
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.GraphicsInterface;
  6. using Autodesk.AutoCAD.Runtime;
  7.  
  8. namespace AcadTest
  9. {
  10.     public class TestEditorDraw
  11.     {
  12.         [CommandMethod("TestEditorDrawArc")]
  13.         public void Run()
  14.         {
  15.             Support.InitializeVars(out Document adoc, out Editor ed, out Database db);
  16.             ed.PointMonitor += Ed_PointMonitor;
  17.             ed.GetPoint("\nSelect point");
  18.             ed.PointMonitor -= Ed_PointMonitor;
  19.         }
  20.  
  21.         private void Ed_PointMonitor(object sender, PointMonitorEventArgs e)
  22.         {
  23.             if (e.Context.PointComputed)
  24.             {
  25.                 Point3d pt = e.Context.ComputedPoint;
  26.  
  27.                 double
  28.                     radius = Point3d.Origin.DistanceTo(pt),
  29.                     angle = Vector3d.XAxis.GetAngleTo(Point3d.Origin.GetVectorTo(pt), Vector3d.ZAxis);
  30.  
  31.                 Vector3d radHor = Vector3d.XAxis.MultiplyBy(radius);
  32.  
  33.                 Point3d
  34.                     start = Point3d.Origin + radHor,
  35.                     pointOnArc = Point3d.Origin + radHor.RotateBy(angle / 2.0, Vector3d.ZAxis),
  36.                     end = Point3d.Origin + radHor.RotateBy(angle, Vector3d.ZAxis);
  37.  
  38.                 DrawArc(e.Context.DrawContext.Geometry, start, pointOnArc, end);
  39.             }
  40.         }
  41.  
  42.         static void DrawArc(ViewportGeometry geometry, Point3d start, Point3d pointOnArc, Point3d end)
  43.         {
  44.             if (Application.Version.Major == 21)
  45.             {
  46.                 using (CircularArc3d arc = new CircularArc3d(start, pointOnArc, end))
  47.                 {
  48.                     double
  49.                         startParam = arc.GetParameterOf(start),
  50.                         endParam = arc.GetParameterOf(end),
  51.                         arcLength = arc.GetLength(startParam, endParam, Tolerance.Global.EqualPoint),
  52.                         delta = 0.3; // Шаг аппроксимации
  53.  
  54.                     Point3d prevPt = start;
  55.                     double
  56.                         tmpLength = 0.0,
  57.                         prevParam = startParam;
  58.  
  59.                     while ((tmpLength += delta) < arcLength)
  60.                     {
  61.                         double curParam = arc.GetParameterAtLength
  62.                             (prevParam, delta, true, Tolerance.Global.EqualPoint);
  63.                         Point3d curPt = arc.EvaluatePoint(curParam);
  64.                         geometry.WorldLine(prevPt, curPt);
  65.                         prevPt = curPt;
  66.                         prevParam = curParam;                      
  67.                     }
  68.  
  69.                     geometry.WorldLine(prevPt, end);
  70.                 }
  71.             }
  72.             else
  73.             {
  74.                 geometry.CircularArc(start, pointOnArc, end, ArcType.ArcSimple);
  75.             }
  76.         }
  77.     }
  78. }
  79.  

P.S. Александр Наумович, спасибо за проверки и подсказки!

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
А вот в 2017 версии - только с отключенным аппаратным ускорением! Получается, надо какое-то решение только для этой версии. Странно, кстати, что у Вас в 2017 работает без отключения ускорения.
Скорее зависит от видеокарты/драйвера видео и настроек аппаратного ускорения.  В 2017-ом с включенным вот этим флажком не рисует совсем:


При тестах он у меня был отключен. Ну и карта "не сертифицированная".  :)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
delta = 0.3; // Шаг аппроксимации
А вот это бы я подсчитывал в зависимости от масштаба изображения (Viewport.GetNumPixelsInUnitSquare)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
При тестах он у меня был отключен.
Ага, вот оно в чём дело! Значит, всё-таки, аппаратное ускорение играет роль!
Ну и карта "не сертифицированная".
Мы пробовали на сертифицированной NVidia Quadro - проблема всё равно есть.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
А вот это бы я подсчитывал в зависимости от масштаба изображения (Viewport.GetNumPixelsInUnitSquare)
В общем случае - да, надо бы. В нашем - такой точности достаточно во всех случаях. Поэтому, время на это тратить не хочется. Думаю, кому надо будет (если надо будет) - на основе этого примера допилят ;)

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
В нашем - такой точности достаточно во всех случаях.
Я как раз подумал, что это будет даже перебор точности. Если единицы - метры и это реальный чертеж, то расстояние между точками в 30 см на десятках и даже сотнях метров - это перебор.
P.S.: Для реальной ситуации деление дуги на 16 частей (ну в крайнем случае на 32) - это достаточная точность.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Да, пожалуй, Вы правы. Тогда, такое решение (с учётом того, что чем больше угловая длина дуги, тем больше сегментов нужно для более плавной отрисовки):
Код - C# [Выбрать]
  1. delta = Math.PI * arc.Radius / 64.0; // Шаг аппроксимации