не получается извлечь площадь штриховки

Автор Тема: не получается извлечь площадь штриховки  (Прочитано 18794 раз)

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

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

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Александр Ривилис,
да, действительно, не заметил..

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

понял! воспользуюсь пока этим кодом.. спасибо! нечто похожее у меня есть для запоминания координат контура..встрою частично туда..огромное спасибо!

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
понял! воспользуюсь пока этим кодом.. спасибо!
Код не отлаживал. Я взял его из GeomProps и перевёл с ObjectARX (C++) на AutoCAD .NET API (C#). На всякий случай исходник:

Код - C++ [Выбрать]
  1. double GetHatchArea(AcDbHatch *pHatch)
  2. {
  3.   double area = 0;
  4.   int nLoop = pHatch->numLoops();
  5.   Adesk::Int32 loopType;
  6.   for (int i = 0; i < nLoop; i++) {
  7.     double looparea = 0;
  8.     if ((loopType = pHatch->loopTypeAt(i)) & AcDbHatch::kPolyline) {
  9.       AcGePoint2dArray  vertices;
  10.       AcGeDoubleArray   bulges;
  11.       if (pHatch->getLoopAt(i, loopType, vertices, bulges) == Acad::eOk) {
  12.         AcDbPolyline *pPoly = new AcDbPolyline(vertices.length());
  13.         for (int j = 0; j < vertices.length(); j++) {
  14.           pPoly->addVertexAt(j, vertices[j], (bulges.length() < vertices.length()) ? 0.0 : bulges[j]);
  15.         }
  16.         pPoly->setClosed(!(loopType & AcDbHatch::kNotClosed));
  17.         pPoly->getArea(looparea);
  18.         if (loopType & AcDbHatch::kExternal) area += fabs(looparea); else area -= fabs(looparea);
  19.         delete pPoly;
  20.       }
  21.     }
  22.     else {
  23.       AcGeVoidPointerArray edgePtrs;
  24.       AcGeIntArray edgeTypes;
  25.       pHatch->getLoopAt(i, loopType, edgePtrs, edgeTypes);
  26.       AcGeCompositeCurve2d compCurve(edgePtrs);
  27.       AcGeInterval interval;  compCurve.getInterval(interval);
  28.       double pmin, pmax; interval.getBounds(pmin, pmax);
  29.       if (fabs(pmax - pmin) > 1e-6) {
  30.         if (compCurve.area(interval.lowerBound(), interval.upperBound(), looparea)) {
  31.           if (loopType & AcDbHatch::kExternal) area += fabs(looparea); else area -= fabs(looparea);
  32.         }
  33.         else {
  34.           AcGePoint2dArray pts; AcGeDoubleArray pars;
  35.           AcGePoint2d pmin, pmax;
  36.           AcGeBoundBlock2d blk2d = compCurve.boundBlock(interval);
  37.           blk2d.getMinMaxPoints(pmin, pmax);
  38.           double diag = pmin.distanceTo(pmax);
  39.           compCurve.getSamplePoints(interval.lowerBound(), interval.upperBound(), 1e-6 * max(1.0, diag), pts, pars);
  40.           int np = pts.length();
  41.           for (int i = 0; i < np; i++) {
  42.             looparea += 0.5 * pts[i][X] * (pts[(i + 1) % np][Y] - pts[(i + np - 1) % np][Y]);
  43.           }
  44.           if (loopType & AcDbHatch::kExternal) area += fabs(looparea); else area -= fabs(looparea);
  45.         }
  46.       }
  47.     }
  48.   }
  49.   return fabs(area);
  50. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Александр Ривилис,
большое спасибо! а по поводу этого есть какие-нибудь версии у вас?
Цитировать
для меня остается загадкой, почему после любых манипуляций с контуром (даже которые ничего не меняют) площадь начинает вычисляться?..и каким образом можно программно их сымитировать? я уже кучу методов hatch перебрал..

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

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

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

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Александр Ривилис, тоже покопаюсь

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Во вложении файлик, код из http://adn-cis.org/forum/index.php?topic=8128.msg28881#msg28881
вернет для штриховки площадь равную 0
Если удалить самопересечение во внутреннем углу, то все считается нормально

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Во вложении файлик, код из http://adn-cis.org/forum/index.php?topic=8128.msg28881#msg28881
вернет для штриховки площадь равную 0
А GeomProps обрабатывает:



Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
И не сомневаюсь, что обрабатывает, однако .Net код нет, а очень хотелось бы.
Причина, я так понимаю в 60 строке и в том, что hatchLoop.Polyline == null
Как обойти и все таки получить площадь?

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

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

Отмечено как Решение Александр Ривилис 14-11-2017, 18:51:31

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Решил сам переделать мой код из C++ в C#. Как всегда оказалось, что кое что в AutoCAD .NET API не работает из того, что работает в ObjectARX. В частности не срабатывает метод Curve2d.GetSamplePoints(double, double, double). Так что пришлось его заменить. В результате код выглядит так:
Код - 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.Runtime;
  6. using System;
  7.  
  8. namespace electricalPlugin
  9. {
  10.   public class test : IExtensionApplication
  11.   {
  12.     [CommandMethod("test")]
  13.     public void Test()
  14.     {
  15.       Document doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
  16.       if (doc == null) return;
  17.       Database db = doc.Database;
  18.       Editor ed = doc.Editor;
  19.  
  20.       TypedValue[] tv = new TypedValue[1];
  21.       tv.SetValue(new TypedValue((int)DxfCode.Start, "HATCH"), 0);
  22.       SelectionFilter sf = new SelectionFilter(tv);
  23.  
  24.       PromptSelectionResult psr = ed.GetSelection(sf);
  25.       if (psr.Status != PromptStatus.OK) return;
  26.  
  27.       using (Transaction tr = db.TransactionManager.StartTransaction())
  28.       {
  29.         foreach (ObjectId id in psr.Value.GetObjectIds())
  30.         {
  31.           if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Hatch))))
  32.           {
  33.             Hatch ent = tr.GetObject(id, OpenMode.ForRead) as Hatch;
  34.             double area = GetHatchArea(ent);
  35.             ed.WriteMessage("\nArea[{0}]={1}",id,area);
  36.           }
  37.         }
  38.         tr.Commit();
  39.       }
  40.     }
  41.  
  42.     double GetHatchArea(Hatch pHatch)
  43.     {
  44.       double area = 0;
  45.       try
  46.       {
  47.         area = pHatch.Area;
  48.       } catch
  49.       {
  50.         int nLoop = pHatch.NumberOfLoops;
  51.         int loopType;
  52.         for (int i = 0; i < nLoop; i++)
  53.         {
  54.           double looparea = 0;
  55.           loopType = (int)pHatch.LoopTypeAt(i);
  56.           if ((loopType & (int)HatchLoopTypes.Polyline) > 0)
  57.           {
  58.             HatchLoop hatchLoop = pHatch.GetLoopAt(i);
  59.             BulgeVertexCollection bulgeVertex = hatchLoop.Polyline;
  60.             using (Polyline pPoly = new Polyline(bulgeVertex.Count))
  61.             {
  62.               for (int j = 0; j < bulgeVertex.Count; j++)
  63.               {
  64.                 pPoly.AddVertexAt(j, bulgeVertex[j].Vertex, bulgeVertex[j].Bulge, 0, 0);
  65.               }
  66.               pPoly.Closed = (loopType & (int)HatchLoopTypes.NotClosed) == 0;
  67.               looparea = pPoly.Area;
  68.               if ((loopType & (int)HatchLoopTypes.External) > 0)
  69.                 area += Math.Abs(looparea);
  70.               else
  71.                 area -= Math.Abs(looparea);
  72.             }
  73.           } else
  74.           {
  75.             HatchLoop hatchLoop = pHatch.GetLoopAt(i);
  76.             Curve2d[] cur2ds = new Curve2d[hatchLoop.Curves.Count];
  77.             hatchLoop.Curves.CopyTo(cur2ds, 0);
  78.             using (CompositeCurve2d compCurve = new CompositeCurve2d(cur2ds))
  79.             {
  80.               Interval interval = compCurve.GetInterval();
  81.               double dMin = interval.GetBounds()[0], dMax = interval.GetBounds()[1];
  82.               if (Math.Abs(dMax - dMin) > 1e-6)
  83.               {
  84.                 try
  85.                 {
  86.                   looparea = compCurve.GetArea(dMin, dMax);
  87.                   if ((loopType & (int)HatchLoopTypes.External) > 0)
  88.                     area += Math.Abs(looparea);
  89.                   else
  90.                     area -= Math.Abs(looparea);
  91.                 }
  92.                 catch
  93.                 {
  94.                   // Разбиваем кривую на 1000000 точек. Надеюсь, что такой точности
  95.                   // будет достаточно.
  96.                   Point2d[] pts = compCurve.GetSamplePoints((int)1e+6);
  97.                   int np = pts.Length;
  98.                   for (int j = 0; j < np; j++)
  99.                   {
  100.                     looparea += 0.5 * pts[j].X * (pts[(j + 1) % np].Y - pts[(j + np - 1) % np].Y);
  101.                   }
  102.                   if ((loopType & (int)HatchLoopTypes.External) > 0)
  103.                     area += Math.Abs(looparea);
  104.                   else
  105.                     area -= Math.Abs(looparea);
  106.                 }
  107.               }
  108.             }
  109.           }
  110.         }
  111.       }
  112.       return Math.Abs(area);
  113.     }
  114.  
  115.     public void Initialize()
  116.     {
  117.     }
  118.  
  119.     public void Terminate()
  120.     {
  121.     }
  122.  
  123.   }
  124. }



Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Спасибо огромное! Попробовал сам разобраться, получилось не очень.

Оффлайн alz

  • ADN OPEN
  • **
  • Сообщений: 95
  • Карма: 11
Решил сам переделать мой код из C++ в C#. Как всегда оказалось, что кое что в AutoCAD .NET API не работает из того, что работает в ObjectARX. В частности не срабатывает метод Curve2d.GetSamplePoints(double, double, double). Так что пришлось его заменить. В результате код выглядит так:

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

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Решил сам переделать мой код из C++ в C#. Как всегда оказалось, что кое что в AutoCAD .NET API не работает из того, что работает в ObjectARX. В частности не срабатывает метод Curve2d.GetSamplePoints(double, double, double). Так что пришлось его заменить. В результате код выглядит так:

Я так понимаю код не учитывает вложенность петель, типы петель текстов и различные стили решения островков. Когда он писался этого еще не было или он так и задумывался для самых простейших штриховок?
Не думаю, что мой код универсальный. Нужно анализировать конкретные штриховки.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение