Subdiv2D / Delaunay OpenCV ломается, когда точка, указанная для определения местоположения, является одной из вершин треугольника? - PullRequest
2 голосов
/ 05 августа 2011

Код для построения триангуляции:

CvSubdiv2D *subdiv;
CvMemStorage *storage = cvCreateMemStorage(0);
CvRect rectangle = cvRect(0, 0, 100, 100);
subdiv = cvCreateSubdivDelaunay2D(rectangle, storage);
CvPoint2D32f p1 = cvPoint2D32f(10, 10);
CvPoint2D32f p2 = cvPoint2D32f(50, 10);
CvPoint2D32f p3 = cvPoint2D32f(10, 50);
cvSubdivDelaunay2DInsert(subdiv, p1);
cvSubdivDelaunay2DInsert(subdiv, p2);
cvSubdivDelaunay2DInsert(subdiv, p3);

После этого выполните запрос, используя одну из точек:

CvSubdiv2DEdge edge;
CvSubdiv2DPoint *pp;
CvSubdiv2DPointLocation loc = cvSubdiv2DLocate(subdiv, p1, &edge, &pp);

Получив результаты, вы должны проверитьесли точка падает на:

  • фасет
  • ребро
  • вершина
  • вне определенной триангуляции / прямоугольника

В данном случае это вершина:

if(loc == CV_PTLOC_VERTEX) {
//        CvSubdiv2DPoint *tp = cvSubdiv2DEdgeOrg(edge);
//        CvPoint2D32f point = tp->pt;
//        std::cout << point.x << ", " << point.y << std::endl;

//        CvSubdiv2DPoint *tp = cvSubdiv2DEdgeOrg(pp->first);
//        CvPoint2D32f point = tp->pt;
//        std::cout << point.x << ", " << point.y << std::endl;
}

Однако оба моих подхода к ней провалились.В первых 3 строках я пытался определить, правильно ли задан locate параметр.Это не так, и я получил ошибку сегментации.Во втором блоке я попытался получить доступ к элементу first в структуре CvSubdiv2DPoint, но он также не работает - ошибка сегментации.Я не могу найти точки на first и не могу использовать ее для итерации по другим ребрам.

Причина, по которой CvSubdiv2DPoint бесполезна, заключается в том, что для итерации по структуре и фактического нахождения треугольниковМне нужно CvSubdiv2DEdge, но, поскольку я не могу преобразовать точку в ребро, результат этой функции бесполезен.

Возможно, я что-то упустил, но мне кажется, что он сломан. Вот документация. Есть мысли?

1 Ответ

0 голосов
/ 17 февраля 2012

Края можно повторять, используя функциональность последовательности, вот код:

CvMemStorage* storage = cvCreateMemStorage();
CvSubdiv2D* subdivision = cvCreateSubdivDelaunay2D(rect, storage);
for (int i = 0; i < points.size(); ++i)
{
    cvSubdivDelaunay2DInsert(subdivision, points[i]);
}

cvCalcSubdivVoronoi2D(subdivision);
CvSeqReader reader;
CvSeq* seq = (CvSeq*) subdivision->edges;
cvStartReadSeq(seq, &reader);
for (int i = 0; i < seq->total; ++i)
{
    CvQuadEdge2D* edge = (CvQuadEdge2D*)reader.ptr;
    if (CV_IS_SET_ELEM(edge))
    {
               //Do something...
    }
    CV_NEXT_SEQ_ELEM(seq->elem_size, reader);
}

if (storage != 0)
{
    cvReleaseMemStorage(&storage);
}

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

...