выбор сегмента полилиниии

Автор Тема: выбор сегмента полилиниии  (Прочитано 28940 раз)

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

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #45 : 16-10-2018, 13:32:04 »
Вот так вот? Готовый код?(
Вечером уже потестирую
Спасибо

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: выбор сегмента полилиниии
« Ответ #46 : 16-10-2018, 13:40:46 »
Готовый код?(
Ну как минимум будет возможность изучить, разобраться в логике работы, протестировать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #47 : 16-10-2018, 13:45:08 »
Да с параметром хорошо получилось.
Моя логика хотя бы была верна в следующем:
Чтоб получить точку в ECS:
Point3d ptEcs = ptWcs.TransformBy(pline.Ecs);
И эту точку уже передавать в метод onsegmentat? Точнее ее х и у

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: выбор сегмента полилиниии
« Ответ #48 : 16-10-2018, 13:54:25 »
Моя логика хотя бы была верна в следующем:
Чтоб получить точку в ECS:
Point3d ptEcs = ptWcs.TransformBy(pline.Ecs);
И эту точку уже передавать в метод onsegmentat? Точнее ее х и у
Всё в точности до наоборот. Читаем документацию. pline.Ecs вернёт матрицу преобразования из ECS в WCS. Т.е. тебе нужна обратная матрица: pline.Ecs.Invert(). Ну и кроме того тебе понадобится еще одно преобразование - UCS в WCS, так как точку ты получаешь от пользователя в UCS. И еще передаваемая точка в метод onsegmentat должна быть в точности на полилинии, а Editor.GetEntity возвращает точку не на полилинии, а рядом в пределах размера pickbox. Поэтому в моём коде и используется нахождение точки на полилинии, ближайшей к указанной (метод GetClosestPointTo).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #49 : 16-10-2018, 14:26:51 »
Да я так и сделал. Упустил лишь момент получения обратной матрицы
Спасибо

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #50 : 16-10-2018, 18:37:45 »
все таки не всегда корректно работает
покрутил начало координат порисовал в разных плоскостях эти полилинии. и в какой то момент он не понимает что где

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: выбор сегмента полилиниии
« Ответ #51 : 16-10-2018, 19:29:06 »
все таки не всегда корректно работает
покрутил начало координат порисовал в разных плоскостях эти полилинии. и в какой то момент он не понимает что где
Чей вариант? Если мой - выкладывай чертеж в котором появляется ошибка. А еще лучше еще и добавь видео (как это делать - у меня в подписи).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #52 : 16-10-2018, 19:47:45 »

кажется получилось

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #53 : 16-10-2018, 19:49:14 »
вот код
Код - C# [Выбрать]
  1. public void Width()
  2.         {
  3.             Document doc = App.DocumentManager.MdiActiveDocument;
  4.             Database db = doc.Database;
  5.             Editor ed = doc.Editor;
  6.            
  7.             PromptEntityOptions peo = new PromptEntityOptions("\nВыберите сегменты полилинии");
  8.             peo.SetRejectMessage("\nЭто не полилиния!");
  9.             peo.AddAllowedClass(typeof(Polyline), true);
  10.  
  11.             PromptDoubleOptions pdo = new PromptDoubleOptions("\nШирина сегмнта полилинии");
  12.             pdo.DefaultValue = def;
  13.             PromptDoubleResult res = ed.GetDouble(pdo);
  14.  
  15.             double width = res.Value;
  16.             def = res.Value;
  17.            
  18.             while (true)
  19.             {
  20.                 PromptEntityResult sel = ed.GetEntity(peo);
  21.                 if (sel.Status == PromptStatus.OK)
  22.                 {
  23.                     using (Transaction tr = doc.TransactionManager.StartTransaction())
  24.                     {
  25.                         if (tr.GetObject(sel.ObjectId, OpenMode.ForWrite) is Polyline pl)
  26.                         {
  27.                             Matrix3d u2w = ed.CurrentUserCoordinateSystem;
  28.                             Vector3d viewDir = ((Point3d)(App.GetSystemVariable("VIEWDIR"))).TransformBy(u2w).GetAsVector().Negate();
  29.                             Point3d pW = pl.GetClosestPointTo(sel.PickedPoint.TransformBy(u2w), viewDir, false);
  30.  
  31.                             int n = (int)pl.GetParameterAtPoint(pW);
  32.  
  33.                             if (pl.GetStartWidthAt(n) != width)
  34.                             {
  35.                                 pl.SetStartWidthAt(n, width);
  36.                                 pl.SetEndWidthAt(n, width);
  37.                             }
  38.                             else
  39.                             {
  40.                                 pl.SetStartWidthAt(n, 0);
  41.                                 pl.SetEndWidthAt(n, 0);
  42.                             }
  43.                         }
  44.                         tr.Commit();
  45.                     }
  46.                 }
  47.                 else break;
  48.             }
  49.         }

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: выбор сегмента полилиниии
« Ответ #54 : 16-10-2018, 19:50:45 »
simson43,
Где чертеж?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #55 : 16-10-2018, 19:52:25 »
еще заодно спрошу.
я сначала транзакцию сделал за циклом. показалось так разумнее. но тогда при выборе сегмента он не сразу меняет ширину а по завершению метода что логично.
добавил в конце цикла regen. меняться конечно ширина стала но на больших чертежах это долго.
убрал реген засунул транзакцию в тело цикла. т е она создается каждую итерацию теперь. зато ширина в реальном времени меняется. и на больших чертежах не отнимает много времени.
это рационально?

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #56 : 16-10-2018, 19:53:16 »
так вот он

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: выбор сегмента полилиниии
« Ответ #57 : 16-10-2018, 20:55:11 »
это рационально?
Это нормально для данного случая.
все таки не всегда корректно работает
Ну вот ты и нарвался на баг в AutoCAD .NET API, с чем тебя и поздравляю. Нужно будет отправить в ADN DevHelp.
В случае если сегмент полилинии имеет ширину отличную от нуля метод public virtual Point3d GetClosestPointTo( Point3d givenPoint,  Vector3d direction, bool extend) работает неправильно, т.е. далеко не всегда правильно находит ближайшую точку. Вместо этого метода применим public virtual Point3d GetClosestPointTo( Point3d givenPoint,  bool extend);
У меня в твоём случае всё нормально работает. Вот код для проверки:
Код - C# [Выбрать]
  1. // (C) Copyright 2018 by  
  2. //
  3. using System;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.AutoCAD.ApplicationServices;
  6. using Autodesk.AutoCAD.DatabaseServices;
  7. using Autodesk.AutoCAD.Geometry;
  8. using Autodesk.AutoCAD.EditorInput;
  9. using App = Autodesk.AutoCAD.ApplicationServices.Application;
  10.  
  11. #pragma warning disable 0618
  12.  
  13. // This line is not mandatory, but improves loading performances
  14. [assembly: CommandClass(typeof(ChangeSegmentWidth.MyCommands))]
  15.  
  16. namespace ChangeSegmentWidth
  17. {
  18.  
  19.   public class MyCommands
  20.   {
  21.     static double def = 0.0;
  22.     [CommandMethod("ChgWidth")]
  23.     public void Width()
  24.     {
  25.       Document doc = App.DocumentManager.MdiActiveDocument;
  26.       Database db = doc.Database;
  27.       Editor ed = doc.Editor;
  28.  
  29.       PromptEntityOptions peo = new PromptEntityOptions("\nВыберите сегменты полилинии");
  30.       peo.SetRejectMessage("\nЭто не полилиния!");
  31.       peo.AddAllowedClass(typeof(Polyline), true);
  32.  
  33.       PromptDoubleOptions pdo = new PromptDoubleOptions("\nШирина сегмента полилинии");
  34.       pdo.DefaultValue = def;
  35.       PromptDoubleResult res = ed.GetDouble(pdo);
  36.  
  37.       double width = res.Value;
  38.       def = res.Value;
  39.  
  40.       while (true)
  41.       {
  42.         PromptEntityResult sel = ed.GetEntity(peo);
  43.         if (sel.Status == PromptStatus.OK)
  44.         {
  45.           using (Polyline pl = sel.ObjectId.Open(OpenMode.ForRead) as Polyline)
  46.           {
  47.             Matrix3d u2w = ed.CurrentUserCoordinateSystem;
  48.             Vector3d viewDir = ((Point3d)(App.GetSystemVariable("VIEWDIR")))
  49.               .TransformBy(u2w).GetAsVector().Negate().GetNormal();
  50.             // Какой-то баг у следующего метода
  51.             // Point3d pW = pl.GetClosestPointTo(sel.PickedPoint.TransformBy(u2w), viewDir, false);
  52.             Point3d pW = pl.GetClosestPointTo(sel.PickedPoint.TransformBy(u2w), false);
  53.             int n = (int)(pl.GetParameterAtPoint(pW) + 1e-10);
  54.  
  55.             try
  56.             {
  57.               pl.UpgradeOpen();
  58.               if (pl.GetStartWidthAt(n) > 1e-10)
  59.               {
  60.                 pl.SetStartWidthAt(n, 0.0);
  61.                 pl.SetEndWidthAt(n, 0.0);
  62.               }
  63.               else
  64.               {
  65.                 pl.SetStartWidthAt(n, width);
  66.                 pl.SetEndWidthAt(n, width);
  67.               }
  68.             }
  69.             catch { }
  70.           }
  71.         }
  72.         else break;
  73.       }
  74.     }
  75.   }
  76. }

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

Оффлайн simson43Автор темы

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: выбор сегмента полилиниии
« Ответ #58 : 16-10-2018, 21:03:22 »
баг это же хорошо. теперь о нем узнают)
Кстати, проверять на равенство плавающие числа (double) не следует.
это вы к тому что машинный ноль не всегда 0?

а про viewDir: я думал вы использовали именно этот метод чтоб он корректно работал при различно повернутых UCS? или как?

pl.SetStartWidthAt(n, 0.0);
это принципиально или просто для наглядности?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: выбор сегмента полилиниии
« Ответ #59 : 16-10-2018, 21:06:59 »
это вы к тому что машинный ноль не всегда 0?
Ты сравниваешь на равенство ширину сегмента полилинии и width на равенство. Так делать не следует.
а про viewDir: я думал вы использовали именно этот метод чтоб он корректно работал при различно повернутых UCS? или как?
Нет. Не путай ПСК и направление взгляда - это разные вещи.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение