Тема: Вычлениние грани из многоугольника

Как грамотней получить указатель на отрезок AcDbLine, когда он является частью (гранью) замкнутого многоугольника, зная сам многоугольник, и грань по точке лежащей на ней (они полученны функцией acedEntSel) ?
В голову приходит вначале сделать
acedCommand(..., _.EXPLODE,...);
затем уже вызвать acedEntSel, пользователь выберет уже отдельную грань, а не примитив, и далее выполнить объединение в многоугольник, но тогда объекта отрезок как такового уже не будет, и идентификатор будет смотреть в никуда ??
Для чего это надо:
есть какой-то многоугольник (может быть неправильный), пользователь щелкает мышкой на какую-то его грань, и она преобразуется в плоскую дугу.

Re: Вычлениние грани из многоугольника

> supremum
Жуть! Откуда отрезок в многоугольнике? И что такое многоугольник? Это AcDbPolyline? Тогда откуда в нем AcDbLine? Тебе нужно найти сегмент полилинии на котором (или ближайший к которому) указал пользователь.

Re: Вычлениние грани из многоугольника

Эээ, сорри что сумбурно выразился !
Многоугольник - это к примеру результат выполненной комманды _.RECTANGLE - замкнутая полилиния !
А сегмент полилинии это что ?

Re: Вычлениние грани из многоугольника

> supremum
сегмент полилини это участок между двумя узловыми точками :)
И кстати он не всегда линейный.
-----------
Первое что приходит на ум это спроецировать точку которую задал ползатель с экрана на твой многоугольник, а потом выяснить внутри какого сегмента она лежит.

Re: Вычлениние грани из многоугольника

> supremum

> Николай
Как вариант:
1) Использовать AcDbCurve::getClosestPointTo() для получения ближайшей точки
2) Использовать AcDbCurve::getParamAtPoint() для получения номера вершины многоугольника (нужно вычислить целую часть)

Re: Вычлениние грани из многоугольника

Жуть. Как-то в голове не укладывается ситуация: человек собирается программировать на ObjectARX, но не знает, что такое сегмент полилинии и не знает, что у многоугольника есть сторона, а не грань, а грань может быть у поверхности или тела.

Re: Вычлениние грани из многоугольника

Сразу вопрос с ходу:
AcDbPolyline наследуется от AcDbCurve, а в чем их разница ?

Re: Вычлениние грани из многоугольника

Да, вот такой кошмар. Если от моих незнаний Вас коробит, то нечитайте мои темы. Два месяца назад я еще вообще не подозревал о существовании ObjectARX и не использовал AutoCAD. По поводу грани - в следующий раз буду внимательней к терминологии, разницу между стороной, ребром и гранью знаю.
Сразу вопрос с ходу:
AcDbPolyline наследуется от AcDbCurve, а в чем их разница ?

Re: Вычлениние грани из многоугольника

> supremum
Я вам скажу честно - иногда мне гораздо интереснее читать ответы в темах, чем вопросы.

Re: Вычлениние грани из многоугольника

> supremum
AcDbCurve - абстрактый класс.

Re: Вычлениние грани из многоугольника

> supremum
Я так понял, на тебя забили :). Не страшно. Все с этого начинали :). AcDbCurve это общий класс для ряда графических примитивов (например AcDbPolyline2d, 3d и т.п. если хочешь, глянь в помощи). Через него можно получить доступ до всех общих свойств его потомков. Но вот доступ к тем свойствам, которые есть только у потомков можно получить только при обращении к ним напрямую.
В твоем случае хватит и AcDbCurve. Может сегодня или завтра (как время будет) кину тебе кусок кода который наверняка тебе поможет.

> Владимир Громов
Жуть. Как-то в голове не укладывается ситуация: человек собирается программировать на ObjectARX, но не знает, что такое сегмент полилинии...

А Вы сразу переписали Автокад под себя?
Да и просто читать можно только газеты. Можешь помочь - помоги, не можешь - не засоряй эфир :)

Re: Вычлениние грани из многоугольника

> Николай
Ишь ты. Чегой-то вы взъерепенились? Мне никогда и в голову не приходило ПЕРЕПИСЫВАТЬ AutoCAD под себя. И программировать (на AutoLISP) я начал через 2 года работы с AutoCAD. А тут - на тебе:

Два месяца назад я еще вообще не подозревал о существовании ObjectARX и не использовал AutoCAD.

Поневоле удивишься.

Re: Вычлениние грани из многоугольника

> Николай

> Владимир Громов
Хорош флудить!

Re: Вычлениние грани из многоугольника

> Владимир Громов
Согласен. НО если человек заинтересовался, то радоваться нада - нашего полку прибыло. А Вы отбиваете всякую охоту задавать вопросы. Согласитесь, не сильно приятно расчитывая получить помошь читать сообщения, которые мягко говоря не несут в себе полезной информации. Берите пример с Александра Ривилиса :), учитесь терпимей относиться к вопросам, какими б ... они не были.

> Александр Ривилис
Сорри, больше не буду :)

> supremum
А это код, который тебя интересует. Работает только в МСК, но его не сложно переделать под любую систему координат. Про дуговые сегменты речь вроде не шла.

