Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Александр Пекшев aka Modis от 23-11-2015, 16:56:51

Название: Сегмент полилинии по точке
Отправлено: Александр Пекшев aka Modis от 23-11-2015, 16:56:51
Всем привет. Задача вроде тривиальная, но не тут-то было ))
В общем - хочу одним выбором объединить два действия - выбрать полилинию и выбрать сегмент полилинии.
Мои предположения: используем PromptEntityResult и получаем выбранный примитив (полилинию) и точку PickedPoint. По точке определяем сегмент.
Т.к. метода получить сегмент по точке нет, то делаем итерацию по вершинам, получаем сегмент в вершине, проверяем его тип (в моем случае нужна Дуга) и проверяем, что PickedPoint принадлежит сегменту. Ну или рядом. У Kean Walmsley нашел похожую тему и попытался ее "прикрутить" к своим нуждам. Прикладываю один из вариантов моих попыток:
Код - C# [Выбрать]
  1. try
  2. {
  3.     var doc = AcApp.DocumentManager.MdiActiveDocument;
  4.     var db = doc.Database;
  5.     var ed = doc.Editor;
  6.     while (true)
  7.     {
  8.  
  9.  
  10.         var peo = new PromptEntityOptions("\nВыберите дуговой сегмент полилинии: ")
  11.         {
  12.             AllowNone = false,
  13.             AllowObjectOnLockedLayer = true
  14.         };
  15.         peo.SetRejectMessage("\nНеверный выбор");
  16.         peo.AddAllowedClass(typeof(Polyline), true);
  17.  
  18.         var per = ed.GetEntity(peo);
  19.         if (per.Status != PromptStatus.OK) return;
  20.         var plineId = per.ObjectId;
  21.         var pickedPt = per.PickedPoint;
  22.  
  23.         using (doc.LockDocument())
  24.         {
  25.             using (var tr = db.TransactionManager.StartTransaction())
  26.             {
  27.                 var dbObj = tr.GetObject(plineId, OpenMode.ForRead);
  28.  
  29.                 if (dbObj is Polyline)
  30.                 {
  31.                     var pline = dbObj as Polyline;
  32.                     for (var i = 0; i < pline.NumberOfVertices; i++)
  33.                     {
  34.                         var segType = pline.GetSegmentType(i);
  35.                         if (segType == SegmentType.Arc)
  36.                         {
  37.                             Curve3d segment = pline.GetArcSegmentAt(i);
  38.                             var p = segment.GetClosestPointTo(pickedPt).Point;
  39.  
  40.                             if (segment.IsOn(p))
  41.                             {
  42.                                 pline.UpgradeOpen();
  43.                                 //.......остальной неважный код
  44.                                 break;
  45.                             }
  46.                         }
  47.                     }
  48.                 }
  49.                 tr.Commit();
  50.             }
  51.         }
  52.     }
  53. }
  54. catch (System.Exception exception)
  55. {
  56.     MpExWin.Show(exception);
  57. }
Логично, что код должен работать, но он не работает. Я пробовал различные вариации, в том числе из Tolerance.Global.EqualPoint. Но либо код вообще не работает, либо работает когда курсор в момент выбора находится на соседнем сегменте
Название: Re: Сегмент полилинии по точке
Отправлено: bargool от 23-11-2015, 17:03:16
А PromptNestedEntityResult не поможет?
Там у него есть вроде как есть метод GetContainers(), который
Цитировать
Returns an array of object IDs representing the containers of this nested entity
Это так, в порядке быстрого бреда. Правда, это не даст сегмент полилинии, но даст дугу, его составляющую
Название: Re: Сегмент полилинии по точке
Отправлено: Александр Пекшев aka Modis от 23-11-2015, 17:15:21
Там у него есть вроде как есть метод GetContainers()
Попробовал - при выборе полилинии GetContainers() всегда возвращает пустой список
Название: Re: Сегмент полилинии по точке
Отправлено: bargool от 23-11-2015, 17:18:50
Зато можно взять концевые точки полученного элемента, и найти их среди вершин полилинии
Название: Re: Сегмент полилинии по точке
Отправлено: Александр Ривилис от 23-11-2015, 17:23:22
Находишь ближайшую точку на полилинии. Находишь параметр в этой точке. Находишь по параметру вершину.
Название: Re: Сегмент полилинии по точке
Отправлено: Александр Пекшев aka Modis от 23-11-2015, 17:35:36
Александр Ривилис, спасибо! Это оно
Как обычно бывает - нужно взглянуть на проблему с другой стороны =)
Название: Re: Сегмент полилинии по точке
Отправлено: RevitTormentor от 02-04-2019, 08:20:47
Находишь ближайшую точку на полилинии. Находишь параметр в этой точке. Находишь по параметру вершину.

Может это отсюда же.
А как найти ближайшую точку на полилинии в месте выбора полилинии?

(https://i.postimg.cc/vgyMT4Dk/11111111.png) (https://postimg.cc/vgyMT4Dk)
Название: Re: Сегмент полилинии по точке
Отправлено: Александр Ривилис от 02-04-2019, 08:58:50
А как найти ближайшую точку на полилинии в месте выбора полилинии?
Воспользуйся методом Curve.GetClosestPointTo