Тема: Как найти угол отрезка полилинии?

Как найти угол отрезка полилинии?
Выбираю полилинию командой ThisDrawing.Utility.GetEntity obj, point, "Select edge:"
Далее требуется определить угол отрезка полилинии, который был указан.

Re: Как найти угол отрезка полилинии?

Нужно определить между какими вершинами полилинии находится данная точка, ну а там уже чистая математика. Я бы для такой задачи воспользовался лиспом, на котором в отличии от VBA без труда можно определить угол наклона любой кривой или ломаной в любой точке, включая кривые и дуговые сегменты. Например так:

(defun c:seang(/ uPnt sSet sCurve Dr)
  (vl-load-com)
  (if
    (and
    (setq uPnt(getpoint "\nSelect point at curve -> "))
    (setq sSet(ssget uPnt '((0 . "*LINE,ARC,ELLIPSE,CIRCLE")
                  (-4 . "<NOT")(0 . "MLINE")(-4 . "NOT>"))))
    (setq sCurve(vlax-ename->vla-object(ssname sSet 0)))
    (setq Dr(vlax-curve-getFirstDeriv sCurve
        (vlax-curve-getParamAtPoint sCurve uPnt)))
     ); end and
      (princ
    (strcat "\nAngle = "
        (angtos
          (-(/ pi 2)(atan(/(car dr)(cadr dr)))))"°"))
    ); end if
  (princ)
  ); end of c:seang

Re: Как найти угол отрезка полилинии?

Нужно определить между какими вершинами полилинии находится данная точка.

Т. е составить уравнения прямых проходящих через точки полилинии, проверить пренадлежность указанной точки соответствующей прямой и по координатам концов отрезка определить угол наклона.

Re: Как найти угол отрезка полилинии?

> {Smirnoff}
Ваш код срабатыват только на, прошу прощения, curve.
А вот как изящно можно решить эту задачу в VBA:
Поместите приведенный код в модуль ThisDrawind,запустите макрос Segment_Angle, и он начнет добросовестно показывать углы ВСЕХ сегментов выбранной полилинии в радианах, начиная с указанного.

Sub Segment_Angle()
    ThisDrawing.SendCommand " _explode "
End Sub
Private Sub AcadDocument_ObjectModified(ByVal Object As Object)
    If (TypeOf Object Is AcadLine) Then
        MsgBox (Object.Angle & " rad")
    End If
End Sub

Ну, а если серьезно, то в задании многовато неизвестных - с какой целью вам это надо, и следовательно, в каком контексте следует решать задачу?

Re: Как найти угол отрезка полилинии?

> LeonidSN
Мой код рабатет, на линии, любые сегменты полилиний, окружности, эллипсы, дуги и сплайны и вычисляет угол наклона в заданной точке. Возможно вы не включили привязки в т. ч. Nearest, о чем я не предупредил и не сделал в этой короткой демке.
Это вы считаете изяществом ? >

ThisDrawing.SendCommand " _explode "

Re: Как найти угол отрезка полилинии?

Да, согласен, для линии все очень просто. Но разблокировать полилинию не очень хочется.
А если через уравнения прямых - у меня точка, когда я указываю полилинию, может и не попасть на прямую?

Re: Как найти угол отрезка полилинии?

И метод на VBA перечисляет углы всех получившихся линий, а мне надо угол только того отрезка, который был указан.

Re: Как найти угол отрезка полилинии?

На самом деле так поступать можно. Однако не с помощью SendCommand а:
1. Использовать метод GetEntity для получения объекта полилинии и точки указания.
2. Создать копию полилинию с помощью метода Copy.
3. Взорвать копию объекта с помощью метода Explode при этом получив массив из объектов получившихся после расчленения.
4. Использовать метод SelectAtPoint для повтороного выбора именно примитива прямой.
5. Собственно измерить угол наклона сегмента.
6. Удалить все объекты получившиеся после "взрыва" методом Delete.
При всём при этом надо начиная с пункта 2. разблокировать слой (если заблокирован) на котором лежит расчленяемая полилиния, а в конце операции "Барбароса" воссановить его состояние.
Можно поступить и по другому. Вызвать простую ЛИСП-программу, которая сделает всё без этих лишних манипуляций и передать значение в среду VBA через пользовательский словарь или на худой случай переменную USERRXX.

