Example #1
0
// Initialize polypartition TPPLPoly from a list of indices and vertices
//
// verts     - 3D polygon vertex vectors
// xind,yind - Indices of 3D vectors to extract as x and y coordinates for 2D
//             triangulation computation.
// inds,size - Array of indices into the `verts` list
// isHole    - Value for the hole flag, and to determine the orientation
static void initTPPLPoly(TPPLPoly& poly,
                         const std::vector<float>& verts,
                         int xind, int yind,
                         const GLuint* inds, int size,
                         bool isHole)
{
    // Check for explicitly closed polygons (last and first vertices equal) and
    // discard the last vertex in these cases.  This is a pretty stupid
    // convention, but the OGC have blessed it and now we've got a bunch of
    // geospatial formats (kml, WKT, GeoJSON) which require it.  Sigh.
    // http://gis.stackexchange.com/questions/10308/why-do-valid-polygons-repeat-the-same-start-and-end-point/10309#10309
    if (inds[0] == inds[size-1] ||
        (verts[3*inds[0]+0] == verts[3*inds[size-1]+0] &&
         verts[3*inds[0]+1] == verts[3*inds[size-1]+1] &&
         verts[3*inds[0]+2] == verts[3*inds[size-1]+2]))
    {
        g_logger.warning_limited("Ignoring duplicate final vertex in explicitly closed polygon");
        size -= 1;
    }
    // Copy into polypartition data structure
    poly.Init(size);
    for (int i = 0; i < size; ++i)
    {
        poly[i].x = verts[3*inds[i]+xind];
        poly[i].y = verts[3*inds[i]+yind];
        poly[i].id = inds[i];
    }
    int orientation = poly.GetOrientation();
    // Invert so that outer = ccw, holes = cw
    if ((orientation == TPPL_CW) ^ isHole)
        poly.Invert();
    poly.SetHole(isHole);
}
Example #2
0
bool TriangulatorAdaptor::triangulate(int *triangleIndexes) {
    int XX, YY;
    from3DTo2D(XX, YY);

    map<pair<double, double> , int> coorToPosMap; // coordinate to position map
    for (int i = 0; i < polygon.size(); i++) {
        coorToPosMap.insert(
                pair<pair<double, double> , int>(
                        pair<double, double>(polygon[i][XX], polygon[i][YY]), i));
    }

    TPPLPoly poly;
    poly.Init(polygon.size());
    for (int i = 0; i < polygon.size(); i++) {
        poly[i].x = polygon[i][XX];
        poly[i].y = polygon[i][YY];
    }

    if (poly.GetOrientation() == TPPL_CW) {
        isClockwise = true;
        poly.Invert(); // polygon has to be counter-clockwise
    } else if(poly.GetOrientation() == TPPL_CCW) {
        isClockwise = false;
    } else {
    	return false;
    }

    list<TPPLPoly> triangles;

    TPPLPartition triangulator; // see http://code.google.com/p/polypartition/
    int success = triangulator.Triangulate_OPT(&poly, &triangles);
    if (success != 1) {
        cout << "Error: polygon cannot be triangulated!" << endl;
        cout << "Polygon:" << endl;
        for (int i=0; i<polygon.size(); i++) {
            cout << polygon[i][0] << "   " << polygon[i][1] << "   " << polygon[i][2] << endl;
        }
		return false;
    }
    //assert(success == 1);
    assert(triangles.size() +2 == polygon.size());
    int count = 0;
    for (list<TPPLPoly>::iterator it = triangles.begin(); it != triangles.end(); it++) {
        if (!isClockwise) {
            for (int j = 0; j < 3; j++) {
                triangleIndexes[count * 3 + j] = coorToPosMap[pair<double, double>((*it)[j].x,
                        (*it)[j].y)];
            }
        } else {
            for (int j = 0; j < 3; j++) {
                triangleIndexes[count * 3 + 2 - j] = coorToPosMap[pair<double, double>((*it)[j].x,
                        (*it)[j].y)];
            }
        }
        count++;
    }
    assert(count == triangles.size());
    return true;
}
Example #3
0
TPPLPoly TPPLPoly_To_Polygon(const ClipperLib::Polygon& B)
{
    TPPLPoly poly;
    poly.Init(B.size());
    for(unsigned int i=0; i < B.size() ; ++i)
    {
        poly[i].x = B[i].X;
        poly[i].y = B[i].Y;
    }
    return poly;
}
Example #4
0
std::vector<sf::Vector2f> _getEdges(TPPLPoly& A)
{
	std::vector<sf::Vector2f> edges;
	for(unsigned int i=0; i < (A.GetNumPoints()+1) ; ++i)
	{
		sf::Vector2f P1( A[i].x, A[i].y);
		sf::Vector2f P2( A[(i+1)%A.GetNumPoints()].x, A[(i+1)%A.GetNumPoints()].y );

		edges.push_back( P2 - P1 );
	}
	return edges;
}
  void
  Cylinder::triangulate(list<TPPLPoly>& tri_list) const
  {
    TPPLPartition pp;
    list<TPPLPoly> polys;
    TPPLPoly poly;
    TPPLPoint pt;

    double d_alpha = 0.5;
    double alpha_max = 0, alpha_min = std::numeric_limits<double>::max();
    for(size_t i = 0; i < contours_[0].size(); ++i)
    {
      double alpha = contours_[0][i](0) / r_;
      if (alpha > alpha_max) alpha_max = alpha;
      if (alpha < alpha_min) alpha_min = alpha;
    }
    std::cout << "r " << r_ << std::endl;
    std::cout << "alpha " << alpha_min << "," << alpha_max << std::endl;
    std::vector<std::vector<std::vector<Eigen::Vector2f> > > contours_split;
    for(size_t j = 0; j < contours_.size(); j++)
    {
      for(double i = alpha_min + d_alpha; i <= alpha_max; i += d_alpha)
      {
        std::vector<Eigen::Vector2f> contour_segment;
        for(size_t k = 0; k < contours_[j].size(); ++k)
        {
          double alpha = contours_[j][k](0) / r_;
          if( alpha >= i - d_alpha - 0.25 && alpha < i + 0.25)
          {
            contour_segment.push_back(contours_[j][k]);
          }
        }
        //std::cout << "c " << j << i << " has " << contour_segment.size() << " points" << std::endl;
        if(contour_segment.size() < 3) continue;
        poly.Init(contour_segment.size());
        poly.SetHole(holes_[j]);
        for( unsigned int l = 0; l < contour_segment.size(); l++)
        {
          pt.x = contour_segment[l](0);
          pt.y = contour_segment[l](1);
          poly[l] = pt;
        }
        if (holes_[j])
          poly.SetOrientation(TPPL_CW);
        else
          poly.SetOrientation(TPPL_CCW);
        polys.push_back(poly);
      }
    }
    // triangulation into monotone triangles
    pp.Triangulate_EC (&polys, &tri_list);
  }
Example #6
0
void make_poly(float* buf, int pnt_sz, TPPLPoly& poly)
{
	poly.Init(pnt_sz);

	for (int k(0); k < pnt_sz; k++)
	{
		poly[k].x = buf[2 * k];
		poly[k].y = buf[2 * k + 1];
	}

	if (poly.GetOrientation() == TPPL_CW)
	{
		poly.SetHole(true);
	}

}
Example #7
0
std::vector<sf::Vector2f> _getPoints(TPPLPoly& A)
{
	std::vector<sf::Vector2f> points;
	for(unsigned int i=0; i < A.GetNumPoints() ; ++i)
	{
		sf::Vector2f P( A[i].x, A[i].y);

		points.push_back( P );
	}
	return points;
}
Example #8
0
 void partition() {
   TPPLPoly poly;
   std::vector<Point> nodes = polygons_[0].nodes_;
   poly.Init(nodes.size());
   unsigned int i = 0;
   for (std::vector<Point>::const_iterator p = nodes.begin(); p != nodes.end(); ++p, ++i) {
     poly[i].x = p->lat;
     poly[i].y = p->lon;
   }
   std::list<TPPLPoly> convex_polys;
   TPPLPartition partitioner;
   partitioner.Triangulate_OPT(&poly, &convex_polys);
   //partitioner.ConvexPartition_HM(&poly, &convex_polys);
   polygons_.clear();
   for (std::list<TPPLPoly>::iterator p = convex_polys.begin(); p != convex_polys.end(); ++p) {
     add_polygon();
     for (long i = 0; i < p->GetNumPoints(); ++i) {
       TPPLPoint point = p->GetPoint(i);
       add_node(Point(point.x, point.y));
     }
   }
 }
