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

ADN Club => ObjectARX => Тема начата: VetalBY от 07-10-2016, 11:00:45

Название: Возможно ли правильно высчитать площадь штриховки?
Отправлено: VetalBY от 07-10-2016, 11:00:45
Предложенный пример посмотрел на 2013 и 2017 акадах. Файл прислали, случай конечно неординарный, присутствует мультилиния. Но всё же оригинал штриховки (который прислал пользователь) команда _AREA считает правильно в AutoCAD 2013, а в 2017 говорит, что объект не обладает площадью. GeomProps даёт другой результат (такой же и мне удалось получить). Как видим, даже разные версии акада дают разный результат. И что делать?  :)
Название: Re: Возможно ли правильно высчитать площадь штриховки?
Отправлено: Александр Ривилис от 07-10-2016, 12:40:55
В 2013 для левой и правой штриховки команда _AREA у меня тоже не видит площадь:

Реального решения я в этой ситуации не вижу. Просто сообщать, что штриховка неправильная.
Название: Re: Возможно ли правильно высчитать площадь штриховки?
Отправлено: VetalBY от 07-10-2016, 13:36:04
А правильной считать штриховку, у которой площадь можно получить с помощью getArea? Александр, Ваш способ основан на этом алгоритме? http://adn-cis.org/perimetr-shtrixovki-s-pomoshhyu-objectarx-i-.net-api.html
Название: Re: Возможно ли правильно высчитать площадь штриховки?
Отправлено: Александр Ривилис от 07-10-2016, 13:44:28
Проанализируй при помощи ARXDBG эту штриховку и увидишь, что вместо 2-ух loop, как должно быть по логике у неё только один:

(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fimg-fotki.yandex.ru%2Fget%2F55431%2F7842324.7%2F0_13eb52_3b9bf209_orig.png&hash=cbd27bf7366ad4681b50fa89ae3728da)

И фактически получается, что площади этих двух контуров суммируются вместо того, чтобы вычитаться.
Алгоритм вычисления площади для штриховки у меня более сложный, чем в том примере.
Если pHatch->getArea(ar) == Acad::eOk  && ar > 1e-6 - используется эта площадь, если нет, то:

Код - 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. }
Название: Re: Возможно ли правильно высчитать площадь штриховки?
Отправлено: VetalBY от 07-10-2016, 13:55:04
Да, я видел, что там один loop. В результате получилось, что внутренний контур вместо вычета прибавился. Беда в том, что его никак не "видно".
Спасибо за код! Получается, что через AcGeCompositeCurve2d результату доверять нельзя.
Название: Re: Возможно ли правильно высчитать площадь штриховки?
Отправлено: Александр Ривилис от 07-10-2016, 16:50:12
Беда в том, что его никак не "видно".
Вообще-то видно. Обрати внимание на то, что первые четыре Edge образуют полный loop и у них у всех конец очередного Edge совпадает с началом следующего. А вот начиная с пятого Edge идёт новый loop. Т.е. теоретически можно собрать их в правильные loop'ы и посчитать правильную площадь.
Название: Re: Возможно ли правильно высчитать площадь штриховки?
Отправлено: VetalBY от 10-10-2016, 09:37:31
Теоретически можно, и в конкретно этом случае (акад похоже и сделал, но loop'ы сложил), как-то не надежно всё это. Думаю, что в любом случае пользователя буду предупреждать, что площадь может быть посчитана не верно. А вообще получается, что вычертить акад штриховку может, а площадь посчитать - нет, забавно) Есть под рукой Bricscad 13, у него проблем с этой штриховкой не возникло, даже в окне свойств показал.