Skip to content

Commit

Permalink
Merge branch 'segmentation' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
Pseudomanifold committed Aug 1, 2011
2 parents 73113bb + fae1b49 commit f5188bd
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 0 deletions.
201 changes: 201 additions & 0 deletions SegmentationAlgorithms/PlanarSegmentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* @brief Functions for the planar segmentation algorithm
*/

#include <list>
#include "PlanarSegmentation.h"

namespace psalm
Expand All @@ -25,6 +26,41 @@ mesh PlanarSegmentation::apply_to(mesh& input_mesh)
{
mesh res;

this->label_planar_vertices(input_mesh);
this->label_nonplanar_faces(input_mesh);
this->label_regions(input_mesh);

size_t cur_region = 0;
size_t written = 0;
do
{
for(size_t i = 0; i < input_mesh.num_vertices(); i++)
{
if(input_mesh.get_vertex(i)->region != std::numeric_limits<size_t>::max())
{
if(input_mesh.get_vertex(i)->region == cur_region)
{
written++;
std::cout << input_mesh.get_vertex(i)->get_position();
}
}
}

std::cout << "\n\n";

if(written == 0)
break;
else
{
cur_region++;
written = 0;
continue;
}
}
while(true);

return(res);

/*
* FIXME: This assumes that the vertex IDs are numbered
* sequentially. If this is not the case, the function will
Expand Down Expand Up @@ -72,4 +108,169 @@ mesh PlanarSegmentation::apply_to(mesh& input_mesh)
return(res);
}

/*!
* Labels all planar vertices of a given input mesh. The result of this
* function is stored locally within the class.
*
* @param input_mesh Mesh that is going to be labelled
*/

void PlanarSegmentation::label_planar_vertices(mesh& input_mesh)
{
planar_vertices.clear();
for(size_t i = 0; i < input_mesh.num_vertices(); i++)
{
vertex* v = input_mesh.get_vertex(i);
double curvature = v->calc_rms_curvature();

// TODO: This should use a user-definable threshold value for
// determining the necessary curvature...
if(curvature < 0.05)
planar_vertices.push_back(v);
else
nonplanar_vertices.push_back(v);
}
}

/*!
* Labels nonplanar faces of the given input mesh. A face is nonplanar if
* at least one of its vertices is nonplanar.
*
* @param input_mesh Mesh that is going to be labelled
*/

void PlanarSegmentation::label_nonplanar_faces(mesh& input_mesh)
{
nonplanar_faces.clear();
for(size_t i = 0; i < input_mesh.num_faces(); i++)
{
face* f = input_mesh.get_face(i);
for(size_t j = 0; j < f->num_vertices(); j++)
{
vertex* v = f->get_vertex(j);

// TODO: Lookup could be optimized by using maps or
// fixed-size arrays...
if(std::find(planar_vertices.begin(), planar_vertices.end(), v) == planar_vertices.end())
{
nonplanar_faces.push_back(f);
break;
}
}
}
}

/*!
* Labels different regions in the given input mesh. Essentially, this is
* a breadth-first-search that tries to reach vertices of nonplanar faces,
* starting with a given vertex of a nonplanar face. Only edges to other
* nonplanar faces are taken into account. Each face reached from the
* starting vertex gets assigned the same region.
*
* @param input_mesh Mesh whose regions are to be labelled
*/

void PlanarSegmentation::label_regions(mesh& input_mesh)
{
size_t cur_region = 0;
while(nonplanar_vertices.size() > 0)
{
std::list<vertex*> unprocessed_vertices;

vertex* v = nonplanar_vertices.front();
if(v->region != std::numeric_limits<size_t>::max())
{
nonplanar_vertices.erase(nonplanar_vertices.begin());
continue;
}

unprocessed_vertices.push_back(v);
while(unprocessed_vertices.size() > 0)
{
vertex* v = unprocessed_vertices.front();
v->region = cur_region;
std::vector<const vertex*> neighbours = v->get_neighbours();
for(size_t i = 0; i < neighbours.size(); i++)
{
vertex* w = const_cast<vertex*>(neighbours[i]);

// TODO: Optimize
if(std::find(planar_vertices.begin(), planar_vertices.end(), w) != planar_vertices.end())
{
// skip planar vertices -- only the
// nonplanar regions should be labelled
continue;
}

if(w->region == std::numeric_limits<size_t>::max())
{
w->region = cur_region;
unprocessed_vertices.push_back(w);
}
}

unprocessed_vertices.pop_front();
}

cur_region++;
nonplanar_vertices.erase(nonplanar_vertices.begin());
}
/*
std::list<vertex*> unprocessed_vertices;
while(nonplanar_faces.size() > 0)
{
face* f = nonplanar_faces.front();
for(size_t i = 0; i < f->num_vertices(); i++)
{
vertex* v = f->get_vertex(i);
// TODO: Optimize
if(std::find(planar_vertices.begin(), planar_vertices.end(), v) != planar_vertices.end())
{
// skip planar vertices -- only nonplanar
// regions should be labelled
continue;
}
// Check if vertex has been visited already
if(v->region == std::numeric_limits<size_t>::max())
{
v->region = cur_region;
unprocessed_vertices.push_back(v);
}
}
nonplanar_faces.erase(nonplanar_faces.begin());
while(unprocessed_vertices.size() > 0)
{
vertex* v = unprocessed_vertices.front();
std::vector<const vertex*> neighbours = v->get_neighbours();
for(size_t i = 0; i < neighbours.size(); i++)
{
vertex* w = const_cast<vertex*>(neighbours[i]);
// TODO: Optimize
if(std::find(planar_vertices.begin(), planar_vertices.end(), w) != planar_vertices.end())
{
// skip planar vertices -- only the
// nonplanar regions should be labelled
continue;
}
if(w->region == std::numeric_limits<size_t>::max())
{
w->region = cur_region;
unprocessed_vertices.push_back(w);
}
}
unprocessed_vertices.pop_front();
}
cur_region++;
}
*/
}

} // end of namespace "psalm"
9 changes: 9 additions & 0 deletions SegmentationAlgorithms/PlanarSegmentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ class PlanarSegmentation : public SegmentationAlgorithm
{
public:
mesh apply_to(mesh& input_mesh);

private:
void label_planar_vertices(mesh& input_mesh);
void label_nonplanar_faces(mesh& input_mesh);
void label_regions(mesh& input_mesh);

std::vector<vertex*> planar_vertices;
std::vector<vertex*> nonplanar_vertices;
std::vector<face*> nonplanar_faces;
};

} // end of namespace "psalm"
Expand Down
27 changes: 27 additions & 0 deletions vertex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ vertex::vertex()
boundary = false;
vertex_point = NULL;
id = std::numeric_limits<size_t>::max();
region = std::numeric_limits<size_t>::max();
scale_attribute = 0.0;

