Exemplo n.º 1
0
void EarClippingTriangulation::initLists ()
{
    // go through points checking ccw, cw or collinear order and identifying ears
    std::list<std::size_t>::iterator it (_vertex_list.begin()), prev(_vertex_list.end()), next;
    --prev;
    next = it;
    ++next;
    GeoLib::Orientation orientation;
    bool first_run(true); // saves special handling of the last case with identical code
    while (_vertex_list.size() >= 3 && first_run) {
        if (next == _vertex_list.end()) {
            first_run = false;
            next = _vertex_list.begin();
        }
        orientation  = getOrientation (_pnts[*prev], _pnts[*it], _pnts[*next]);
        if (orientation == GeoLib::COLLINEAR) {
            WARN("EarClippingTriangulation::initLists(): collinear points (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)",
                    (*_pnts[*prev])[0], (*_pnts[*prev])[1], (*_pnts[*prev])[2],
                    (*_pnts[*it])[0], (*_pnts[*it])[1], (*_pnts[*it])[2],
                    (*_pnts[*next])[0], (*_pnts[*next])[1], (*_pnts[*next])[2]);
            it = _vertex_list.erase (it);
            ++next;
        } else {
            if (orientation == GeoLib::CW) {
                _convex_vertex_list.push_back (*it);
                if (isEar (*prev, *it, *next))
                    _ear_list.push_back (*it);
            }
            prev = it;
            it = next;
            ++next;
        }
    }
}
Exemplo n.º 2
0
void EarClippingTriangulation::initLists ()
{
	// go through points checking ccw, cw or collinear order and identifying ears
	std::list<size_t>::iterator it (_vertex_list.begin()), prev(_vertex_list.end()), next;
	prev--;
	next = it;
	next++;
	MathLib::Orientation orientation;
	while (next != _vertex_list.end())
	{
		orientation  = getOrientation (_pnts[*prev], _pnts[*it], _pnts[*next]);
		if (orientation == COLLINEAR)
		{
			it = _vertex_list.erase (it);
			next++;
		}
		else
		{
			if (orientation == CW)
			{
				_convex_vertex_list.push_back (*it);
				if (isEar (*prev, *it, *next))
					_ear_list.push_back (*it);
			}
			prev = it;
			it = next;
			next++;
		}
	}

	next = _vertex_list.begin();
	orientation = getOrientation (_pnts[*prev], _pnts[*it], _pnts[*next]);
	if (orientation == COLLINEAR)
		it = _vertex_list.erase (it);
	if (orientation == CW)
	{
		_convex_vertex_list.push_back (*it);
		if (isEar (*prev, *it, *next))
			_ear_list.push_back (*it);
	}
}
PolygonTriangulation EarRemovalAlgorithm::triangulate(const vector<Point2D> & polygon){
	int n = polygon.size();
	PolygonTriangulation t(polygon);
	if(n < 3) return t;

	list<int> currPoly; // Lista que armazena os índices do polígono atual do algoritmo de remoção de orelhas
	vector<int> isEar(n, 0); // Vetor que armazena indicador de formação de orelha nos pontos do polígono

	// Adiciona todos os pontos do polígono na lista de pontos do polígono atual do algoritmo
	for(int i=0; i<n; i++){
		currPoly.push_back(i);
	}

	// Determina para cada ponto se no mesmo se forma uma orelha no triângulo formado com seus vizinhos
	for(list<int>::iterator it = currPoly.begin(); it != currPoly.end(); it++){
		int p = *it;
		isEar[p] = checkEar(currPoly, it, polygon);
	}

	// Equanto não tivermos apenas um triângulo, então removemos ums orelha
	while(currPoly.size() > 3){
		// Procura uma orelha no polígono atual
		for(list<int>::iterator it = currPoly.begin(); it != currPoly.end(); it++){
			int p = *it;
			if(isEar[p]){
				list<int>::iterator prevIt = getPrevIterator(currPoly, it);
				list<int>::iterator nextIt = getNextIterator(currPoly, it);
				// Determina índice dos pontos da orelha
				int p0 = *prevIt;
				int p1 = *it;
				int p2 = *nextIt;
				// Adicioa orelha a triangulação do polígono
				t.addTriangle(p0, p1, p2);
				// Remove o ponto central do triângulo do polígono
				currPoly.erase(it);
				// Atualiza o indicador de orelha nos pontos vizinhos de p1 no novo polígono formado após a remoção de p1
				isEar[p0] = checkEar(currPoly, prevIt, polygon);
				isEar[p2] = checkEar(currPoly, nextIt, polygon);
				break;
			}
		}
	}
	// Adiciona o triângulo final na triangulação
	list<int>::iterator it = currPoly.begin();
	int p0 = *it; it++;
	int p1 = *it; it++;
	int p2 = *it;

	t.addTriangle(p0, p1, p2);

	return t;
}
Exemplo n.º 4
0
    void triangulate(const Vertices& vertices, PolygonMesh& output)
    {
        const int n_vertices = vertices.vertices.size();

        if (n_vertices <= 3)
        {
            output.polygons.push_back(vertices);
            return;
        }

        std::vector<uint32_t> remaining_vertices(n_vertices);
        if (area(vertices.vertices) > 0) // clockwise?
        {
            remaining_vertices = vertices.vertices;
        }
        else
        {
            for (int v = 0; v < n_vertices; v++)
                remaining_vertices[v] = vertices.vertices[n_vertices - 1 - v];
        }

        // Avoid closed loops.
        if (remaining_vertices.front() == remaining_vertices.back())
            remaining_vertices.erase(remaining_vertices.end()-1);

        // null_iterations avoids infinite loops if the polygon is not simple.
        for (int u = remaining_vertices.size() - 1, null_iterations = 0;
                remaining_vertices.size() > 2 && null_iterations < remaining_vertices.size()*2;
                ++null_iterations, u=(u+1)%remaining_vertices.size())
        {
            int v = (u + 1) % remaining_vertices.size();
            int w = (u + 2) % remaining_vertices.size();

            if (isEar(u, v, w, remaining_vertices))
            {
                Vertices triangle;
                triangle.vertices.resize(3);
                triangle.vertices[0] = remaining_vertices[u];
                triangle.vertices[1] = remaining_vertices[v];
                triangle.vertices[2] = remaining_vertices[w];
                output.polygons.push_back(triangle);
                remaining_vertices.erase(remaining_vertices.begin()+v);
                null_iterations = 0;
            }
        }
        for (int i = 0; i < remaining_vertices.size(); ++i)
            ntk_dbg_print(remaining_vertices[i], 1);
    }
Exemplo n.º 5
0
void
pcl::EarClipping::triangulate (const Vertices& vertices, PolygonMesh& output)
{
  const int n_vertices = static_cast<const int> (vertices.vertices.size ());

  if (n_vertices <= 3)
    return;

  std::vector<uint32_t> remaining_vertices (n_vertices);
  if (area (vertices.vertices) > 0) // clockwise?
    remaining_vertices = vertices.vertices;
  else
    for (int v = 0; v < n_vertices; v++)
      remaining_vertices[v] = vertices.vertices[n_vertices - 1 - v];

  // Avoid closed loops.
  if (remaining_vertices.front () == remaining_vertices.back ())
    remaining_vertices.erase (remaining_vertices.end () - 1);

  // null_iterations avoids infinite loops if the polygon is not simple.
  for (int u = static_cast<int> (remaining_vertices.size ()) - 1, null_iterations = 0;
      remaining_vertices.size () > 2 && null_iterations < static_cast<int >(remaining_vertices.size () * 2);
      ++null_iterations, u = (u+1) % static_cast<int> (remaining_vertices.size ()))
  {
    int v = (u + 1) % static_cast<int> (remaining_vertices.size ());
    int w = (u + 2) % static_cast<int> (remaining_vertices.size ());

    if (isEar (u, v, w, remaining_vertices))
    {
      Vertices triangle;
      triangle.vertices.resize (3);
      triangle.vertices[0] = remaining_vertices[u];
      triangle.vertices[1] = remaining_vertices[v];
      triangle.vertices[2] = remaining_vertices[w];
      output.polygons.push_back (triangle);
      remaining_vertices.erase (remaining_vertices.begin () + v);
      null_iterations = 0;
    }
  }
}
Exemplo n.º 6
0
void EarClippingTriangulation::clipEars()
{
	std::list<size_t>::iterator it, prev, next;
	// *** clip an ear
	while (_vertex_list.size() > 3)
	{
		// pop ear from list
		size_t ear = _ear_list.front();
		_ear_list.pop_front();
		// remove ear tip from _convex_vertex_list
		_convex_vertex_list.remove(ear);

		// remove ear from vertex_list, apply changes to _ear_list, _convex_vertex_list
		bool nfound(true);
		it = _vertex_list.begin();
		prev = _vertex_list.end();
		prev--;
		while (nfound && it != _vertex_list.end())
		{
			if (*it == ear)
			{
				nfound = false;
				it = _vertex_list.erase(it); // remove ear tip
				next = it;
				if (next == _vertex_list.end())
				{
					next = _vertex_list.begin();
					prev = _vertex_list.end();
					prev--;
				}
				// add triangle
				_triangles.push_back(GEOLIB::Triangle(_pnts, *prev, ear, *next));

				// check the orientation of prevprev, prev, next
				std::list<size_t>::iterator prevprev;
				if (prev == _vertex_list.begin())
					prevprev = _vertex_list.end();
				else
					prevprev = prev;
				prevprev--;

				// apply changes to _convex_vertex_list and _ear_list looking "backward"
				MathLib::Orientation orientation = getOrientation(_pnts[*prevprev],
				                                                  _pnts[*prev],
				                                                  _pnts[*next]);
				if (orientation == CW)
				{
					BASELIB::uniqueListInsert(_convex_vertex_list, *prev);
					// prev is convex
					if (isEar(*prevprev, *prev, *next))
						// prev is an ear tip
						BASELIB::uniqueListInsert(_ear_list, *prev);
					else
						// if necessary remove prev
						_ear_list.remove(*prev);
				}
				else
				{
					// prev is not convex => reflex or collinear
					_convex_vertex_list.remove(*prev);
					_ear_list.remove(*prev);
					if (orientation == COLLINEAR)
					{
						prev = _vertex_list.erase(prev);
						if (prev == _vertex_list.begin())
						{
							prev = _vertex_list.end();
							prev--;
						}
						else
							prev--;
					}
				}

				// check the orientation of prev, next, nextnext
				std::list<size_t>::iterator nextnext,
				help_it(_vertex_list.end());
				help_it--;
				if (next == help_it)
					nextnext = _vertex_list.begin();
				else
				{
					nextnext = next;
					nextnext++;
				}

				// apply changes to _convex_vertex_list and _ear_list looking "forward"
				orientation = getOrientation(_pnts[*prev], _pnts[*next],
				                             _pnts[*nextnext]);
				if (orientation == CW)
				{
					BASELIB::uniqueListInsert(_convex_vertex_list, *next);
					// next is convex
					if (isEar(*prev, *next, *nextnext))
						// next is an ear tip
						BASELIB::uniqueListInsert(_ear_list, *next);
					else
						// if necessary remove *next
						_ear_list.remove(*next);
				}
				else
				{
					// next is not convex => reflex or collinear
					_convex_vertex_list.remove(*next);
					_ear_list.remove(*next);
					if (orientation == COLLINEAR)
					{
						next = _vertex_list.erase(next);
						if (next == _vertex_list.end())
							next = _vertex_list.begin();
					}
				}
			}
			else
			{
				prev = it;
				it++;
			}
		}
	}
	// add last triangle
	next = _vertex_list.begin();
	prev = next;
	next++;
	it = next;
	next++;
	if (getOrientation(_pnts[*prev], _pnts[*it], _pnts[*next]) == CCW)
		_triangles.push_back(GEOLIB::Triangle(_pnts, *prev, *next, *it));
	else
		_triangles.push_back(GEOLIB::Triangle(_pnts, *prev, *it, *next));
}
Exemplo n.º 7
0
Graph <Point2D> EarClipper::triangulate(const Graph <Point2D> &arg, std::vector <Triangle2D> *triangles) {
    Graph <Point2D> result (arg);
    std::vector<bool> vertexStatus (arg.getVertexCount(), false); //1 - ear, 0 - not ear
    std::list<int> remainingVertices;
    short direction = determineDirection(arg);

    for (unsigned int i = 0; i < arg.getVertexCount(); ++i) {
        remainingVertices.push_back(i);
    }

    for (std::list<int>::iterator it = remainingVertices.begin(); it != remainingVertices.end(); ++it) {
        vertexStatus[*it] = isEar(arg, remainingVertices, it, direction);
    }

    std::list<int>::iterator currentVertex = remainingVertices.begin();
    while (remainingVertices.size() > 3) {
        bool earFound = false;

        for (unsigned int i = remainingVertices.size(); i > 0 && remainingVertices.size() > 3; --i) {
            if (vertexStatus[*currentVertex] == 1) {
                earFound = true;
                addTriangle(result, remainingVertices, currentVertex, triangles);

                std::list<int>::iterator vertexToRemove = currentVertex;

                if (++currentVertex == remainingVertices.end()) {
                    currentVertex = remainingVertices.begin();
                }
                remainingVertices.erase(vertexToRemove);
                vertexStatus[*currentVertex] = isEar(arg, remainingVertices, currentVertex, direction);

                if (currentVertex == remainingVertices.begin()) {
                    currentVertex = --remainingVertices.end();
                } else {
                    --currentVertex;
                }
                vertexStatus[*currentVertex] = isEar(arg, remainingVertices, currentVertex, direction);
            } else {
                if (++currentVertex == remainingVertices.end()) {
                    currentVertex = remainingVertices.begin();
                }
            }
        }

        if (!earFound) {
            result.connectVertices();
            triangles->clear();

            std::cerr << "Impossoble to triangulate\n";
            return result;
        }
    }

    if (triangles != 0 && remainingVertices.size() == 3) { //add remains to triangulation
        triangles->push_back(Triangle2D(arg.getVertex(*remainingVertices.begin()), arg.getVertex(*++remainingVertices.begin()),
                                        arg.getVertex(*--remainingVertices.end())));
    }

    if (triangles != 0) {
        if (validateTriangulation(arg, *triangles)) {
            std::cout << "Validation OK\n";
        } else {
            std::cerr << "Validation failed\n";
        }
    }

    return result;
}