Re: Как найти угол отрезка полилинии?

Спасибо всем за подсказку.
На данный момент реализовал через нахождение, принадлежит ли точка прямой.
Единственный минус: командой ThisDrawing.Utility.GetEntity трудно указать точку на прямой, поэтому приходиться делать поправку на погрешность.

Re: Как найти угол отрезка полилинии?

Alexshd пишет:

На данный момент реализовал через нахождение, принадлежит ли точка прямой.

И это правильно.

Единственный минус: командой ThisDrawing.Utility.GetEntity трудно указать точку на прямой, поэтому приходиться делать поправку на погрешность.

Да вроде GetEntity корректирует возвращаемую точку так чтобы она пренадлежала выббранному объекту. Во всяком аналогиченая лисповская функция ENTSEL поступает именно так. Однако погрешность всё равно учитывать надо поскольку производятся вычисления и погрешность накапливается сама собой.

Re: Как найти угол отрезка полилинии?

> {Smirnoff}
На самом деле пункт 2 вашего описания алгоритма лишний. Т. к. метод

 object.Explode

Реально не разбивает обььект , а лиш возврашхает массив с его(обььекта) составными частями

Re: Как найти угол отрезка полилинии?

Gogi пишет:

На самом деле пункт 2 вашего описания алгоритма лишний. Т. к. метод
object.Explode
Реально не разбивает объект , а лиш возвращает массив с его(объекта) составными частями

А если разок попробывать?

Sub plExplode()
Dim obj As AcadObject
Dim pt As Variant
Dim exArr As Variant
ThisDrawing.Utility.GetEntity obj, pt, "Разбей эту полилинию >"
exArr = obj.Explode
MsgBox "Получилось линий: " & UBound(exArr) - LBound(exArr) + 1
End Sub

Re: Как найти угол отрезка полилинии?

> {Smirnoff}
Вот и попробуите.  Полилиния  obj
вашего примера останется целая и не вредимая. Зато добавятся поверх нее ешхе и осколки.

Re: Как найти угол отрезка полилинии?

> Gogi
Да однако вы правы, я не замечал этого раньше. Это наверное потому что практически ничего не эксплодил, всегда "забираясь" внутрь объекта. Спасибо.

Re: Как найти угол отрезка полилинии?

> {Smirnoff}
Действительно, с привязкой nearest функция seang прекрасно работает. Я добавил в ее начало строчку -

(setvar "OSMODE" 512)

и при случае ею воспользуюсь. Спасибо.
Вероятно из практических соображений, в данном случае удобнее всего использовать AutoLISP, поскольку в нем представлен целый набор подходящих встроенных функций.
Однако задание было помещено в разделе VBA, что предполагает наличие молчаливого условия. И мне показалось интересным продемонстрировать характерное развитие ситуации при выполнении заказа, в данном случае - программы. Заказчик выдает задание, Исполнитель его выполняет. Когда Заказчик знакомится с результатами работы, то понимает, что чего-то не досказал и выдвигает дополнительные условия. Исполнитель переделывает работу, и цикл повторяется.
Итак, вот программка переработанная в соответствие с дополнительными условиями:

Sub Segment_Angle()
    Dim plineObj As AcadLWPolyline
    Dim PickedPoint As Variant
    ThisDrawing.Utility.GetEntity plineObj, PickedPoint, "Select segment of polyline:"
    Dim explodedObjects As Variant
    explodedObjects = plineObj.Explode
    Dim ln As AcadLine
    Dim i As Integer
    On Error Resume Next
    For i = 0 To UBound(explodedObjects)
        Set ln = explodedObjects(i)
        If (BelongingCheck(PickedPoint, ln)) Then
            MsgBox (ln.Angle & " rad")
            GoTo Label
        End If
    Next i