// FIXME: this->set(...) should be called here in order to avoid code
// duplication
}

/*!
Expand Down Expand Up @@ -85,6 +89,9 @@ void vertex::set(double x, double y, double z, double nx, double ny, double nz,
// Sensible default for any vertex. Negative values make no sense, as
// the scale attribute is composed of edge lengths.
scale_attribute = 0.0;

// By default, no region is assigned to the vertex
region = std::numeric_limits<size_t>::max();
}

/*!
Expand Down Expand Up @@ -722,4 +729,24 @@ double vertex::calc_gaussian_curvature() const
return(gaussian_curvature);
}

/*!
* Calculates the root mean square curvature around the vertex. This
* requires enumerating the 1-ring neighbourhood of the vertex.
*
* @return RMS curvature around the vertex
*/

double vertex::calc_rms_curvature() const
{
double H = this->calc_mean_curvature();
double K = this->calc_gaussian_curvature();

double squared_curvature = 4*H*H-2*K;
if(squared_curvature < 0)
return(0.0);
else
return(sqrt(squared_curvature));
}


} // end of namespace "psalm"
3 changes: 3 additions & 0 deletions vertex.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,14 @@ class vertex

double calc_mean_curvature() const;
double calc_gaussian_curvature() const;
double calc_rms_curvature() const;

double calc_voronoi_area() const;
double calc_mixed_area() const;
double calc_ring_area() const;

size_t region; // XXX: Identifies region the vertex belongs to

private:
std::vector<edge*> E;
std::vector<const face*> F;
Expand Down

0 comments on commit f5188bd

Please sign in to comment.