Example #9
0
//triangulates a set of polygons by first partitioning them into monotone polygons
//O(n*log(n)) time complexity, O(n) space complexity
//the algorithm used here is outlined in the book
//"Computational Geometry: Algorithms and Applications" 
//by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
int TPPLPartition::MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys) {
	list<TPPLPoly>::iterator iter;
	MonotoneVertex *vertices;
	long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
	long polystartindex, polyendindex;
	TPPLPoly *poly;
	MonotoneVertex *v,*v2,*vprev,*vnext;
	ScanLineEdge newedge;
	bool error = false;

	numvertices = 0;
	for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
		numvertices += iter->GetNumPoints();
	}

	maxnumvertices = numvertices*3;
	vertices = new MonotoneVertex[maxnumvertices];
	newnumvertices = numvertices;

	polystartindex = 0;
	for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
		poly = &(*iter);
		polyendindex = polystartindex + poly->GetNumPoints()-1;
		for(i=0;i<poly->GetNumPoints();i++) {
			vertices[i+polystartindex].p = poly->GetPoint(i);
			if(i==0) vertices[i+polystartindex].previous = polyendindex;
			else vertices[i+polystartindex].previous = i+polystartindex-1;
			if(i==(poly->GetNumPoints()-1)) vertices[i+polystartindex].next = polystartindex;
			else vertices[i+polystartindex].next = i+polystartindex+1;
		}
		polystartindex = polyendindex+1;
	}

	//construct the priority queue
	long *priority = new long [numvertices];
	for(i=0;i<numvertices;i++) priority[i] = i;
	std::sort(priority,&(priority[numvertices]),VertexSorter(vertices));

	//determine vertex types
	char *vertextypes = new char[maxnumvertices];
	for(i=0;i<numvertices;i++) {
		v = &(vertices[i]);
		vprev = &(vertices[v->previous]);
		vnext = &(vertices[v->next]);

		if(Below(vprev->p,v->p)&&Below(vnext->p,v->p)) {
			if(IsConvex(vnext->p,vprev->p,v->p)) {
				vertextypes[i] = TPPL_VERTEXTYPE_START;
			} else {
				vertextypes[i] = TPPL_VERTEXTYPE_SPLIT;
			}
		} else if(Below(v->p,vprev->p)&&Below(v->p,vnext->p)) {
			if(IsConvex(vnext->p,vprev->p,v->p))
			{
				vertextypes[i] = TPPL_VERTEXTYPE_END;
			} else {
				vertextypes[i] = TPPL_VERTEXTYPE_MERGE;
			}
		} else {
			vertextypes[i] = TPPL_VERTEXTYPE_REGULAR;
		}
	}

	//helpers
	long *helpers = new long[maxnumvertices];

	//binary search tree that holds edges intersecting the scanline
	//note that while set doesn't actually have to be implemented as a tree
	//complexity requirements for operations are the same as for the balanced binary search tree
	set<ScanLineEdge> edgeTree;
	//store iterators to the edge tree elements
	//this makes deleting existing edges much faster
	set<ScanLineEdge>::iterator *edgeTreeIterators,edgeIter;
	edgeTreeIterators = new set<ScanLineEdge>::iterator[maxnumvertices];
	pair<set<ScanLineEdge>::iterator,bool> edgeTreeRet;
	for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = edgeTree.end();

	//for each vertex
	for(i=0;i<numvertices;i++) {
		vindex = priority[i];
		v = &(vertices[vindex]);
		vindex2 = vindex;
		v2 = v;

		//depending on the vertex type, do the appropriate action
		//comments in the following sections are copied from "Computational Geometry: Algorithms and Applications"
		switch(vertextypes[vindex]) {
			case TPPL_VERTEXTYPE_START:
				//Insert ei in T and set helper(ei) to vi.
				newedge.p1 = v->p;
				newedge.p2 = vertices[v->next].p;
				newedge.index = vindex;
				edgeTreeRet = edgeTree.insert(newedge);
				edgeTreeIterators[vindex] = edgeTreeRet.first;
				helpers[vindex] = vindex;
				break;

			case TPPL_VERTEXTYPE_END:
				//if helper(ei-1) is a merge vertex
				if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
					//Insert the diagonal connecting vi to helper(ei-1) in D.
					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous], 
						vertextypes, edgeTreeIterators, &edgeTree, helpers);
				}
				//Delete ei-1 from T
				edgeTree.erase(edgeTreeIterators[v->previous]);
				break;

			case TPPL_VERTEXTYPE_SPLIT:
				//Search in T to find the edge e j directly left of vi.
				newedge.p1 = v->p;
				newedge.p2 = v->p;
				edgeIter = edgeTree.lower_bound(newedge);
				if(edgeIter == edgeTree.begin()) {
					error = true;
					break;
				}
				edgeIter--;
				//Insert the diagonal connecting vi to helper(ej) in D.
				AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
					vertextypes, edgeTreeIterators, &edgeTree, helpers);
				vindex2 = newnumvertices-2;
				v2 = &(vertices[vindex2]);
				//helper(e j)?vi
				helpers[edgeIter->index] = vindex;
				//Insert ei in T and set helper(ei) to vi.
				newedge.p1 = v2->p;
				newedge.p2 = vertices[v2->next].p;
				newedge.index = vindex2;
				edgeTreeRet = edgeTree.insert(newedge);
				edgeTreeIterators[vindex2] = edgeTreeRet.first;
				helpers[vindex2] = vindex2;
				break;

			case TPPL_VERTEXTYPE_MERGE:
				//if helper(ei-1) is a merge vertex
				if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
					//Insert the diagonal connecting vi to helper(ei-1) in D.
					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
						vertextypes, edgeTreeIterators, &edgeTree, helpers);
					vindex2 = newnumvertices-2;
					v2 = &(vertices[vindex2]);
				}
				//Delete ei-1 from T.
				edgeTree.erase(edgeTreeIterators[v->previous]);
				//Search in T to find the edge e j directly left of vi.
				newedge.p1 = v->p;
				newedge.p2 = v->p;
				edgeIter = edgeTree.lower_bound(newedge);
				if(edgeIter == edgeTree.begin()) {
					error = true;
					break;
				}
				edgeIter--;
				//if helper(ej) is a merge vertex
				if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
					//Insert the diagonal connecting vi to helper(e j) in D.
					AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index],
						vertextypes, edgeTreeIterators, &edgeTree, helpers);
				}
				//helper(e j)?vi
				helpers[edgeIter->index] = vindex2;
				break;

			case TPPL_VERTEXTYPE_REGULAR:
				//if the interior of P lies to the right of vi
				if(Below(v->p,vertices[v->previous].p)) {
					//if helper(ei-1) is a merge vertex
					if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) {
						//Insert the diagonal connecting vi to helper(ei-1) in D.
						AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
							vertextypes, edgeTreeIterators, &edgeTree, helpers);
						vindex2 = newnumvertices-2;
						v2 = &(vertices[vindex2]);
					}
					//Delete ei-1 from T.
					edgeTree.erase(edgeTreeIterators[v->previous]);
					//Insert ei in T and set helper(ei) to vi.
					newedge.p1 = v2->p;
					newedge.p2 = vertices[v2->next].p;
					newedge.index = vindex2;
					edgeTreeRet = edgeTree.insert(newedge);
					edgeTreeIterators[vindex2] = edgeTreeRet.first;
					helpers[vindex2] = vindex;
				} else {
					//Search in T to find the edge ej directly left of vi.
					newedge.p1 = v->p;
					newedge.p2 = v->p;
					edgeIter = edgeTree.lower_bound(newedge);
					if(edgeIter == edgeTree.begin()) {
						error = true;
						break;
					}
					edgeIter--;
					//if helper(ej) is a merge vertex
					if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) {
						//Insert the diagonal connecting vi to helper(e j) in D.
						AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
							vertextypes, edgeTreeIterators, &edgeTree, helpers);
					}
					//helper(e j)?vi
					helpers[edgeIter->index] = vindex;
				}
				break;
		}

		if(error) break;
	}

	char *used = new char[newnumvertices];
	memset(used,0,newnumvertices*sizeof(char));

	if(!error) {
		//return result
		long size;
		TPPLPoly mpoly;
		for(i=0;i<newnumvertices;i++) {
			if(used[i]) continue;
			v = &(vertices[i]);
			vnext = &(vertices[v->next]);
			size = 1;
			while(vnext!=v) {
				vnext = &(vertices[vnext->next]);
				size++;
			}
			mpoly.Init(size);
			v = &(vertices[i]);
			mpoly[0] = v->p;
			vnext = &(vertices[v->next]);
			size = 1;
			used[i] = 1;
			used[v->next] = 1;
			while(vnext!=v) {
				mpoly[size] = vnext->p;
				used[vnext->next] = 1;
				vnext = &(vertices[vnext->next]);
				size++;
			}
			monotonePolys->push_back(mpoly);
		}
	}

	//cleanup
	delete [] vertices;
	delete [] priority;
	delete [] vertextypes;
	delete [] edgeTreeIterators;
	delete [] helpers;
	delete [] used;

	if(error) {
		return 0;
	} else {
		return 1;
	}
}
Example #10
0
GeneralPolygon::operator list<TPPLPoly>()
{
	
	auto isPolygonOutside = [&](const Contour &referencePolygon, const Contour &poly)
	{
		for(unsigned int p=0; p < referencePolygon.size() ; ++p)
			if( !_evenOddRuleAlgorithm( referencePolygon[p], poly) )
				return true;
		return false;
	};

	list<TPPLPoly> polys;
	for(unsigned int c=0; c < _contours.size() ; ++c)
	{
		const Contour &contour = _contours[c];
		TPPLPoly poly;
		poly.Init(contour.size());

		for(unsigned int v=0; v < contour.size() ; ++v)
		{
			TPPLPoint point;
			point.x = contour[v].x;
			point.y = contour[v].y;
			poly[v] = point;
		}

		// BE CAREFULL!!! not really correct because the polygon could be concave then
		// the center of mass could not be inside the polygon
		sf::Vector2f centerOfMass(0.0f, 0.0f);
		for(unsigned int i=0; i < contour.size() ; ++i)
			centerOfMass += contour[i];
		centerOfMass *= (1.0f/contour.size());

		std::vector<Contour> outsideContours;
		for(unsigned int i=0; i < _contours.size() ; ++i)
		{
			if( i == c )
			{
				outsideContours.push_back(_contours[i]);
				continue;
			}
			if( isPolygonOutside(_contours[i], contour) )
				outsideContours.push_back(_contours[i]);
		}

		// first test if is a hole or not
		if( !_evenOddRuleAlgorithm( centerOfMass, outsideContours ) )
			poly.SetHole(true);
		else
			poly.SetHole(false);

		// if it is a hole then it must be in CW order to the algorithm to recognize
		// else must be in CCW
		if( poly.IsHole() )
			poly.SetOrientation(TPPL_CW);// Hole orientation (needed in the algorithm)
		else
			poly.SetOrientation(TPPL_CCW);// Not a hole orientation (needed in the algorithm)

		polys.push_back(poly);
	}
	return polys;
}
Example #11
0
int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts) {
	TPPLPoint p1,p2,p3,p4;
	PartitionVertex *vertices;
	DPState2 **dpstates;
	long i,j,k,n,gap;
	list<Diagonal> diagonals,diagonals2;
	Diagonal diagonal,newdiagonal;
	list<Diagonal> *pairs,*pairs2;
	list<Diagonal>::iterator iter,iter2;
	int ret;
	TPPLPoly newpoly;
	list<long> indices;
	list<long>::iterator iiter;
	bool ijreal,jkreal;

	n = poly->GetNumPoints();
	vertices = new PartitionVertex[n];

	dpstates = new DPState2 *[n];
	for(i=0;i<n;i++) {
		dpstates[i] = new DPState2[n];
	}

	//init vertex information
	for(i=0;i<n;i++) {
		vertices[i].p = poly->GetPoint(i);
		vertices[i].isActive = true;
		if(i==0) vertices[i].previous = &(vertices[n-1]);
		else vertices[i].previous = &(vertices[i-1]);
		if(i==(poly->GetNumPoints()-1)) vertices[i].next = &(vertices[0]);
		else vertices[i].next = &(vertices[i+1]);
	}
	for(i=1;i<n;i++) {
		UpdateVertexReflexity(&(vertices[i]));
	}

	//init states and visibility
	for(i=0;i<(n-1);i++) {
		p1 = poly->GetPoint(i);
		for(j=i+1;j<n;j++) {
			dpstates[i][j].visible = true;
			if(j==i+1) {
				dpstates[i][j].weight = 0;
			} else {
				dpstates[i][j].weight = 2147483647;
			}
			if(j!=(i+1)) {
				p2 = poly->GetPoint(j);
				
				//visibility check
				if(!InCone(&vertices[i],p2)) {
					dpstates[i][j].visible = false;
					continue;
				}
				if(!InCone(&vertices[j],p1)) {
					dpstates[i][j].visible = false;
					continue;
				}

				for(k=0;k<n;k++) {
					p3 = poly->GetPoint(k);
					if(k==(n-1)) p4 = poly->GetPoint(0);
					else p4 = poly->GetPoint(k+1);
					if(Intersects(p1,p2,p3,p4)) {
						dpstates[i][j].visible = false;
						break;
					}
				}
			}
		}
	}
	for(i=0;i<(n-2);i++) {
		j = i+2;
		if(dpstates[i][j].visible) {
			dpstates[i][j].weight = 0;
			newdiagonal.index1 = i+1;
			newdiagonal.index2 = i+1;
			dpstates[i][j].pairs.push_back(newdiagonal);
		}
	}

	dpstates[0][n-1].visible = true;
	vertices[0].isConvex = false; //by convention

	for(gap=3; gap<n; gap++) {
		for(i=0;i<n-gap;i++) {
			if(vertices[i].isConvex) continue;
			k = i+gap;
			if(dpstates[i][k].visible) {
				if(!vertices[k].isConvex) {
					for(j=i+1;j<k;j++) TypeA(i,j,k,vertices,dpstates);
				} else {
					for(j=i+1;j<(k-1);j++) {
						if(vertices[j].isConvex) continue;				
						TypeA(i,j,k,vertices,dpstates);
					}
					TypeA(i,k-1,k,vertices,dpstates);
				}
			}
		}
		for(k=gap;k<n;k++) {
			if(vertices[k].isConvex) continue;
			i = k-gap;
			if((vertices[i].isConvex)&&(dpstates[i][k].visible)) {
				TypeB(i,i+1,k,vertices,dpstates);
				for(j=i+2;j<k;j++) {
					if(vertices[j].isConvex) continue;				
					TypeB(i,j,k,vertices,dpstates);
				}
			}
		}
	}


	//recover solution
	ret = 1;
	newdiagonal.index1 = 0;
	newdiagonal.index2 = n-1;
	diagonals.push_front(newdiagonal);
	while(!diagonals.empty()) {
		diagonal = *(diagonals.begin());
		diagonals.pop_front();
		if((diagonal.index2 - diagonal.index1) <=1) continue;
		pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
		if(pairs->empty()) {
			ret = 0;
			break;
		}
		if(!vertices[diagonal.index1].isConvex) {
			iter = pairs->end();
			iter--;
			j = iter->index2;
			newdiagonal.index1 = j;
			newdiagonal.index2 = diagonal.index2;
			diagonals.push_front(newdiagonal);
			if((j - diagonal.index1)>1) {
				if(iter->index1 != iter->index2) {
					pairs2 = &(dpstates[diagonal.index1][j].pairs);
					while(1) {
						if(pairs2->empty()) {
							ret = 0;
							break;
						}
						iter2 = pairs2->end();
						iter2--;
						if(iter->index1 != iter2->index1) pairs2->pop_back();
						else break;
					}
					if(ret == 0) break;
				}
				newdiagonal.index1 = diagonal.index1;
				newdiagonal.index2 = j;
				diagonals.push_front(newdiagonal);
			}
		} else {
			iter = pairs->begin();
			j = iter->index1;
			newdiagonal.index1 = diagonal.index1;
			newdiagonal.index2 = j;
			diagonals.push_front(newdiagonal);
			if((diagonal.index2 - j) > 1) {
				if(iter->index1 != iter->index2) {
					pairs2 = &(dpstates[j][diagonal.index2].pairs);
					while(1) {
						if(pairs2->empty()) {
							ret = 0;
							break;
						}
						iter2 = pairs2->begin();
						if(iter->index2 != iter2->index2) pairs2->pop_front();
						else break;
					}
					if(ret == 0) break;
				}
				newdiagonal.index1 = j;
				newdiagonal.index2 = diagonal.index2;
				diagonals.push_front(newdiagonal);
			}
		}
	}

	if(ret == 0) {
		for(i=0;i<n;i++) {
			delete [] dpstates[i];
		}
		delete [] dpstates;
		delete [] vertices;

		return ret;
	}

	newdiagonal.index1 = 0;
	newdiagonal.index2 = n-1;
	diagonals.push_front(newdiagonal);
	while(!diagonals.empty()) {
		diagonal = *(diagonals.begin());
		diagonals.pop_front();
		if((diagonal.index2 - diagonal.index1) <= 1) continue;
		
		indices.clear();
		diagonals2.clear();
		indices.push_back(diagonal.index1);
		indices.push_back(diagonal.index2);
		diagonals2.push_front(diagonal);

		while(!diagonals2.empty()) {
			diagonal = *(diagonals2.begin());
			diagonals2.pop_front();
			if((diagonal.index2 - diagonal.index1) <= 1) continue;
			ijreal = true;
			jkreal = true;
			pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
			if(!vertices[diagonal.index1].isConvex) {
				iter = pairs->end();
				iter--;
				j = iter->index2;
				if(iter->index1 != iter->index2) ijreal = false;
			} else {
				iter = pairs->begin();
				j = iter->index1;
				if(iter->index1 != iter->index2) jkreal = false;
			}

			newdiagonal.index1 = diagonal.index1;
			newdiagonal.index2 = j;
			if(ijreal) {
				diagonals.push_back(newdiagonal);
			} else {
				diagonals2.push_back(newdiagonal);
			}

			newdiagonal.index1 = j;
			newdiagonal.index2 = diagonal.index2;
			if(jkreal) {
				diagonals.push_back(newdiagonal);
			} else {
				diagonals2.push_back(newdiagonal);
			}

			indices.push_back(j);
		}

		indices.sort();
		newpoly.Init((long)indices.size());
		k=0;
		for(iiter = indices.begin();iiter!=indices.end();iiter++) {
			newpoly[k] = vertices[*iiter].p;
			k++;
		}
		parts->push_back(newpoly);
	}

	for(i=0;i<n;i++) {
		delete [] dpstates[i];
	}
	delete [] dpstates;
	delete [] vertices;

	return ret;
}
Example #12
0
//minimum-weight polygon triangulation by dynamic programming
//O(n^3) time complexity
//O(n^2) space complexity
int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles) {
	long i,j,k,gap,n;
	DPState **dpstates;
	TPPLPoint p1,p2,p3,p4;
	long bestvertex;
	tppl_float weight,minweight,d1,d2;
	Diagonal diagonal,newdiagonal;
	list<Diagonal> diagonals;
	TPPLPoly triangle;
	int ret = 1;

	n = poly->GetNumPoints();
	dpstates = new DPState *[n];
	for(i=1;i<n;i++) {
		dpstates[i] = new DPState[i];
	}

	//init states and visibility
	for(i=0;i<(n-1);i++) {
		p1 = poly->GetPoint(i);
		for(j=i+1;j<n;j++) {
			dpstates[j][i].visible = true;
			dpstates[j][i].weight = 0;
			dpstates[j][i].bestvertex = -1;
			if(j!=(i+1)) {
				p2 = poly->GetPoint(j);
				
				//visibility check
				if(i==0) p3 = poly->GetPoint(n-1);
				else p3 = poly->GetPoint(i-1);
				if(i==(n-1)) p4 = poly->GetPoint(0);
				else p4 = poly->GetPoint(i+1);
				if(!InCone(p3,p1,p4,p2)) {
					dpstates[j][i].visible = false;
					continue;
				}

				if(j==0) p3 = poly->GetPoint(n-1);
				else p3 = poly->GetPoint(j-1);
				if(j==(n-1)) p4 = poly->GetPoint(0);
				else p4 = poly->GetPoint(j+1);
				if(!InCone(p3,p2,p4,p1)) {
					dpstates[j][i].visible = false;
					continue;
				}

				for(k=0;k<n;k++) {
					p3 = poly->GetPoint(k);
					if(k==(n-1)) p4 = poly->GetPoint(0);
					else p4 = poly->GetPoint(k+1);
					if(Intersects(p1,p2,p3,p4)) {
						dpstates[j][i].visible = false;
						break;
					}
				}
			}
		}
	}
	dpstates[n-1][0].visible = true;
	dpstates[n-1][0].weight = 0;
	dpstates[n-1][0].bestvertex = -1;

	for(gap = 2; gap<n; gap++) {
		for(i=0; i<(n-gap); i++) {
			j = i+gap;
			if(!dpstates[j][i].visible) continue; 
			bestvertex = -1;
			for(k=(i+1);k<j;k++) {
				if(!dpstates[k][i].visible) continue; 
				if(!dpstates[j][k].visible) continue;

				if(k<=(i+1)) d1=0;
				else d1 = Distance(poly->GetPoint(i),poly->GetPoint(k));
				if(j<=(k+1)) d2=0;
				else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j));

				weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2;

				if((bestvertex == -1)||(weight<minweight)) {
					bestvertex = k;
					minweight = weight;
				}
			}
			if(bestvertex == -1) {
				for(i=1;i<n;i++) {
					delete [] dpstates[i];
				}
				delete [] dpstates;

				return 0;
			}
			
			dpstates[j][i].bestvertex = bestvertex;
			dpstates[j][i].weight = minweight;
		}
	}

	newdiagonal.index1 = 0;
	newdiagonal.index2 = n-1;
	diagonals.push_back(newdiagonal);
	while(!diagonals.empty()) {
		diagonal = *(diagonals.begin());
		diagonals.pop_front();
		bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
		if(bestvertex == -1) {
			ret = 0;		
			break;
		}
		triangle.Triangle(poly->GetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2));
		triangles->push_back(triangle);
		if(bestvertex > (diagonal.index1+1)) {
			newdiagonal.index1 = diagonal.index1;
			newdiagonal.index2 = bestvertex;
			diagonals.push_back(newdiagonal);
		}
		if(diagonal.index2 > (bestvertex+1)) {
			newdiagonal.index1 = bestvertex;
			newdiagonal.index2 = diagonal.index2;
			diagonals.push_back(newdiagonal);
		}
	}

	for(i=1;i<n;i++) {
		delete [] dpstates[i];
	}
	delete [] dpstates;

	return ret;
}
Example #13
0
int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts) {
	list<TPPLPoly> triangles;
	list<TPPLPoly>::iterator iter1,iter2;
	TPPLPoly *poly1 = 0, *poly2 = 0;
	TPPLPoly newpoly;
	TPPLPoint d1,d2,p1,p2,p3;
	long i11,i12,i21,i22,i13,i23,j,k;
	bool isdiagonal;
	long numreflex;

	//check if the poly is already convex
	numreflex = 0;
	for(i11=0;i11<poly->GetNumPoints();i11++) {
		if(i11==0) i12 = poly->GetNumPoints()-1;
		else i12=i11-1;
		if(i11==(poly->GetNumPoints()-1)) i13=0;
		else i13=i11+1;
		if(IsReflex(poly->GetPoint(i12),poly->GetPoint(i11),poly->GetPoint(i13))) {
			numreflex = 1;
			break;
		}
	}
	if(numreflex == 0) {
		parts->push_back(*poly);
		return 1;
	}

	if(!Triangulate_EC(poly,&triangles)) return 0;

	for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
		poly1 = &(*iter1);
		for(i11=0;i11<poly1->GetNumPoints();i11++) {
			d1 = poly1->GetPoint(i11);
			i12 = (i11+1)%(poly1->GetNumPoints());
			d2 = poly1->GetPoint(i12);

			isdiagonal = false;
			for(iter2 = iter1; iter2 != triangles.end(); iter2++) {
				if(iter1 == iter2) continue;
				poly2 = &(*iter2);

				for(i21=0;i21<poly2->GetNumPoints();i21++) {
					if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue;
					i22 = (i21+1)%(poly2->GetNumPoints());
					if((d1.x != poly2->GetPoint(i22).x)||(d1.y != poly2->GetPoint(i22).y)) continue;
					isdiagonal = true;
					break;
				}
				if(isdiagonal) break;
			}

			if(!isdiagonal) continue;

			p2 = poly1->GetPoint(i11);
			if(i11 == 0) i13 = poly1->GetNumPoints()-1;
			else i13 = i11-1;
			p1 = poly1->GetPoint(i13);
			if(i22 == (poly2->GetNumPoints()-1)) i23 = 0;
			else i23 = i22+1;
			p3 = poly2->GetPoint(i23);

			if(!IsConvex(p1,p2,p3)) continue;
			
			p2 = poly1->GetPoint(i12);
			if(i12 == (poly1->GetNumPoints()-1)) i13 = 0;
			else i13 = i12+1;
			p3 = poly1->GetPoint(i13);
			if(i21 == 0) i23 = poly2->GetNumPoints()-1;
			else i23 = i21-1;
			p1 = poly2->GetPoint(i23);
			
			if(!IsConvex(p1,p2,p3)) continue;

			newpoly.Init(poly1->GetNumPoints()+poly2->GetNumPoints()-2);
			k = 0;
			for(j=i12;j!=i11;j=(j+1)%(poly1->GetNumPoints())) {
				newpoly[k] = poly1->GetPoint(j);
				k++;
			}
			for(j=i22;j!=i21;j=(j+1)%(poly2->GetNumPoints())) {
				newpoly[k] = poly2->GetPoint(j);
				k++;
			}

			triangles.erase(iter2);
			*iter1 = newpoly;
			poly1 = &(*iter1);
			i11 = -1;

			continue;
		}
	}

	for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
		parts->push_back(*iter1);
	}

	return 1;
}
Example #14
0
//triangulation by ear removal
int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles) {
	long numvertices;
	PartitionVertex *vertices;
	PartitionVertex *ear = 0;
	TPPLPoly triangle;
	long i,j;
	bool earfound;

	if(poly->GetNumPoints() < 3) return 0;
	if(poly->GetNumPoints() == 3) {
		triangles->push_back(*poly);
		return 1;
	}

	numvertices = poly->GetNumPoints();

	vertices = new PartitionVertex[numvertices];
	for(i=0;i<numvertices;i++) {
		vertices[i].isActive = true;
		vertices[i].p = poly->GetPoint(i);
		if(i==(numvertices-1)) vertices[i].next=&(vertices[0]);
		else vertices[i].next=&(vertices[i+1]);
		if(i==0) vertices[i].previous = &(vertices[numvertices-1]);
		else vertices[i].previous = &(vertices[i-1]);
	}
	for(i=0;i<numvertices;i++) {
		UpdateVertex(&vertices[i],vertices,numvertices);
	}

	for(i=0;i<numvertices-3;i++) {
		earfound = false;
		//find the most extruded ear
		for(j=0;j<numvertices;j++) {
			if(!vertices[j].isActive) continue;
			if(!vertices[j].isEar) continue;
			if(!earfound) {
				earfound = true;
				ear = &(vertices[j]);
			} else {
				if(vertices[j].angle > ear->angle) {
					ear = &(vertices[j]);				
				}
			}
		}
		if(!earfound) {
			delete [] vertices;
			return 0;
		}

		triangle.Triangle(ear->previous->p,ear->p,ear->next->p);
		triangles->push_back(triangle);

		ear->isActive = false;
		ear->previous->next = ear->next;
		ear->next->previous = ear->previous;

		if(i==numvertices-4) break;

		UpdateVertex(ear->previous,vertices,numvertices);
		UpdateVertex(ear->next,vertices,numvertices);
	}
	for(i=0;i<numvertices;i++) {
		if(vertices[i].isActive) {
			triangle.Triangle(vertices[i].previous->p,vertices[i].p,vertices[i].next->p);
			triangles->push_back(triangle);
			break;
		}
	}

	delete [] vertices;

	return 1;
}
Example #15
0
//removes holes from inpolys by merging them with non-holes
int TPPLPartition::RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys) {
	list<TPPLPoly> polys;
	list<TPPLPoly>::iterator holeiter,polyiter,iter,iter2;
	long i,i2,holepointindex,polypointindex;
	TPPLPoint holepoint,polypoint,bestpolypoint;
	TPPLPoint linep1,linep2;
	TPPLPoint v1,v2;
	TPPLPoly newpoly;
	bool hasholes;
	bool pointvisible;
	bool pointfound;
	
	//check for trivial case (no holes)
	hasholes = false;
	for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
		if(iter->IsHole()) {
			hasholes = true;
			break;
		}
	}
	if(!hasholes) {
		for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
			outpolys->push_back(*iter);
		}
		return 1;
	}

	polys = *inpolys;

	while(1) {
		//find the hole point with the largest x
		hasholes = false;
		for(iter = polys.begin(); iter!=polys.end(); iter++) {
			if(!iter->IsHole()) continue;

			if(!hasholes) {
				hasholes = true;
				holeiter = iter;
				holepointindex = 0;
			}

			for(i=0; i < iter->GetNumPoints(); i++) {
				if(iter->GetPoint(i).x > holeiter->GetPoint(holepointindex).x) {
					holeiter = iter;
					holepointindex = i;
				}
			}
		}
		if(!hasholes) break;
		holepoint = holeiter->GetPoint(holepointindex);
		
		pointfound = false;
		for(iter = polys.begin(); iter!=polys.end(); iter++) {
			if(iter->IsHole()) continue;
			for(i=0; i < iter->GetNumPoints(); i++) {
				if(iter->GetPoint(i).x <= holepoint.x) continue;
				if(!InCone(iter->GetPoint((i+iter->GetNumPoints()-1)%(iter->GetNumPoints())),
					iter->GetPoint(i),
					iter->GetPoint((i+1)%(iter->GetNumPoints())),
					holepoint)) 
					continue;
				polypoint = iter->GetPoint(i);
				if(pointfound) {
					v1 = Normalize(polypoint-holepoint);
					v2 = Normalize(bestpolypoint-holepoint);
					if(v2.x > v1.x) continue;				
				}
				pointvisible = true;
				for(iter2 = polys.begin(); iter2!=polys.end(); iter2++) {
					if(iter2->IsHole()) continue;
					for(i2=0; i2 < iter2->GetNumPoints(); i2++) {
						linep1 = iter2->GetPoint(i2);
						linep2 = iter2->GetPoint((i2+1)%(iter2->GetNumPoints()));
						if(Intersects(holepoint,polypoint,linep1,linep2)) {
							pointvisible = false;
							break;
						}
					}
					if(!pointvisible) break;
				}
				if(pointvisible) {
					pointfound = true;
					bestpolypoint = polypoint;
					polyiter = iter;
					polypointindex = i;
				}
			}
		}

		if(!pointfound) return 0;

		newpoly.Init(holeiter->GetNumPoints() + polyiter->GetNumPoints() + 2);
		i2 = 0;
		for(i=0;i<=polypointindex;i++) {
			newpoly[i2] = polyiter->GetPoint(i);
			i2++;
		}
		for(i=0;i<=holeiter->GetNumPoints();i++) {
			newpoly[i2] = holeiter->GetPoint((i+holepointindex)%holeiter->GetNumPoints());
			i2++;
		}
		for(i=polypointindex;i<polyiter->GetNumPoints();i++) {
			newpoly[i2] = polyiter->GetPoint(i);
			i2++;
		}
		
		polys.erase(holeiter);
		polys.erase(polyiter);
		polys.push_back(newpoly);
	}

	for(iter = polys.begin(); iter!=polys.end(); iter++) {
		outpolys->push_back(*iter);
	}
	
	return 1;
}
Example #16
0
//triangulates monotone polygon
//O(n) time, O(n) space complexity
int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles) {
	long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
	TPPLPoint *points;
	long numpoints;
	TPPLPoly triangle;

	numpoints = inPoly->GetNumPoints();
	points = inPoly->GetPoints();

	//trivial calses
	if(numpoints < 3) return 0;
	if(numpoints == 3) {
		triangles->push_back(*inPoly);
	}

	topindex = 0; bottomindex=0;
	for(i=1;i<numpoints;i++) {
		if(Below(points[i],points[bottomindex])) bottomindex = i;
		if(Below(points[topindex],points[i])) topindex = i;
	}

	//check if the poly is really monotone
	i = topindex;
	while(i!=bottomindex) {
		i2 = i+1; if(i2>=numpoints) i2 = 0;
		if(!Below(points[i2],points[i])) return 0;
		i = i2;
	}
	i = bottomindex;
	while(i!=topindex) {
		i2 = i+1; if(i2>=numpoints) i2 = 0;
		if(!Below(points[i],points[i2])) return 0;
		i = i2;
	}

	char *vertextypes = new char[numpoints];
	long *priority = new long[numpoints];

	//merge left and right vertex chains
	priority[0] = topindex;
	vertextypes[topindex] = 0;
	leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0;
	rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1;
	for(i=1;i<(numpoints-1);i++) {
		if(leftindex==bottomindex) {
			priority[i] = rightindex;
			rightindex--; if(rightindex<0) rightindex = numpoints-1;
			vertextypes[priority[i]] = -1;
		} else if(rightindex==bottomindex) {
			priority[i] = leftindex;
			leftindex++;  if(leftindex>=numpoints) leftindex = 0;
			vertextypes[priority[i]] = 1;
		} else {
			if(Below(points[leftindex],points[rightindex])) {
				priority[i] = rightindex;
				rightindex--; if(rightindex<0) rightindex = numpoints-1;
				vertextypes[priority[i]] = -1;
			} else {
				priority[i] = leftindex;
				leftindex++;  if(leftindex>=numpoints) leftindex = 0;
				vertextypes[priority[i]] = 1;			
			}
		}
	}
	priority[i] = bottomindex;
	vertextypes[bottomindex] = 0;

	long *stack = new long[numpoints];
	long stackptr = 0;

	stack[0] = priority[0];
	stack[1] = priority[1];
	stackptr = 2;

	//for each vertex from top to bottom trim as many triangles as possible
	for(i=2;i<(numpoints-1);i++) {
		vindex = priority[i];
		if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) {
			for(j=0;j<(stackptr-1);j++) {
				if(vertextypes[vindex]==1) {
					triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
				} else {
					triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
				}
				triangles->push_back(triangle);
			}
			stack[0] = priority[i-1];
			stack[1] = priority[i];
			stackptr = 2;
		} else {
			stackptr--;
			while(stackptr>0) {
				if(vertextypes[vindex]==1) {
					if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) {
						triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]);
						triangles->push_back(triangle);
						stackptr--;
					} else {
						break;
					}
				} else {
					if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) {
						triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]);
						triangles->push_back(triangle);
						stackptr--;
					} else {
						break;
					}
				}
			}
			stackptr++;
			stack[stackptr] = vindex;
			stackptr++;
		}
	}
	vindex = priority[i];
	for(j=0;j<(stackptr-1);j++) {
		if(vertextypes[stack[j+1]]==1) {
			triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
		} else {
			triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
		}
		triangles->push_back(triangle);
	}

	delete [] priority;
	delete [] vertextypes;
	delete [] stack;

	return 1;
}
  void ShapeMarker::onNewMessage( const MarkerConstPtr& old_message,
                                  const MarkerConstPtr& new_message )
  {

    TPPLPartition pp;
    list<TPPLPoly> polys,result;

    //fill polys
    for(size_t i=0; i<new_message->points.size(); i++) {
      pcl::PointCloud<pcl::PointXYZ> pc;
      TPPLPoly poly;

      pcl::fromROSMsg(new_message->points[i],pc);

      poly.Init(pc.size());
      poly.SetHole(new_message->holes[i]);

      for(size_t j=0; j<pc.size(); j++) {
        poly[j] = MsgToPoint2D(pc[j], new_message);
      }
      if(new_message->holes[i])
        poly.SetOrientation(TPPL_CW);
      else
        poly.SetOrientation(TPPL_CCW);

      polys.push_back(poly);
    }

    pp.Triangulate_EC(&polys,&result);


    polygon_->clear();
    polygon_->begin(createMaterialIfNotExists(new_message->color.r,new_message->color.b,new_message->color.g,new_message->color.a), Ogre::RenderOperation::OT_TRIANGLE_LIST);

    TPPLPoint p1,p2,p3,p4, p12,p23,p31;

    for(std::list<TPPLPoly>::iterator it=result.begin(); it!=result.end(); it++) {
      //draw each triangle
      if(it->GetNumPoints()!=3) continue;

      p1 = it->GetPoint(0);
      p2 = it->GetPoint(1);
      p3 = it->GetPoint(2);
      p4.x = (p1.x+p2.x+p3.x)/3;
      p4.y = (p1.y+p2.y+p3.y)/3;
      p12.x = (p1.x+p2.x)/2;
      p12.y = (p1.y+p2.y)/2;
      p23.x = (p3.x+p2.x)/2;
      p23.y = (p3.y+p2.y)/2;
      p31.x = (p1.x+p3.x)/2;
      p31.y = (p1.y+p3.y)/2;

      triangle(new_message,polygon_,p1,p12,p4);
      triangle(new_message,polygon_,p1,p31,p4);
      triangle(new_message,polygon_,p3,p23,p4);

      triangle(new_message,polygon_,p12,p2,p4);
      triangle(new_message,polygon_,p31,p3,p4);
      triangle(new_message,polygon_,p23,p2,p4);
    }

    polygon_->end();

    vis_manager_->getSelectionManager()->removeObject(coll_);
    /*coll_ = vis_manager_->getSelectionManager()->createCollisionForObject(
        shape_, SelectionHandlerPtr(new MarkerSelectionHandler(this, MarkerID(
            "fake_ns", new_message->id))), coll_);*/

    Ogre::Vector3 pos, scale, scale_correct;
    Ogre::Quaternion orient;
    //transform(new_message, pos, orient, scale);

    /*if (owner_ && (new_message->scale.x * new_message->scale.y
     * new_message->scale.z == 0.0f))
  {
    owner_->setMarkerStatus(getID(), status_levels::Warn,
        "Scale of 0 in one of x/y/z");
  }*/
    Eigen::Vector3f origin=MsgToOrigin(new_message);
    pos.x = origin(0);
    pos.y = origin(1);
    pos.z = origin(2);

    //setPosition(pos);
    return;
    setOrientation( orient * Ogre::Quaternion( Ogre::Degree(90), Ogre::Vector3(1,0,0) ) );

    //scale_correct = Ogre::Quaternion( Ogre::Degree(90), Ogre::Vector3(1,0,0) ) * scale;

    //shape_->setScale(scale_correct);
  }