Label:
    For i = 0 To UBound(explodedObjects)
        explodedObjects(i).Delete
    Next
End Sub
Private Function BelongingCheck(PickedPoint As Variant, ln As AcadLine) As Boolean
'проверка на принадлежность PickedPoint  точки отрезку ln:
    BelongingCheck = False
    Dim a As Double
    Dim b As Double
     a = Abs(ln.Delta(0) / ln.Delta(1))
     b = Abs((ln.StartPoint(0) - PickedPoint(0)) / (ln.StartPoint(1) - PickedPoint(1)))
     a = Round(a)
     b = Round(b)
     If (a = b) Then
        BelongingCheck = True
     End If
End Function

Что же касается разговоров об изящном, то мне кажется, что вы слишком уж серьезно отнеслись к моему заявлению. Хотя, с другой стороны, почему бы и не воспользоваться самым коротким путем к цели...

Re: Как найти угол отрезка полилинии?

А позвольте усложнить вопрос.
Если выделяемый отрезок полилинии является дугой. Тут уже не обойтись только вычислением принадлежности точки прямой.

Re: Как найти угол отрезка полилинии?

Не позволю!
Это уже новая работа, которая должна выполняться за отдельную плату.
В задании было сказано:"Как найти угол отрезка полилинии?", а не - угол в точке

Re: Как найти угол отрезка полилинии?

> LeonidSN
Я бы всё таки воспользовался математикой и вычислил бы принадлежность точки отрезку с помощью параметрического уравнения прямой проходящей через две точки ограничив парметр условием 0<=p<=1, естественно с учётом допуска. К сожалению у меня неправильно копируется русский текст (имею ввиду пояснения к функции), но я думаю что аргументы функции понятны их названий. Единственное аргумент Segment если равен True то определяется принадлежность точки отрезку, если False то прямой.

Public Function Asmi_Is_Point_On_Line( _
ByVal X1 As Double, ByVal Y1 As Double, _
ByVal X2 As Double, ByVal Y2 As Double, _
ByVal Xp As Double, ByVal Yp As Double, _
Precision As Double, Segment As Boolean) As Boolean
Dim Tx, Ty As Double
If X2 <> X1 Then
Tx = (Xp - X1) / (X2 - X1)
End If
If Y2 <> Y1 Then
Ty = (Yp - Y1) / (Y2 - Y1)
End If
If X1 = X2 And _
(X1 - Precision <= Xp) And (Xp <= X1 + Precision) Then
Tx = Ty
End If
If Y1 = Y2 And _
(Y1 - Precision <= Yp) And (Yp <= Y1 + Precision) Then
Ty = Tx
End If
If (Ty - Precision <= Tx) And (Tx <= Ty + Precision) _
And (0 - Precision <= Tx) And (Tx <= 1 + Precision) Then
    Asmi_Is_Point_On_Line = True
ElseIf (Ty - Precision <= Tx) And (Tx <= Ty + Precision) _
And Segment = False Then
    Asmi_Is_Point_On_Line = True
Else
    Asmi_Is_Point_On_Line = False
End If
End Function

Вот кстати ещё SEANG дополненый включением-отключением привязки и обработчиком ошибок:

(defun c:seang(/ *error* oldOsm uPnt sSet sCurve Dr)
  (vl-load-com)
  (defun *error*(msg)
    (setvar "OSMODE" oldOsm)
    (princ)
    ); end of *error*
  (setq oldOsm(getvar "OSMODE"))
  (setvar "OSMODE" 512)
  (if
    (and
    (setq uPnt(getpoint "\nSelect point at curve -> "))
    (setq sSet(ssget uPnt '((0 . "*LINE,ARC,ELLIPSE,CIRCLE")
                  (-4 . "<NOT")(0 . "MLINE")(-4 . "NOT>"))))
    (setq sCurve(vlax-ename->vla-object(ssname sSet 0)))
    (setq Dr(vlax-curve-getFirstDeriv sCurve
        (vlax-curve-getParamAtPoint sCurve uPnt)))
     ); end and
      (princ
    (strcat "\nAngle = "
        (angtos
          (-(/ pi 2)(atan(/(car dr)(cadr dr)))))"°"))
    ); end if
  (setvar "OSMODE" oldOsm)
  (princ)
  ); end of c:seang