ads_name ent;
ads_point pt;
AcDbCurve* pCurve;
AcDbObjectId eId;
if(ads_entsel("\nУкажите контур: ",ent,pt) != RTNORM) return;
if(acdbGetObjectId(eId, ent)!= Acad::eOk) return;
if (acdbOpenObject(pCurve, eId, AcDb::kForRead)!= Acad::eOk)return;
// -- начало проверки
// контур должен быть только полилинией
if (pCurve!=0) pCurve->close(); // на всякий случай закрываем объект
else return;
// -- конец поверки        
if (RTNORM != acedGetPoint(0, "\nУкажите сегмент:\n", pt)) return;
AcGePoint3dArray ptArr; ptArr.setLogicalLength(0); // на всякий случай
AcGeIntArray a1; a1.setLogicalLength(0);
AcGeIntArray a2; a2.setLogicalLength(0);
pCurve->getGripPoints(ptArr,a1,a2);
if (pCurve->isClosed()) ptArr.append(ptArr.first());
// в ptArr теперь хранятся координаты узловых точек контура
AcGePoint3d pt3d;
pt3d.x = pt[X];pt3d.y = pt[Y];pt3d.z = pt[Z];
AcGePoint3d ptOnCurve;
AcGePoint3d ptStartSegment, ptEndSegment;
pCurve->getClosestPointTo(pt3d, ptOnCurve);
// точка ptOnCurve лежит на контуре. Осталось вычленить сегмент.
double param1, param2, paramPT, dist1, dist2, distPT;    
pCurve->getParamAtPoint(ptOnCurve,paramPT);
pCurve->getDistAtParam(paramPT,distPT); // вычисляем расстояние от начальной точки до нашей точки
  for (int i = 0; i < ptArr.length() - 1; i++)
  {
    // pCurve->getDistAtPoint() не всегда срабатывает правильно
    pCurve->getParamAtPoint(ptArr.at(i),param1);
    pCurve->getParamAtPoint(ptArr.at(i+1),param2);
    pCurve->getDistAtParam(param1,dist1);
    pCurve->getDistAtParam(param2,dist2);            
    if (dist2 < dist1)
    {
      pCurve->getEndParam(param2);
      pCurve->getDistAtParam(param2,dist2);
    }
    if ((distPT > dist1)&&(distPT < dist2))
    {
      pCurve->getPointAtParam(param1,ptStartSegment);
      pCurve->getPointAtParam(param2,ptEndSegment);
      break;
    }
}
// в ptStartSegment находится начальная точка сегмента
// в ptEndSegment находится конечная точка сегмента
// ...

Может и не совсем изящно написано, но работает правильно на 100%. Проверял.

Re: Вычлениние грани из многоугольника

Теоритический вопрос - что есть "parameter of curve", исползуемый в функциях getDistAtParam, getParamAtPoint и тп ?

Re: Вычлениние грани из многоугольника

Если не ошибаюсь, то это гдето так (из книги)

Абстрактный класс AcDbCurve обеспечивает множество функций для действия на кривых, включая функции для проектирования, распространения{*продления*}, и кривых смещения, также как набора функций для запроса параметров кривой. Кривые могут быть определены или в пространстве параметра или в Декартовом координатном пространстве. Трехмерная кривая - функция одного параметра (f (t)), в то время как трехмерная поверхность - функция двух параметров (f (u, v)). Конверсионные функции позволяют Вам конвертировать{*преобразовывать*} данные от его представления параметра до точек в Декартовой системе координат.

Но в принципе не забивай себе этом голову. Считай что

  pCurve->getParamAtPoint(...);
  pCurve->getDistAtParam(...);

это усложненный вариант

pCurve->getDistAtPoint(...);

Там где-то так в комментариях и написано.
--
Так помог код или это не совсем то что хотелось получить?

Re: Вычлениние грани из многоугольника

Код помог (сейчас еще вопросы напишу нему smile ), но я сделал немного не так. Изучив AcDbPolyline, я понял что вычленять ничего не надо, так как у сегмента полилинии есть св-во bulge, изменяя которое (0 или ненулевое значение) я соответственно получаю или line или arc тип сегмента:

        ads_name name;
        ads_point pt;
        double num;
        AcDbPolyline *pline;
        AcDbObjectId eId;
        AcGePoint3d ptOnCurve;
        acedEntSel("Укажи сторону для преобразования\n", name, pt);
        AcGePoint3d pt3= AcGePoint3d(pt[0],pt[1],0);
        if(acdbGetObjectId(eId, name)!= Acad::eOk) return AcRx::kRetError;
        if (acdbOpenObject(pline, eId, AcDb::kForWrite)!= Acad::eOk) return AcRx::kRetError;
        
        pline->getClosestPointTo(pt3, ptOnCurve);
        AcGePoint2d ptOnPolyLine = AcGePoint2d(ptOnCurve.x , ptOnCurve.y);
        
        for(int i=0; i < pline->numVerts(); i++)
        {
            if(pline->onSegAt(i, ptOnPolyLine, num) == Adesk::kTrue)
            {
                acutPrintf("vertex # %i is selected !", i); break;
            }
        }
        pline->close();