Example #18
0
void PlaneExt::TriangulatePlanePolygon()
{
	// clear Marker and Shape messages
	planeTriangles.points.clear();
	planeTrianglesSRS.clear();

	// for all polygons representing this plane
	for (unsigned int polygon_i = 0; polygon_i < planePolygonsClipper.size(); ++polygon_i)
	{
		planeTrianglesSRS.push_back(cob_3d_mapping_msgs::Shape());
		planeTrianglesSRS.back().type = cob_3d_mapping_msgs::Shape::POLYGON;
		planeTrianglesSRS.back().params.push_back(a);
		planeTrianglesSRS.back().params.push_back(b);
		planeTrianglesSRS.back().params.push_back(c);
		planeTrianglesSRS.back().params.push_back(d);
		planeTrianglesSRS.back().holes.push_back(false);

		// convert each polygon to polygonizer DS
    	TPPLPoly triPolygon;
    	triPolygon.Init(planePolygonsClipper[polygon_i].outer.size());
    	pcl::PointCloud<pcl::PointXYZ> current_point_cloud;

		for (unsigned int i = 0; i < planePolygonsClipper[polygon_i].outer.size(); ++i)
		{
			triPolygon[i].x = CONVERT_FROM_LONG(planePolygonsClipper[polygon_i].outer[i].X);
			triPolygon[i].y = CONVERT_FROM_LONG(planePolygonsClipper[polygon_i].outer[i].Y);

			// additionaly, insert this point into shape message
			pcl::PointXYZ point;
			point.x = triPolygon[i].x;
			point.y = triPolygon[i].y;
			point.z = 0;
			current_point_cloud.push_back(point);
		}

		// triangulate
		TPPLPartition triangulation;
		std::list<TPPLPoly> triangles;
		triangulation.Triangulate_EC(&triPolygon, &triangles);

		// create a message object
		for (std::list<TPPLPoly>::iterator it = triangles.begin(); it != triangles.end(); ++it)
		{
			for (unsigned int j = 0; j < it->GetNumPoints(); ++j)
			{
				Eigen::Vector3f vec;
				vec(0) = it->GetPoint(j).x;
				vec(1) = it->GetPoint(j).y;
				vec(2) = 0;
				vec = planeTransXY.inverse() * vec;
				geometry_msgs::Point p;
				p.x = vec(0) + planeShift*a;
				p.y = vec(1) + planeShift*b;
				p.z = vec(2) + planeShift*c;

				planeTriangles.points.push_back(p);
			}
		}

		// insert polygon point cloud into Shape message
		pcl::transformPointCloud(current_point_cloud, current_point_cloud, planeTransXY.inverse());
		pcl::transformPointCloud(current_point_cloud, current_point_cloud, Eigen::Vector3f(a*planeShift, b*planeShift, c*planeShift), Eigen::Quaternion<float>(0,0,0,0));

		sensor_msgs::PointCloud2 cloud;
		pcl::toROSMsg(current_point_cloud, cloud);
		planeTrianglesSRS.back().points.push_back(cloud);
		planeTrianglesSRS.back().centroid.x = planeShift*a;
		planeTrianglesSRS.back().centroid.y = planeShift*b;
		planeTrianglesSRS.back().centroid.z = planeShift*c;
		planeTrianglesSRS.back().color = color;
		planeTriangles.color = color;
	}

	// compute centroid
}
Example #19
0
  std::vector<std::vector<Point3d> > computeTriangulation(const Point3dVector& vertices, const std::vector<std::vector<Point3d> >& holes, double tol)
  {
    std::vector<std::vector<Point3d> > result;

    // check input
    if (vertices.size () < 3){
      return result;
    }

    boost::optional<Vector3d> normal = getOutwardNormal(vertices);
    if (!normal || normal->z() > -0.999){
      return result;
    }

    for (const auto& hole : holes){
      normal = getOutwardNormal(hole);
      if (!normal || normal->z() > -0.999){
        return result;
      }
    }

    std::vector<Point3d> allPoints;

    // PolyPartition does not support holes which intersect the polygon or share an edge
    // if any hole is not fully contained we will use boost to remove all the holes
    bool polyPartitionHoles = true;
    for (const std::vector<Point3d>& hole : holes){
      if (!within(hole, vertices, tol)){
        // PolyPartition can't handle this
        polyPartitionHoles = false;
        break;
      }
    }

    if (!polyPartitionHoles){
      // use boost to do all the intersections
      std::vector<std::vector<Point3d> > allFaces = subtract(vertices, holes, tol);
      std::vector<std::vector<Point3d> > noHoles;
      for (const std::vector<Point3d>& face : allFaces){
        std::vector<std::vector<Point3d> > temp = computeTriangulation(face, noHoles);
        result.insert(result.end(), temp.begin(), temp.end());
      }
      return result;
    }

    // convert input to vector of TPPLPoly
    std::list<TPPLPoly> polys;

    TPPLPoly outerPoly; // must be counter-clockwise, input vertices are clockwise
    outerPoly.Init(vertices.size());
    outerPoly.SetHole(false);
    unsigned n = vertices.size();
    for(unsigned i = 0; i < n; ++i){

      // should all have zero z coordinate now
      double z = vertices[n-i-1].z();
      if (abs(z) > tol){
        LOG_FREE(Error, "utilities.geometry.computeTriangulation", "All points must be on z = 0 plane for triangulation methods");
        return result;
      }

      Point3d point = getCombinedPoint(vertices[n-i-1], allPoints, tol);
      outerPoly[i].x = point.x();
      outerPoly[i].y = point.y();
    }
    outerPoly.SetOrientation(TPPL_CCW);
    polys.push_back(outerPoly);


    for (const std::vector<Point3d>& holeVertices : holes){

      if (holeVertices.size () < 3){
        LOG_FREE(Error, "utilities.geometry.computeTriangulation", "Hole has fewer than 3 points, ignoring");
        continue;
      }

      TPPLPoly innerPoly; // must be clockwise, input vertices are clockwise
      innerPoly.Init(holeVertices.size());
      innerPoly.SetHole(true);
      //std::cout << "inner :";
      for(unsigned i = 0; i < holeVertices.size(); ++i){

        // should all have zero z coordinate now
        double z = holeVertices[i].z();
        if (abs(z) > tol){
          LOG_FREE(Error, "utilities.geometry.computeTriangulation", "All points must be on z = 0 plane for triangulation methods");
          return result;
        }

        Point3d point = getCombinedPoint(holeVertices[i], allPoints, tol);
        innerPoly[i].x = point.x();
        innerPoly[i].y = point.y();
      }
      innerPoly.SetOrientation(TPPL_CW);
      polys.push_back(innerPoly);
    }

    // do partitioning
    TPPLPartition pp;
    std::list<TPPLPoly> resultPolys;
    int test = pp.Triangulate_EC(&polys,&resultPolys);
    if (test == 0){
      test = pp.Triangulate_MONO(&polys, &resultPolys);
    }
    if (test == 0){
      LOG_FREE(Error, "utilities.geometry.computeTriangulation", "Failed to partition polygon");
      return result;
    }

    // convert back to vertices
    std::list<TPPLPoly>::iterator it, itend;
    //std::cout << "Start" << std::endl;
    for(it = resultPolys.begin(), itend = resultPolys.end(); it != itend; ++it){

      it->SetOrientation(TPPL_CW);

      std::vector<Point3d> triangle;
      for (long i = 0; i < it->GetNumPoints(); ++i){
        TPPLPoint point = it->GetPoint(i);
        triangle.push_back(Point3d(point.x, point.y, 0));
      }
      //std::cout << triangle << std::endl;
      result.push_back(triangle);
    }
    //std::cout << "End" << std::endl;

    return result;
  }
