예제 #1
0
int main()
{
    std::vector<Point_3> points;

    points.push_back(Point_3(2.0f, 3.535533905932738f, 3.535533905932737f));
    points.push_back(Point_3(4.0f, 2.0f, 0.0f));
    points.push_back(Point_3(0.0f, 2.0f, 0.0f));
    points.push_back(Point_3(1.0f, 0.0f, 0.0f));
    points.push_back(Point_3(4.0f, 1.414213562373095f, 1.414213562373095f));
    points.push_back(Point_3(0.0f, 1.414213562373095f, 1.414213562373095f));
    points.push_back(Point_3(3.0f, 0.0f, 0.0f));
    points.push_back(Point_3(2.0f, 5.0f, 0.0f));

    Polyhedron P;

    CGAL::convex_hull_3(points.begin(), points.end(), P);

    std::cout << "- Number of vertices  = " << P.size_of_vertices()    << std::endl;
    std::cout << "- Number of edges     = " << P.size_of_halfedges()/2 << std::endl;
    std::cout << "- Number of faces     = " << P.size_of_facets()      << std::endl;

    for ( Facet_iterator i = P.facets_begin(); i != P.facets_end(); ++i)
    {
        Halfedge_facet_circulator j = i->facet_begin();
        CGAL_assertion( CGAL::circulator_size(j) >= 3);
        std::cout << CGAL::circulator_size(j) << ' ';
        do{
            //std::cout << ' ' << std::distance(P.vertices_begin(), j->vertex());
            std::cout << " (" << j->vertex()->point().x() << ' ' << j->vertex()->point().y() << ' ' << j->vertex()->point().z() << ')' << ", ";
        } while ( ++j != i->facet_begin());

        std::cout << std::endl;
    }
    return 0;
}
void Polyhedron_demo_mesh_simplification_plugin::on_actionSimplify_triggered()
{
  const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex();
  
  Scene_polyhedron_item* item = 
    qobject_cast<Scene_polyhedron_item*>(scene->item(index));

  if(item)
  {
    Polyhedron* pMesh = item->polyhedron();

    // get option (#edges)
    bool ok;
  
    const int nb_edges = 
    QInputDialog::getInt(mw, tr("Stop condition"),
      tr("Number of edges:"),
      (int)(pMesh->size_of_halfedges () / 4), // default value: current #edges / 2 
      3, // min = one triangle
      (int)pMesh->size_of_halfedges(), // max #edges
      1, // step for the spinbox
      &ok);

    // check user cancellation
    if(!ok)
      return;

    // simplify
    QTime time;
    time.start();
    std::cout << "Simplify...";
    QApplication::setOverrideCursor(Qt::WaitCursor);
    namespace SMS = CGAL::Surface_mesh_simplification;
    SMS::Count_stop_predicate< Polyhedron > stop(nb_edges); // target #edges
    SMS::edge_collapse( *pMesh, stop,
                        CGAL::parameters::vertex_index_map(get(CGAL::vertex_external_index,*pMesh))
                                         .halfedge_index_map(get(CGAL::halfedge_external_index,*pMesh)));
    std::cout << "ok (" << time.elapsed() << " ms, " 
      << pMesh->size_of_halfedges() / 2 << " edges)" << std::endl;

    // update scene
    item->invalidate_buffers();
    scene->itemChanged(index);
    QApplication::restoreOverrideCursor();
  }
}
예제 #3
0
//------------------------------------------------------------------------------
//	Compute and store the results of dual graphs into appropriate variables
//
//  computeDual( mesh, whole, bary, mid ); 
//------------------------------------------------------------------------------
void computeDual( Polyhedron & poly, Graph & dual,
		  vector< Point3 > & bary, vector< Point3 > & mid )
{
    // initialize the array of face barycenters: refer to the point at which the gravitational forces exerted by 2 objects are equal

    bary.clear();
    bary.resize( poly.size_of_facets() );

    // initialize the dual graph with dual vertices
    dual.clear();
    int fid = 0;
    for ( Facet_iterator fi = poly.facets_begin(); fi != poly.facets_end(); ++fi ) {
	// add a vertex: each face equals to each dual vertex
	add_vertex( dual );
	bary[ fid++ ] = fi->center(); 
	// cerr << " Barycenter No. " << fid-1 << " : " << bary[ fid-1 ] << endl;
    }

    int size_of_edges = poly.size_of_halfedges() / 2; //redundant

    // initialize the array of midpoints
    mid.clear();
    mid.resize( size_of_edges );

    // initialize the array of lengths
    // length.clear();
    // length.resize( size_of_edges );

    // construct the connecitivity of the dual graph
    for ( Halfedge_iterator hi = poly.halfedges_begin(); hi != poly.halfedges_end(); ++hi ) {
	int origID = hi->facet()->id(); // the face
	int destID = hi->opposite()->facet()->id(); // the neighbor face
	Point3 origCoord = hi->vertex()->point();
	Point3 destCoord = hi->opposite()->vertex()->point();
	Vector3 dispVec = origCoord - destCoord;
	Point3 midCoord = destCoord + 0.5 * dispVec;
	// double curLength = sqrt( dispVec.squared_length() ); // the length between two connected vertices
#ifdef DEBUG
	cerr << origID << " -- " << destID << endl;
#endif	// DEBUG	
	
	if ( origID < destID )
		add_edge( origID, destID, hi->id(), dual );  
		
	mid[ hi->id() ] = midCoord;
	hi->mid() = hi->opposite()->mid() = midCoord;
	hi->weight() = hi->opposite()->weight() = 1.0;
    }
}
// a helper method for running different iterators
void running_iterators( Polyhedron& P) {
    if ( P.size_of_facets() == 0)
        return;

    std::size_t nv = P.size_of_vertices();

    std::cout << "The number of vertices in the Polyhedron: " << nv << std::endl;
    std::cout << "The number of facets in the Polyhedron: " << P.size_of_facets() << std::endl;
    std::cout << "The number of half edges in the Polyhedron: " << P.size_of_halfedges() << std::endl;

    std::cout << std:: endl;

    Polyhedron::Vertex_iterator last_v = P.vertices_end();
    -- last_v;  // the last of the old vertices

    Polyhedron::Edge_iterator last_e = P.edges_end();
    -- last_e;  // the last of the old edges

    Polyhedron::Facet_iterator last_f = P.facets_end();
    -- last_f;  // the last of the old facets

    int k = 0;
    Polyhedron::Facet_iterator f = P.facets_begin();

    do {
    	std::cout << "Printing a facet index: " << k++ <<  std::endl;

    	f->halfedge();

    } while ( f++ != last_f);

    std::cout  << std::endl;

    // -------------------------------------------------
    // traverse the vertices
    // -------------------------------------------------

    std::cout << "Printing the vertex indices: " << std::endl;

     int n=0;
     for (Polyhedron::Vertex_iterator vi = P.vertices_begin(); vi != P.vertices_end(); ++vi)
     {
    	 Kernel::Point_3 p;
    	 p = vi->point();
    	 std::cout << "Vertex index: "  << n++ << std::endl;
    	 std::cout << "p.x() = "  << p.x() << std::endl;
    	 std::cout << "p.y() = "  << p.y() << std::endl;
    	 std::cout << "p.z() = "  << p.z() << std::endl;

     }

     std::cout  << std::endl;

     // -------------------------------------------------
     // traverse the edges
     // -------------------------------------------------

     std::cout << "Iterating over the edges.... " << std::endl;

     n=0;
     for (Polyhedron::Edge_iterator ei = P.edges_begin(); ei != P.edges_end(); ++ei)
     {
    	 ei->next();
    	 Kernel::Point_3 p;
    	 p =  ei->vertex()->point();
    	 std::cout << "For edge index: " << n++ << std::endl;
    	 std::cout << "p.x() = "  << p.x() << std::endl;
		 std::cout << "p.y() = "  << p.y() << std::endl;
		 std::cout << "p.z() = "  << p.z() << std::endl;

     }
     std::cout  << std::endl;

	 // -----------------------------------------------
	 // Do something else with the edge iterators
	 // -----------------------------------------------

    Polyhedron::Edge_iterator e = P.edges_begin();
    ++ last_e; // make it the past-the-end position again

    while ( e != last_e) {
    	Polyhedron::Halfedge_handle h = e;
        ++e;
    };

    CGAL_postcondition( P.is_valid());
}
예제 #5
0
TrianglesList meshSimplification(TrianglesList &triangles, int stopPredicate) {

	#ifdef MESHSIMPLIFICATION_LOG
	CGAL::Timer timer;
	timer.start();
	#endif

	TrianglesList result;

	try
	{
		Polyhedron P;

		#ifdef MESHSIMPLIFICATION_LOG
		std::cout << "Start Building Polyhedron surface... " << std::endl;
		#endif

		Build_triangle_mesh_coherent_surface<HalfedgeDS> triangle(triangles);
		P.delegate(triangle);
		P.normalize_border();

		#ifdef MESHSIMPLIFICATION_LOG
		std::cout << "Completed Building Polyhedron surface:" << std::endl;
		std::cout << "Polyhedron is_pure_triangle: " << P.is_pure_triangle() << std::endl;
		std::cout << "Polyhedron is_closed: " << P.is_closed() << std::endl;
		std::cout << "Polyhedron is_pure_bivalent : " << P.is_pure_bivalent () << std::endl;
		std::cout << "Polyhedron is_pure_trivalent: " << P.is_pure_trivalent() << std::endl;
		std::cout << "Polyhedron is_valid 0: " << P.is_valid(false, 0) << std::endl;
		std::cout << "Polyhedron is_valid 1: " << P.is_valid(false, 1) << std::endl;
		std::cout << "Polyhedron is_valid 2: " << P.is_valid(false, 2) << std::endl;
		std::cout << "Polyhedron is_valid 3: " << P.is_valid(false, 3) << std::endl;
		std::cout << "Polyhedron is_valid 4: " << P.is_valid(false, 4) << std::endl;
		std::cout << "Polyhedron normalized_border_is_valid : " << P.normalized_border_is_valid(false) << std::endl;
		#endif

		#ifdef MESHSIMPLIFICATION_LOG
		std::cout << "Start edge_collapse... " << std::endl;
		#endif

		SMS::Count_stop_predicate<Polyhedron> stop(stopPredicate);

		int removedEdges = SMS::edge_collapse(P, stop,
				CGAL::vertex_index_map(boost::get(CGAL::vertex_external_index, P)).edge_index_map(boost::get(CGAL::edge_external_index ,P))
		);

		#ifdef MESHSIMPLIFICATION_LOG
		std::cout << "Completed edge_collapse:" << std::endl;
		std::cout << "Finished with: " << removedEdges << " edges removed and "  << (P.size_of_halfedges()/2) << " final edges." << std::endl;
		#endif

		//Build output result
		for ( Polyhedron::Facet_iterator fit( P.facets_begin() ), fend( P.facets_end() ); fit != fend; ++fit )
		{
			if ( fit->is_triangle() )
			{
				PointCGAL verts[3];
				int tick = 0;

				Polyhedron::Halfedge_around_facet_circulator hit( fit->facet_begin() ), hend( hit );
				do
				{
					if ( tick < 3 )
					{
						verts[tick++] = PointCGAL( hit->vertex()->point().x(), hit->vertex()->point().y(), hit->vertex()->point().z() );
					}
					else
					{
						std::cout << "meshSimplification: We've got facets with more than 3 vertices even though the facet reported to be triangular..." << std::endl;
					}

				} while( ++hit != hend );

				result.push_back( Triangle(verts[0], verts[1], verts[2]) );
			}
			else
			{
				std::cout << "meshSimplification: Skipping non-triangular facet" << std::endl;
			}

		}

	}
	catch (CGAL::Assertion_exception e)
	{
		std::cout << "ERROR: meshSimplification CGAL::Assertion_exception" << e.message() << std::endl;
	}

	#ifdef MESHSIMPLIFICATION_LOG
	timer.stop();
	std::cout << "meshSimplification result with: " << result.size() << " triangles." << std::endl;
	std::cout << "Total meshSimplification time: " << timer.time() << std::endl;
	#endif

	return result;
}
void mergeCoplanar(Polyhedron& p,bool step2) {
	int facetsBefore =  p.size_of_facets();
	
	p.normalize_border();
	if(!p.size_of_border_halfedges()) {
		// Calculate normals only once in advace! so all tris should be coplanar with the original
		std::transform( p.facets_begin(), p.facets_end(),p.planes_begin(),Plane_equation());			// Calculate plane equations (only works on tri<- = bs)=true
		bool coplanarFound = true;
		std::vector<Polyhedron::Halfedge_handle> skipHEs;
		while (coplanarFound) {			
			coplanarFound = false;																		// Set coplanarFound false
			int percCount = 1;
			for (Polyhedron::Halfedge_iterator hit = p.halfedges_begin(); hit != p.halfedges_end(); ++hit,++percCount){ // Loop through all halfedges
				if (is_coplanar(hit,true)){																// If coplanar and equals semantics
					Polyhedron::Halfedge_handle removeMe = hit;
					while (CGAL::circulator_size(removeMe->vertex_begin()) < 3)							// Mover handle to beginning of linestring
						removeMe = removeMe->next();
					
					bool jcnh = false;
					if (!step2) jcnh = joinCreatesNoHole (hit);
					else		jcnh = joinCreatesNoHole2(hit);
					if (jcnh){														// If no holes will be created

						std::cout << "\rFacets   before/after: "<<facetsBefore<<" -> "<< p.size_of_facets()<<". ("<<100*percCount/p.size_of_halfedges()<<"%)";

						while (CGAL::circulator_size(removeMe->opposite()->vertex_begin()) < 3)			// Join vertexes until at the other end of linestring
							if (removeMe->facet_degree()>3 && removeMe->opposite()->facet_degree()>3)
								removeMe = (p.join_vertex(removeMe))->next()->opposite();
							else																		// One of the faces turned into a triangle ->remove center vertex
								break;																	
						if (CGAL::circulator_size(removeMe->opposite()->vertex_begin()) < 3)			// Remove remained of the border
							p.erase_center_vertex(removeMe->opposite());								// if two segments remain remove center point
						else
							p.join_facet(removeMe);														// if one segment remains join facets
						coplanarFound = true;
						break;
					} else { // simplify border, but how to do this safely? not optimal solution implemented. Should do: add inward offseted point of intersection etc.
						if (std::find(skipHEs.begin(), skipHEs.end(),hit)!=skipHEs.end()) {					// Skip if hit in skipList
							while (CGAL::circulator_size(removeMe->opposite()->vertex_begin()) < 3)	{		// Join vertexes until at the other end of linestring
								if (removeMe->facet_degree()>3 && removeMe->opposite()->facet_degree()>3)
									if (triDoesNotIntersectFacet(removeMe))									// if tri reMe,reME->prev does not intersect left or right facet
										removeMe = (p.join_vertex(removeMe))->next()->opposite();			// remove removeME
									else {
										skipHEs.push_back(removeMe);
										skipHEs.push_back(removeMe->opposite());
										removeMe = removeMe->prev();										// move removeME one halfedge back
									}
								else break;																	// stop if only a triangle remains or at other end																
							}	
							skipHEs.push_back(removeMe);
							skipHEs.push_back(removeMe->opposite());
	}	}	}	}	}	}
	//if (!step2) mergeCoplanar(p,true);
	//else 
		std::cout << "\rFacets   before/after: "<<facetsBefore<<" -> "<< p.size_of_facets()<<". (100%)"<<std::endl;
}
void mergeColinear(Polyhedron& p) {
	int vertBefore =  p.size_of_vertices();
	bool colinearFound = true;
	while (colinearFound) {
		colinearFound = false; // Set temporarily to false, if merge degments then set true

		int percCount = 1;
		for (Polyhedron::Halfedge_iterator hit = p.halfedges_begin(); hit != p.halfedges_end(); ++hit,++percCount){
			if (CGAL::circulator_size(hit->vertex_begin()) == 1) {
				std::cerr << "WARNING: Loose edge, but how??"<<std::endl;
				while (CGAL::circulator_size(hit->vertex_begin()) == 1)
					hit = p.join_vertex(hit->opposite());
				break;
			}

			if ((CGAL::circulator_size(hit->vertex_begin()) == 2) &&			// if only two he connected to vertex
				(hit->facet_degree()>3 && hit->opposite()->facet_degree()>3)) { // if faces are not triangles // prob faster

				Vector_3 cur(hit->prev()->vertex()->point(),hit->vertex()->point());
				Vector_3 nex(hit->vertex()->point(),hit->next()->vertex()->point());
				if ( is_colinear(cur,nex)) {									// check if colinear
					std::cout << "\rVertices before/after: "<<vertBefore<<" -> "<< p.size_of_vertices()<<". ("<<100*percCount/p.size_of_halfedges()<<"%)";
					p.join_vertex(hit->opposite());								// move cur to prev point
					colinearFound = true;
					break;
	}	}	}	}
	std::cout << "\rVertices before/after: "<<vertBefore<<" -> "<< p.size_of_vertices()<<". (100%)" << std::endl;
}