Что же касается разговоров об изящном, то мне кажется, что вы слишком уж серьезно отнеслись к моему заявлению.

Я тоже потом подумал что вы это не совсем серьёзно. Да и где время найти чтобы совсем серьёзно:(

Re: Как найти угол отрезка полилинии?

> Alexshd
Вначале хочу сказать что был неправ когда сказал что при применении метода GetEntity координаты точки корректируются так чтобы она была на выбираемом объекте. Так происходит в ЛИСПе, при применении родственной методу GetEntity функции ENTSEL, а в VBA оказывается не так :( В следствии этого приходится применять достаточно большой допуск. Думаю что для большей точности можно воспользоваться методом GetPoint с включенной объектной привязкой, а после выбора точки воспользоваться методом SelectAtPoint для выбора полилинии. Как это выглядит можете посмотреть запустив SEANG (см. в предыдущем постинге), там выбор происходит аналогично- точка, потом примитив проходящий через точку.

А позвольте усложнить вопрос.
Если выделяемый отрезок полилинии является дугой. Тут уже не обойтись только вычислением принадлежности точки прямой.

Ну что тут сделаешь? Либо опять включать математику (исходных в свойствах дуги достаточно). Или воспользоваться ЛИСП-функциями с префиксом vlax-curve- через которые можно получить полный спектр информации о любых параметрах кривых в любой точке. Т. е. то о чём я с самого начала говорил.
И вообще какой угол у дуги вы хотите узнать? Угол наклона в выбранной точке (вычисляется через первую производную в данной точке) или угол наклона хорды соединяющей концы дуги или что либо другое?

Re: Как найти угол отрезка полилинии?

> {Smirnoff}
Знаете, по поводу наших с вами выступлений на этой скромной ветке возникает целый ряд соображений, но я не уверен, что... мой настрой разделит большинство.
Однако, попробуем.
Форум есть место обсуждения проблем, а не обязательно вечер вопросов и ответов. Есть, например, общая проблема - взаимоотношения Заказчика и Исполнителя, проблема взаимной ответственности и компетентности. От ее нерешенности страдают многие. Однако, мы предпочитаем ее не замечать!
Конечно, для меня и, возможно, для вас проще всего написать код и таким образом отреагировать на вызовы внешнего мира. Но проблема же не исчезает, Заказчик продолжает считать себя вправе ломать без конца задание на проектирование и относиться наплевательски к работе Исполнителя. Это МЫ позволяем ему так вести себя. Так может быть следует что-то предпринять, чтобы изменить ситуацию? Для начала - обратить на нее внимание.
Возможно, мы недостаточно внимательны друг к другу - вы пишите "> LeonidSN (2006-02-08 23:06:08)
Я бы всё таки воспользовался математикой и вычислил бы принадлежность точки отрезку "
- но это именно то, что сделано в моем предыдущем посте.
Полагаю, что мы все склонны зацикливаться на собственном коде - отсюда, проблемы вызванные ограниченностью. Например, проблема точности вычислений геометрических характеристик. Я с этим сталкивался и убежден, что здесь надо привлекать специалистов по вычислительной математике, но мы продолжаем вариться в собственном соку и кустарничать.
Одним словом, я - за плодотворное обсуждение, а результат придет.

Re: Как найти угол отрезка полилинии?

LeonidSN пишет:

Знаете, по поводу наших с вами выступлений на этой скромной ветке возникает целый ряд соображений, но я не уверен, что... мой настрой разделит большинство.
Однако, попробуем.
Форум есть место обсуждения проблем, а не обязательно вечер вопросов и ответов. Есть, например, общая проблема — взаимоотношения Заказчика и Исполнителя, проблема взаимной ответственности и компетентности. От ее нерешенности страдают многие. Однако, мы предпочитаем ее не замечать!
Конечно, для меня и, возможно, для вас проще всего написать код и таким образом отреагировать на вызовы внешнего мира. Но проблема же не исчезает, Заказчик продолжает считать себя вправе ломать без конца задание на проектирование и относиться наплевательски к работе Исполнителя. Это МЫ позволяем ему так вести себя. Так может быть следует что-то предпринять, чтобы изменить ситуацию? Для начала — обратить на нее внимание.

Ну это очень комплексная проблемма. Тут и психология и юридические проблеммы и денежные отношения. И такое положение будет в той или иной мере будет существовать всегда, вопрос только в том насколько это затрагивает вас лично. Это явно не тема ветки Программирвание VBA, но если есть желание куча таких тем "за жизнь" поднималось на www.dwg.ru где я являюсь скромным модератором. Думаю вы и сейчас можете открыть там подобную ветку (или продолжить одну из старых) и желающих обсудить будет много. Но увы не я...

Возможно, мы недостаточно внимательны друг к другу — вы пишите "> LeonidSN (2006-02-08 23:06:08)
Я бы всё таки воспользовался математикой и вычислил бы принадлежность точки отрезку "
- но это именно то, что сделано в моем предыдущем посте.

Я внимательно посмотрел ваш код и запустил его. Однако я имел ввиду другое - то что возможно вычислить принадлежность точки соответствующему сегменту полилинии не расчленяя её. А просто обработав массив точек из свойства Coordinates вышеприведённой функцией.

Я с этим сталкивался и убежден, что здесь надо привлекать специалистов по вычислительной математике, но мы продолжаем вариться в собственном соку и кустарничать.

Это конечно здорово. Однако кто будет платить этим специалистам? Надо чётко разделять собственное кустарничество (в своё удовольствие) и работу профи которые могут и готовы платить за необходимым специалистам, покупать библиотеки и т. д. Я к примеру никакой не программист, а инженер, пишу в собственное удовольствие для оптимизации работы и для друзей.
Круто вы с Alexshd прямо как с Заказчиком...

> Alexshd
Можете обращатся, с дуговым сегментом на VBA не помогу, а вот как запустить соответствующий ЛИСП и передать данные обратно в VBA могу посодействовать.

Re: Как найти угол отрезка полилинии?

Можете обращатся, с дуговым сегментом на VBA не помогу, а вот как запустить соответствующий ЛИСП и передать данные обратно в VBA могу посодействовать.

Спасибо большое. Но на данный момент мне хочется реализовать задачу своими силами на VBA.
Я остановился на математическом способе. Дугу буду вычислять через GetBulge.
-----
Мне очень помогли Ваши советы.
И в свете последних обсуждений "клиент-исполнитель" я не прошу выкладывать горы кода. Мне интересно знать, какими методами я могу решить задачу, какими инструментами VBA позволит мне это сделать.

Re: Как найти угол отрезка полилинии?

> Alexshd
... в свете последних обсуждений "клиент-исполнитель"...
Я воспринял ваши посты как участие в этой небольшой игре. Так что спасибо и Вам, что подыграли.

Re: Как найти угол отрезка полилинии?

И тему мы, конечно, закрыли, и мои телодвижения выглядят несколько суетливо, но... не надуманная это проблема, вот наткнулся на солидарные настроения:
https://www.caduser.ru/forum/topic15897.html

Re: Как найти угол отрезка полилинии?

Посмотрите тут. https://www.caduser.ru/forum/topic22264.html
Это чтобы понять как можно "красиво" и "легко" работать с точкой на полилинии. задача решённая там сложнее вашей. Упростить предлагаю самостоятельно.