void
ShapeMarker::createMarker (visualization_msgs::InteractiveMarkerControl& im_ctrl)
{
  marker.id = shape_.id;

  marker.header = shape_.header;
  //std::cout << marker.header.frame_id << std::endl;
  //marker.header.stamp = ros::Time::now() ;

  marker.type = visualization_msgs::Marker::TRIANGLE_LIST;
  marker.ns = "shape visualization";
  marker.action = visualization_msgs::Marker::ADD;
  marker.lifetime = ros::Duration ();

  //set color
  marker.color.g = shape_.color.g;
  marker.color.b = shape_.color.b;
  marker.color.r = shape_.color.r;
  if (arrows_ || deleted_){
    marker.color.a = 0.5;
  }
  else
  {
    marker.color.a = shape_.color.a;
    //      marker.color.r = shape_.color.r;
  }

  //set scale
  marker.scale.x = 1;
  marker.scale.y = 1;
  marker.scale.z = 1;

  /* transform shape points to 2d and store 2d point in triangle list */
  TPPLPartition pp;
  list<TPPLPoly> polys, tri_list;

  Eigen::Vector3f v, normal, origin;

  if(shape_.type== cob_3d_mapping_msgs::Shape::CYLINDER)
  {
    cob_3d_mapping::Cylinder c;
    cob_3d_mapping::fromROSMsg (shape_, c);
    c.ParamsFromShapeMsg();
    // make trinagulated cylinder strip
    //transform cylinder in local coordinate system
    c.makeCyl2D();
    c.TransformContours(c.transform_from_world_to_plane);
    //c.transform2tf(c.transform_from_world_to_plane);
    //TODO: WATCH OUT NO HANDLING FOR MULTY CONTOUR CYLINDERS AND HOLES
    TPPLPoly poly;
    TPPLPoint pt;


    for(size_t j=0;j<c.contours.size();j++){

      poly.Init(c.contours[j].size());
      poly.SetHole (shape_.holes[j]);


      for(size_t i=0;i<c.contours[j].size();++i){

        pt.x=c.contours[j][i][0];
        pt.y=c.contours[j][i][1];

        poly[i]=pt;

      }
      if (shape_.holes[j])
        poly.SetOrientation (TPPL_CW);
      else
        poly.SetOrientation (TPPL_CCW);
      polys.push_back(poly);
    }
    // triangualtion itno monotone triangles
    pp.Triangulate_EC (&polys, &tri_list);

    transformation_inv_ = c.transform_from_world_to_plane.inverse();
    // optional refinement step
    list<TPPLPoly> refined_tri_list;
    triangle_refinement(tri_list,refined_tri_list);
    tri_list=refined_tri_list;

  }
  if(shape_.type== cob_3d_mapping_msgs::Shape::POLYGON)
  {
    cob_3d_mapping::Polygon p;

    if (shape_.params.size () == 4)
    {
      cob_3d_mapping::fromROSMsg (shape_, p);
      normal (0) = shape_.params[0];
      normal (1) = shape_.params[1];
      normal (2) = shape_.params[2];
      origin (0) = shape_.centroid.x;
      origin (1) = shape_.centroid.y;
      origin (2) = shape_.centroid.z;
      v = normal.unitOrthogonal ();

      pcl::getTransformationFromTwoUnitVectorsAndOrigin (v, normal, origin, transformation_);
      transformation_inv_ = transformation_.inverse ();
    }

    for (size_t i = 0; i < shape_.points.size (); i++)
    {
      pcl::PointCloud<pcl::PointXYZ> pc;
      TPPLPoly poly;
      pcl::fromROSMsg (shape_.points[i], pc);
      poly.Init (pc.points.size ());
      poly.SetHole (shape_.holes[i]);

      for (size_t j = 0; j < pc.points.size (); j++)
      {
        poly[j] = msgToPoint2D (pc[j]);
      }
      if (shape_.holes[i])
        poly.SetOrientation (TPPL_CW);
      else
        poly.SetOrientation (TPPL_CCW);

      polys.push_back (poly);
    }
    pp.Triangulate_EC (&polys, &tri_list);

  }//Polygon

  if(tri_list.size()==0)
  {
    ROS_WARN("Could not triangulate, will not display this shape! (ID: %d)", shape_.id);
  }
  //ROS_INFO(" creating markers for this shape.....");

  marker.points.resize (/*it->GetNumPoints ()*/tri_list.size()*3);
  TPPLPoint pt;
  int ctr=0;
  for (std::list<TPPLPoly>::iterator it = tri_list.begin (); it != tri_list.end (); it++)
  {

    //draw each triangle
    switch(shape_.type)
    {
      case(cob_3d_mapping_msgs::Shape::POLYGON):
      {
        for (long i = 0; i < it->GetNumPoints (); i++)
        {
          pt = it->GetPoint (i);
          marker.points[3*ctr+i].x = pt.x;
          marker.points[3*ctr+i].y = pt.y;
          marker.points[3*ctr+i].z = 0;
          //if(shape_.id == 39) std::cout << pt.x << "," << pt.y << std::endl;
        }
        //std::cout << marker.points.size() << std::endl;
      }
      case(cob_3d_mapping_msgs::Shape::CYLINDER):
      {
        for (long i = 0; i < it->GetNumPoints (); i++)
        {
          pt = it->GetPoint(i);

          //apply rerolling of cylinder analogous to cylinder class
          if(shape_.params.size()!=10){
            break;
          }

          double alpha=pt.x/shape_.params[9];


          marker.points[3*ctr+i].x = shape_.params[9]*sin(-alpha);
          marker.points[3*ctr+i].y = pt.y;
          marker.points[3*ctr+i].z = shape_.params[9]*cos(-alpha);

          ////Keep Cylinder flat - Debuging
          //marker.points[i].x = pt.x;
          //marker.points[i].y = pt.y;
          //marker.points[i].z = 0;
        }
      }
    }
    ctr++;
  }
  //set pose
  Eigen::Quaternionf quat (transformation_inv_.rotation ());
  Eigen::Vector3f trans (transformation_inv_.translation ());

  marker.pose.position.x = trans (0);
  marker.pose.position.y = trans (1);
  marker.pose.position.z = trans (2);

  marker.pose.orientation.x = quat.x ();
  marker.pose.orientation.y = quat.y ();
  marker.pose.orientation.z = quat.z ();
  marker.pose.orientation.w = quat.w ();

  im_ctrl.markers.push_back (marker);

  //  if(!arrows_) {
  // Added For displaying the arrows on Marker Position
  marker_.pose.position.x = marker.pose.position.x ;
  marker_.pose.position.y = marker.pose.position.y ;
  marker_.pose.position.z = marker.pose.position.z ;

  marker_.pose.orientation.x = marker.pose.orientation.x ;
  marker_.pose.orientation.y = marker.pose.orientation.y ;
  marker_.pose.orientation.z = marker.pose.orientation.z ;
  // end
}