Как определить направление вращения замкнутой полилинии?

Автор Тема: Как определить направление вращения замкнутой полилинии?  (Прочитано 8701 раз)

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

Оффлайн Александр РивилисАвтор темы

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

Оффлайн albyc

  • ADN OPEN
  • Сообщений: 3
  • Карма: 0
Здравствуйте. Прошу помочь переделать код определения вращения полилинии в код на python.

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Здравствуйте. Прошу помочь переделать код определения вращения полилинии в код на python.
О каком python идёт речь?  Если имеется в виду работа python с AutoCAD через COM/ActiveX, то это должен быть совсем другой код.
Этот код переделать нельзя.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн albyc

  • ADN OPEN
  • Сообщений: 3
  • Карма: 0
О каком python идёт речь?
python3
Если имеется в виду работа python с AutoCAD через COM/ActiveX
да, осущевствляю доступ к автокаду через библиотеку win32com.
Этот код переделать нельзя.
разжуйте пожалуйста логику работы скрипта.
входным объектом обязательно должна быть замкнутная полилиния?
я правильно понял, что требуется посчитать кол-во поворотов, вычислить направление последних, а затем сравнить их по модулю?

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
да, осущевствляю доступ к автокаду через библиотеку win32com.
Вот это самое существенное. Поэтому возможности очень ограниченные. Фактически с помощью можно получить координаты вершин (в Com/ActiveX метод Coordinate), и кривизну (bulge) в каждой из вершин (в Com/ActiveX метод GetBulge).
входным объектом обязательно должна быть замкнутная полилиния?
Для незамкнутой полилинии нет понятия по часовой или против часовой.
я правильно понял, что требуется посчитать кол-во поворотов, вычислить направление последних, а затем сравнить их по модулю?
Не количество поворотов, а сумму углов поворотов по модулю 2*PI. Причем угол поворота рассчитывается хитрым образом - в определённых случаях с плюсом, в определенных с минусом.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Еще один алгоритм, основанный на знаке площади (спасибо Gilles Chanteau ):
Код - C# [Выбрать]
  1.     public static class AlgebraicArea
  2.     {
  3.         public static double GetArea(Point2d pt1, Point2d pt2, Point2d pt3)
  4.         {
  5.             return (((pt2.X - pt1.X) * (pt3.Y - pt1.Y)) -
  6.                         ((pt3.X - pt1.X) * (pt2.Y - pt1.Y))) / 2.0;
  7.         }
  8.  
  9.         public static double GetArea(this CircularArc2d arc)
  10.         {
  11.             double rad = arc.Radius;
  12.             double ang = arc.IsClockWise ?
  13.                 arc.StartAngle - arc.EndAngle :
  14.                 arc.EndAngle - arc.StartAngle;
  15.             return rad * rad * (ang - Math.Sin(ang)) / 2.0;
  16.         }
  17.  
  18.         public static double GetArea(this Polyline pline)
  19.         {
  20.             CircularArc2d arc = new CircularArc2d();
  21.             double area = 0.0;
  22.             int last = pline.NumberOfVertices - 1;
  23.             Point2d p0 = pline.GetPoint2dAt(0);
  24.  
  25.             if (pline.GetBulgeAt(0) != 0.0)
  26.             {
  27.                 area += pline.GetArcSegment2dAt(0).GetArea();
  28.             }
  29.             for (int i = 1; i < last; i++)
  30.             {
  31.                 area += GetArea(p0, pline.GetPoint2dAt(i), pline.GetPoint2dAt(i + 1));
  32.                 if (pline.GetBulgeAt(i) != 0.0)
  33.                 {
  34.                     area += pline.GetArcSegment2dAt(i).GetArea(); ;
  35.                 }
  36.             }
  37.             if ((pline.GetBulgeAt(last) != 0.0) && pline.Closed)
  38.             {
  39.                 area += pline.GetArcSegment2dAt(last).GetArea();
  40.             }
  41.             return area;
  42.         }
  43.     }

Проверочный код:
Код - C# [Выбрать]
  1.         [CommandMethod("Test")]
  2.         public void ClockwisePolyline()
  3.         {
  4.             Document doc = AcAp.DocumentManager.MdiActiveDocument;
  5.             Database db = HostApplicationServices.WorkingDatabase;
  6.             Editor ed = doc.Editor;
  7.             using (Transaction tr = db.TransactionManager.StartTransaction())
  8.             {
  9.                 BlockTableRecord btr =
  10.                     (BlockTableRecord)db.CurrentSpaceId.GetObject(OpenMode.ForWrite);
  11.                 PromptEntityOptions peo = new PromptEntityOptions("\nSelect a polyline: ");
  12.                 peo.SetRejectMessage("Selected object is not a polyline.");
  13.                 peo.AddAllowedClass(typeof(Polyline), false);
  14.                 while (true)
  15.                 {
  16.                     PromptEntityResult per = ed.GetEntity(peo);
  17.                     if (per.Status != PromptStatus.OK) break; ;
  18.                     Polyline pline = (Polyline)per.ObjectId.GetObject(OpenMode.ForRead);
  19.                     double area = pline.GetArea();
  20.                     Application.ShowAlertDialog(
  21.                         string.Format("{0}\nArea = {1}", area < 0 ? "CW" : "CCW", area));
  22.                 }
  23.                 tr.Commit();
  24.             }
  25.         }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн albyc

  • ADN OPEN
  • Сообщений: 3
  • Карма: 0
кривизну (bulge)
у меня метод object.GetBulge возвращает 0.0 в любом случае не обращая внимания на направление.

На данный момент пробую использовать для 3х точек полилинии:
но не дошло какие точки необходимы: начальная средняя и последняя?
Код - Python [Выбрать]
  1. def get_area_3pts(pt1, pt2, pt3):
  2.     check = (((pt2[0] - pt1[0]) * (pt3[1] - pt1[1])) -
  3.              ((pt3[0] - pt1[0]) * (pt2[1] - pt1[1])))/2.0
  4.     return check
  5.  

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
у меня метод object.GetBulge возвращает 0.0 в любом случае не обращая внимания на направление.
У вас полилиния состоящия только из отрезков прямых? Если есть дуговые сегменты, то object.GetBulge возвращает отличное от 0.0 значение.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
На данный момент пробую использовать для 3х точек полилинии:
но не дошло какие точки необходимы: начальная средняя и последняя?
Это полная ерунда. Такой код может сработать только для полилинии-треугольника.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр РивилисАвтор темы

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Код - Visual Basic [Выбрать]
  1. ' polyArea - возвращает площадь полилинии состоящей только из
  2. ' прямых участков (т.е. не имеет дуг)
  3. ' Возвращаемое значение < 0 если полилиния по часовой стрелке и > 0
  4. ' если полилиния против часовой стрелки
  5. Function polyArea(arrPts() As Double) As Double
  6.  Dim i As Integer
  7.  Dim iL As Integer
  8.  Dim iH As Integer
  9.  Dim dblArea As Double
  10.  dblArea = 0.0
  11.  
  12.  iL = LBound(arrPts)
  13.  iH = UBound(arrPts)
  14.  For i = iL To iH - 2 Step 2
  15.    dblArea = dblArea + arrPts(i) * arrPts(i + 3) - arrPts(i + 1) * arrPts(i + 2)
  16.  Next i
  17.  dblArea = dblArea + arrPts(iH - 1) * arrPts(1) - arrPts(iH) * arrPts(0)
  18.  polyArea = dblArea / 2
  19. End Function
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение