//-----------------------------------------------------------------------
// note : input must not contain cutting segment
void Triangulator::triangulatePolygon(const std::vector<int>& input, const DelaunaySegment& seg, DelaunayTriangleBuffer& tbuffer, const PointList& pointList)
{	
	// Find a point which, when associated with seg.i1 and seg.i2, builds a Delaunay triangle
	std::vector<int>::const_iterator currentPoint = input.begin();
	bool found = true;
	while (!found)
	{
		Circle c(pointList[*currentPoint], pointList[seg.i1], pointList[seg.i2]);		
		for (std::vector<int>::const_iterator it = input.begin();it!=input.end();it++)
		{
			if (c.isPointInside(pointList[*it]) )
			{			
				currentPoint = it;
				break;
			}
		}
		found = true;
	}
	
	// Insert current triangle
	Triangle t(&pointList, tbuffer.end());
	t.setVertices(*currentPoint, seg.i1, seg.i2);
	tbuffer.push_back(t);
	
	// Recurse	
	std::vector<int> part1(input.begin(), currentPoint-1);		
	if (!part1.empty())
		triangulatePolygon(part1, seg, tbuffer, pointList);
	
	std::vector<int> part2(currentPoint+1, input.end());
	if (!part2.empty())
		triangulatePolygon(part2, seg, tbuffer, pointList);	
}
void CreateHexCore::createBoundaryFaces()
{
  EG_VTKSP(vtkUnstructuredGrid, new_grid);

  // find all polygons which need to be triangulated and collect the new triangles
  m_Part.setAllCells();
  QList<QVector<vtkIdType> > new_triangles;
  QVector<bool> adapt_cell(m_Grid->GetNumberOfCells(), false);
  for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
    vec3_t xc = cellCentre(m_Grid, id_cell);
    if (isVolume(id_cell, m_Grid)) {
      for (int i = 0; i < m_Part.c2cGSize(id_cell); ++i) {
        if (m_Part.c2cGG(id_cell, i) == -1) {
          QVector<vtkIdType> face;
          getFaceOfCell(m_Grid, id_cell, i, face);
          QVector<QVector<vtkIdType> > triangles;
          triangulatePolygon(m_Grid, face, triangles);
          foreach (QVector<vtkIdType> triangle, triangles) {
            vec3_t x1, x2, x3;
            m_Grid->GetPoint(triangle[0], x1.data());
            m_Grid->GetPoint(triangle[1], x2.data());
            m_Grid->GetPoint(triangle[2], x3.data());
            vec3_t xt = (1.0/3.0)*(x1 + x2 + x3);
            vec3_t nt = GeometryTools::triNormal(x1, x2, x3);
            if (nt*(xt - xc) < 0) {
              swap(triangle[0], triangle[1]);
            }
            new_triangles.append(triangle);
          }
          if (face.size() > 3) {
            adapt_cell[id_cell] = true;
          }
        }
      }
    }
Beispiel #3
0
void PolygonNode::calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color)
{
    if (getNumDifferentPts(m_Pts) < 3) {
        return;
    }
    // Remove duplicate points
    vector<glm::vec2> pts;
    vector<unsigned int> holeIndexes;
    pts.reserve(m_Pts.size());

    if (glm::distance2(m_Pts[0], m_Pts[m_Pts.size()-1]) > 0.1) {
        pts.push_back(m_Pts[0]);
    }
    for (unsigned i = 1; i < m_Pts.size(); ++i) {
        if (glm::distance2(m_Pts[i], m_Pts[i-1]) > 0.1) {
            pts.push_back(m_Pts[i]);
        }
    }

    if (m_Holes.size() > 0) {
        for (unsigned int i = 0; i < m_Holes.size(); i++) { //loop over collection
            holeIndexes.push_back(pts.size());
            for (unsigned int j = 0; j < m_Holes[i].size(); j++) { //loop over vector
                pts.push_back(m_Holes[i][j]);
            }
        }
    }
    if (color.getA() > 0) {
        glm::vec2 minCoord = pts[0];
        glm::vec2 maxCoord = pts[0];
        for (unsigned i = 1; i < pts.size(); ++i) {
            if (pts[i].x < minCoord.x) {
                minCoord.x = pts[i].x;
            }
            if (pts[i].x > maxCoord.x) {
                maxCoord.x = pts[i].x;
            }
            if (pts[i].y < minCoord.y) {
                minCoord.y = pts[i].y;
            }
            if (pts[i].y > maxCoord.y) {
                maxCoord.y = pts[i].y;
            }
        }
        vector<unsigned int> triIndexes;
        triangulatePolygon(triIndexes, pts, holeIndexes);

        for (unsigned i = 0; i < pts.size(); ++i) {
            glm::vec2 texCoord = calcFillTexCoord(pts[i], minCoord, maxCoord);
            pVertexData->appendPos(pts[i], texCoord, color);
        }
        for (unsigned i = 0; i < triIndexes.size(); i+=3) {
            pVertexData->appendTriIndexes(triIndexes[i], triIndexes[i+1], 
                    triIndexes[i+2]);
        }
    }
}
Beispiel #4
0
void ConcaveShape::ensureDecomposed() const
{
	if (!mNeedsDecomposition)
		return;

	// Split the concave polygon into convex triangles
	triangulatePolygon(mPoints.begin(), mPoints.end(), TriangleGenerator(mTriangleVertices, mFillColor));
	mNeedsDecomposition = false;
}
// ----------------------------------------------------
void SpotsScene::addPoints() {
    pts.clear();
    
    for(int i=0; i<6; i++) {
        float x = ofRandom(10, CUBE_SCREEN_WIDTH-10);
        float y = ofRandom(10, CUBE_SCREEN_HEIGHT-10);
        pts.push_back(ofVec2f(x, y));
    }   
    
    
    tris = triangulatePolygon(pts);
}
Beispiel #6
0
/**
* @see testBurnTrianglePolygonAndTriangulateResult1()
*
* В треугольнике делается две неперекрывающиеся дыры.
*/
void testBurnTrianglePolygonAndTriangulateResult2() {

	// Треугольник
	polygon_t tri;
	bg::append( tri, bg::make< p_t >(   0.0,   0.0 ) );
	bg::append( tri, bg::make< p_t >(   0.0, 100.0 ) );
	bg::append( tri, bg::make< p_t >( 100.0,   0.0 ) );
	bg::correct( tri );
	cout << "Треугольник: " << bg::dsv( tri ) << endl;

	// Кольцо 1 внутри треугольника
	polygon_t ring1;
	bg::append( ring1, bg::make< p_t >( 10.0, 10.0 ) );
	bg::append( ring1, bg::make< p_t >( 10.0, 50.0 ) );
	bg::append( ring1, bg::make< p_t >( 20.0, 50.0 ) );
	bg::append( ring1, bg::make< p_t >( 20.0, 10.0 ) );
	bg::correct( ring1 );
	cout << "Кольцо 1 внутри треугольника (дыра): " << bg::dsv( ring1 ) << endl;

	// Кольцо 2 внутри треугольника, не перекрывает кольцо 1
	polygon_t ring2;
	bg::append( ring2, bg::make< p_t >( 1.0, 1.0 ) );
	bg::append( ring2, bg::make< p_t >( 1.0, 5.0 ) );
	bg::append( ring2, bg::make< p_t >( 2.0, 5.0 ) );
	bg::append( ring2, bg::make< p_t >( 2.0, 2.0 ) );
	bg::correct( ring2 );
	cout << "Кольцо 2 внутри треугольника (дыра): " << bg::dsv( ring2 ) << endl;
	assert( !bg::intersects( ring1, ring2) && "Кольца не должны пересекаться." );

	cout << endl << "Выжигаем в треугольнике дыру по форме кольца 1." << endl;
    std::vector< polygon_t > figure;
    bg::difference( tri, ring1, figure );
	assert( (figure.size() == 1) && "Должен получиться 1 полигон." );

	cout << endl << "Выжигаем в треугольнике дыру по форме кольца 2." << endl;
	polygon_t firstPoly = *figure.cbegin();
	figure.clear();
	bg::difference( firstPoly, ring2, figure );
	assert( (figure.size() == 1) && "Должен получиться 1 полигон." );
	
	cout << endl << "Полигонов после выжигания 2 дыр: " << figure.size() << endl;
	for (auto itr = figure.cbegin(); itr != figure.cend(); ++itr) {
	    cout << "Полигон " << bg::dsv( *itr ) << endl;
    }

	// Отдаём полученную фигуру на триангуляцию
	firstPoly = *figure.cbegin();
	const std::vector< triangle_t >  r = triangulatePolygon( firstPoly );
	assert( (r.size() > 1) && "Должно получиться много треугольников." );

}
void PolygonBuilder::triangulate(const std::vector<float>& verts,
                                 std::vector<GLuint>& triangleInds)
{
    if (!m_valid)
        return;
    if (m_outerRingInds.size() == 3 && m_innerRingSizes.empty())
    {
        // Already a triangle - nothing to do.
        for (int i = 0; i < 3; ++i)
            triangleInds.push_back(m_outerRingInds[i]);
        return;
    }
    triangulatePolygon(verts, m_outerRingInds, m_innerRingSizes,
                        m_innerRingInds, triangleInds);
}
Beispiel #8
0
/**
* Пересечение треугольника и кольца (полигон без дырок). Кольцо много
* меньше треугольника и лежит внутри треугольника, прожигая в нём дыру.
* После вычисления фигуры пересечения делаем её триангуляцию.
*/
void testBurnTrianglePolygonAndTriangulateResult1() {

	// Треугольник
	/*
	triangle_t tri(
		bg::make< p_t >( 0.0,     0.0 ),
		bg::make< p_t >( 0.0,   100.0 ),
		bg::make< p_t >( 100.0,   0.0 )
	);
	*/
	polygon_t tri;
	bg::append( tri, bg::make< p_t >(   0.0,   0.0 ) );
	bg::append( tri, bg::make< p_t >(   0.0, 100.0 ) );
	bg::append( tri, bg::make< p_t >( 100.0,   0.0 ) );
	bg::correct( tri );
	cout << "Треугольник: " << bg::dsv( tri ) << endl;

	// Кольцо внутри треугольника
	polygon_t ring;
	bg::append( ring, bg::make< p_t >( 10.0, 10.0 ) );
	bg::append( ring, bg::make< p_t >( 10.0, 50.0 ) );
	bg::append( ring, bg::make< p_t >( 20.0, 50.0 ) );
	bg::append( ring, bg::make< p_t >( 20.0, 10.0 ) );
	bg::correct( ring );
	cout << "Кольцо внутри треугольника (дыра): " << bg::dsv( ring ) << endl;


	cout << endl << "Выжигаем в треугольнике дыру по форме кольца." << endl << endl;
	// @see http://www.boost.org/doc/libs/1_47_0/libs/geometry/doc/html/geometry/reference/algorithms/difference.html
    std::vector< polygon_t > figure;
    bg::difference( tri, ring, figure );
	
	cout << endl << "Полигонов после выжигания дыры: " << figure.size() << endl;
	for (auto itr = figure.cbegin(); itr != figure.cend(); ++itr) {
	    cout << "Полигон " << bg::dsv( *itr ) << endl;
    }

	assert( (figure.size() == 1) && "Должен получиться 1 полигон." );

	// Отдаём полученную фигуру на триангуляцию
	polygon_t firstPoly = *figure.cbegin();
	const std::vector< triangle_t >  r = triangulatePolygon( firstPoly );
	assert( (r.size() > 1) && "Должно получиться много треугольников." );

}
Beispiel #9
0
/**
* @see testBurnTrianglePolygonAndTriangulateResult1()
*
* В треугольнике делается дыра, делающая из него вогнутый полигон.
*/
void testBurnTrianglePolygonAndTriangulateResult3() {

	// Треугольник
	polygon_t tri;
	bg::append( tri, bg::make< p_t >(   0.0,   0.0 ) );
	bg::append( tri, bg::make< p_t >(   0.0, 100.0 ) );
	bg::append( tri, bg::make< p_t >( 100.0,   0.0 ) );
	bg::correct( tri );
	cout << "Треугольник: " << bg::dsv( tri ) << endl;

	// Кольцо, часть - внутри треугольника, часть - снаружи
	polygon_t ring;
	bg::append( ring, bg::make< p_t >( -5.0, -5.0 ) );
	bg::append( ring, bg::make< p_t >( -5.0, 50.0 ) );
	bg::append( ring, bg::make< p_t >( 20.0, 50.0 ) );
	bg::append( ring, bg::make< p_t >( 20.0, -5.0 ) );
	bg::correct( ring );
	cout << "Кольцо выбивает часть треугольника: " << bg::dsv( ring ) << endl;
	//assert( bg::overlaps( tri, ring ) && "Треугольник и кольцо должны частично перекрывать друг друга." );
	//assert( bg::intersects( tri, ring ) && !bg::within( ring, tri ) && "Треугольник и кольцо должны частично перекрывать друг друга." );


	cout << endl << "Выбиваем в треугольнике часть по форме кольца." << endl << endl;
    std::vector< polygon_t > figure;
    bg::difference( tri, ring, figure );
	
	cout << endl << "Полигонов после выбивания: " << figure.size() << endl;
	for (auto itr = figure.cbegin(); itr != figure.cend(); ++itr) {
	    cout << "Полигон " << bg::dsv( *itr ) << endl;
    }

	assert( (figure.size() == 1) && "Должен получиться 1 полигон." );

	// Отдаём вогнутый полигон на триангуляцию
	polygon_t firstPoly = *figure.cbegin();
	assert( (firstPoly.inners().size() == 0) && "Фигура должна быть с выбоиной, но без дыры." );
	const std::vector< triangle_t >  r = triangulatePolygon( firstPoly );
	assert( (r.size() > 1) && "Должно получиться много треугольников." );

}
Beispiel #10
0
void PHBezierPath::rebuildVAO(PHGLVertexArrayObject * vao, const PHRect & texCoord)
{
    const vector<anchorPoint> * a = tesselate(calculatedVertices());
    size_t nVertices;
    GLfloat * r = vertexDataFromAnchorList(*a, texCoord, nVertices);
    delete a;

    vao->bindToEdit();
    PHGLVBO * vbo = vao->attributeVBO(PHIMAGEATTRIBUTE_POS);
    if (!vbo)
        vbo = new PHGLVertexBufferObject(vao->gameManager());
    else
        vbo->retain();

    vbo->bindTo(PHGLVBO::arrayBuffer);
    vbo->setData(NULL, nVertices*4*sizeof(GLfloat), PHGLVBO::dynamicDraw);
    vbo->setSubData(r, 0, nVertices*4*sizeof(GLfloat));
    vao->vertexPointer(PHIMAGEATTRIBUTE_POS, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0, vbo);
    vao->vertexPointer(PHIMAGEATTRIBUTE_TXC, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 2*sizeof(GLfloat), vbo);
    vbo->unbind();
    vbo->release();

    size_t nIndexes;
    GLushort * indexes = triangulatePolygon(r, 4, nVertices, nIndexes);
    delete r;

    PHGLVBO * ivbo = vao->elementArrayVBO();
    if (!ivbo)
        ivbo = new PHGLVertexBufferObject(vao->gameManager());
    else
        ivbo->retain();
    ivbo->bindTo(PHGLVBO::elementArrayBuffer);
    ivbo->setData(indexes, nIndexes*sizeof(GLushort), PHGLVBO::dynamicDraw);
    vao->setDrawElements(GL_TRIANGLES, nIndexes, GL_UNSIGNED_SHORT, 0);

    ivbo->release();
    delete indexes;
    vao->unbind();
}
Beispiel #11
0
void LcpFinder::triangulate(int polygon) {


    if (this->triangulated[polygon]) {
        return;
    }
    this->triangulated[polygon] = true;

    auto points = this->polygons.at(polygon);

    std::vector<Triangle*> newTriangles = triangulatePolygon(points, polygon);
    int nodecount = 0;
    for (auto ring : points) {
        nodecount += ring.size();
    }
    for (int i = 0; i < newTriangles.size(); i++) {
        //std::cout<<"i"<<i<<std::endl;
        Triangle* newTri = newTriangles[i];
        for (int n = 0; n < 3; n++) {
            if (newTri->neighbours[n] == nullptr) {
                const Coords* lb = newTri->points[(n + 2) % 3];
                const Coords* rb = newTri->points[(n + 1) % 3];
                double d = eucDistance(lb, rb);
                if (d>this->maxDist) {
                    //std::cout << "intermediate points between" << lb->toString() << rb->toString();
                    //std::cout << newTri;
                    int toAdd = std::ceil(d / this->maxDist) - 1;
                    //std::cout << "adding: " << toAdd << std::endl;
                    //std::cout<<"toAdd: "<<toAdd<<std::endl;
                    for (int i = 1; i <= toAdd; i++) {
                        double x{((rb->getX() - lb->getX()) / (toAdd + 1)) * i + lb->getX()};
                        double y{((rb->getY() - lb->getY()) / (toAdd + 1)) * i + lb->getY()};
                        std::pair < std::tr1::unordered_set<Coords, CoordsHasher>::iterator, bool> success = this->coordmap.insert(Coords{x, y, polygon, false});

                        const Coords* intermediate = &*success.first;
                        intermediate->addToPolygon(polygon);
                        //std::cout << intermediate->toString();

                        newTri->interiorPoints.push_back(intermediate);
                        const Coords* thirdCorner = newTri->points[n];

                        Triangle* t1 = new Triangle{};
                        t1->points[0] = intermediate;
                        t1->points[1] = thirdCorner;
                        t1->points[2] = rb;
                        Triangle* t2 = new Triangle{};
                        t2->points[0] = intermediate;
                        t2->points[1] = lb;
                        t2->points[2] = thirdCorner;

                        t1->neighbours[2] = t2;
                        t1->neighbours[0] = newTri->neighbours[(n + 2) % 3];
                        t2->neighbours[1] = t1;
                        t2->neighbours[0] = newTri->neighbours[(n + 1) % 3];


                        for (const Coords* interior : newTri->interiorPoints) {
                            if (coordsInTriangle(t1, interior)) {
                                t1->interiorPoints.push_back(interior);
                            }
                            if (coordsInTriangle(t2, interior)) {
                                t2->interiorPoints.push_back(interior);
                            }
                        }
                        checkTargets(polygon, t1); //change to using old triangle interior points to make faster
                        checkTargets(polygon, t2);

                        intermediate->addTriangle(t1, polygon);
                        intermediate->addTriangle(t2, polygon);
                    }
                }
            }
        }

        if (coordsInTriangle(newTri, this->startPoint)) {
            subTriangles(newTri, polygon, this->startPoint);
        }
        this->checkTargets(polygon, newTri);
        this->checkLinear(polygon, newTri, true);

    }


}
//----------------------------------------
void ofxBox2dPolygon::triangulate() {
	vector <ofxVec2f> orgPts = vertices;
	vertices = triangulatePolygon(vertices);
	bIsTriangulated = true;
}